Usando un modelo Keras dentro de un estimador TF

Quiero usar uno de los modelos de keras precomstackdos (vgg, inicio, resnet, etc.) incluidos en tf.keras.application para la extracción de características para ahorrar tiempo de entrenamiento.

¿Cuál es la forma correcta de hacer esto dentro de una función de modelo de estimador?

Esto es lo que tengo actualmente.

 import tensorflow as tf def model_fn(features, labels, mode): # Import the pretrained model base_model = tf.keras.applications.InceptionV3( weights='imagenet', include_top=False, input_shape=(200,200,3) ) # get the output features from InceptionV3 resnet_features = base_model.predict(features['x']) # flatten and feed into dense layers pool2_flat = tf.layers.flatten(resnet_features) dense1 = tf.layers.dense(inputs=pool2_flat, units=5120, activation=tf.nn.relu) # ... Add in N number of dense layers depending on my application logits = tf.layers.dense(inputs=denseN, units=5) # Calculate Loss onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=5) loss = tf.losses.softmax_cross_entropy( onehot_labels=onehot_labels, logits=logits) optimizer = tf.train.AdamOptimizer(learning_rate=1e-3) train_op = optimizer.minimize( loss=loss, global_step=tf.train.get_global_step() ) return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op) if __name__ == "__main__": # import Xtrain and Ytrain classifier = tf.estimator.Estimator( model_fn=model_fn, model_dir="/tmp/conv_model") train_input_fn = tf.estimator.inputs.numpy_input_fn( x={'x': Xtrain}, y=Ytrain, batch_size=100, num_epochs=None, shuffle=True) classifier.train( input_fn=train_input_fn, steps=100) 

Sin embargo, este código arroja el error:

 TypeError: unsupported operand type(s) for /: 'Dimension' and 'float' 

en la línea resnet_features = base_model.predict(features['x'])

Creo que esto se debe a que el modelo keras está esperando una matriz numpy, pero el estimador está pasando en un tf.Tensor.

Entonces, ¿cuál es la forma correcta de usar un modelo de keras dentro de un estimador? Y, si no debe hacer esto, ¿cuál es la forma más sencilla de aprovechar un modelo pre-entrenado para la transferencia de aprendizaje en TF?

No tengo conocimiento de ningún método disponible que le permita crear un model_fn personalizado a model_fn de un modelo keras model_fn . Una forma más fácil es usar tf.keras.estimator.model_to_estimator()

 model = tf.keras.applications.ResNet50( input_shape=(224, 224, 3), include_top=False, pooling='avg', weights='imagenet') logits = tf.keras.layers.Dense(10, 'softmax')(model.layers[-1].output) model = tf.keras.models.Model(model.inputs, logits) model.compile('adam', 'categorical_crossentropy', ['accuracy']) # Convert Keras Model to tf.Estimator estimator = tf.keras.estimator.model_to_estimator(keras_model=model) estimator.train(input_fn=....) 

Sin embargo, si desea crear un model_fn personalizado para agregar más operaciones (p. Ej., Operaciones de resumen), puede escribir lo siguiente:

 import tensorflow as tf _INIT_WEIGHT = True def model_fn(features, labels, mode, params): global _INIT_WEIGHT # This is important, it allows keras model to update weights tf.keras.backend.set_learning_phase(mode == tf.estimator.ModeKeys.TRAIN) model = tf.keras.applications.MobileNet( input_tensor=features, include_top=False, pooling='avg', weights='imagenet' if _INIT_WEIGHT else None) # Only init weights on first run if _INIT_WEIGHT: _INIT_WEIGHT = False feature_map = model(features) logits = tf.keras.layers.Dense(units=params['num_classes'])(feature_map) # loss loss = tf.losses.softmax_cross_entropy(labels=labels, logits=logits) ... 

Solo puedes tener tensores en model_fn . Tal vez puedas probar algo como esto. Esto puede ser considerado como un hack. La mejor parte es que este código, aparte de proporcionar model_fn , también almacena los pesos del modelo cargado como un punto de control. Esto le ayuda a obtener los pesos cuando llama estimator.train(...) o estimator.evaluate(...) desde el punto de control.

 def model_fn(features, labels, mode): # Import the pretrained model base_model = tf.keras.applications.InceptionV3( weights='imagenet', include_top=False, input_shape=(200,200,3) ) # some check if not hasattr(m, 'optimizer'): raise ValueError( 'Given keras model has not been compiled yet. ' 'Please compile first ' 'before creating the estimator.') # get estimator object from model keras_estimator_obj = tf.keras.estimator.model_to_estimator( keras_model=base_model, model_dir=, config=, ) # pull model_fn that we need (hack) return keras_estimator_obj._model_fn