Hey guys, I tried this tensorflow tutorials which use Keras API and tf hub image feature vector to custom model. When I try to save the model at the end, using
model.save('my_model.h5')
instead of
tf.contrib.saved_model.save_keras_model(model, "./saved_models")
error came out as
FailedPreconditionError (see above for traceback): Error while reading resource variable module/MobilenetV2/expanded_conv_9/project/weights from Container: localhost. This could mean that the variable was uninitialized. Not found: Resource localhost/module/MobilenetV2/expanded_conv_9/project/weights/class tensorflow::Var does not exist.
Then I use session to reinitialize
sess = tf.keras.backend.get_session()
init = tf.global_variables_initializer()
sess.run(init)
The model successfully saved, but when I reload this .h5 file. I found that I need to import tf hub and specify the url. Then I tried saved model to serve. Both .h5 model and saved model get random result. How can I fix this?
Hi,
a couple of questions:
tf.contrib.saved_model.save_keras_model is the way to go. Is there any special reason why you are trying to save as .h5?@vbardiovskyg
Thank you for your reply.
The reason why I want to save .h5 model is to load model simply. I'm learning tensorflow, and this way is more familiar to me. At first, I just want to have a try.
I'm trying to build a classifier using tf hub mobilenet image feature vector.
There are more details about random result. Without run initialization code agian init = tf.global_variables_initializer()to save a h5 model, error will occur. And I found once I run init = tf.global_variables_initializer(), prediction will become random. It looks like [0.56666, 0.76111, ....], and before init = tf.global_variables_initializer() the prediction will be [0.99999, 0.00001, ....].
Before I save, I use this code to train a model.
````
module = hub.Module(MODEL_PATH)
def feature_vector(x)
return module(x)
IMAGE_SIZE = hub.get_expected_image_size(hub.Module(MODEL_PATH))
feature_vector_layer = tf.keras.layers.Lambda(feature_vector, input_shape=IMAGE_SIZE + [3])
feature_vector_layer.trainable = False
model = tf.keras.Sequential([
feature_vector_layer,
tf.keras.layers.Dense(1024, activation='relu'),
tf.keras.layers.Dense(20, activation='sigmoid')
])
model.compile(loss=tf.keras.losses.binary_crossentropy,
optimizer='adam')
model.summary()
sess = tf.keras.backend.get_session()
init = tf.global_variables_initializer()
sess.run(init)
history = model.fit(
train_dataset,
validation_data=val_dataset,
steps_per_epoch=int(np.ceil(len(x_train_files) / float(batch_size))),
epochs=epochs,
validation_steps=int(np.ceil(len(x_val_files) / float(batch_size))),
)
to save a .h5 model, I use
sess.run(init)
model.save('my_model.h5')
About saved model. I need a model including image prepossess to string to float.
I first usetf.contrib.saved_model.save_keras_modelto export saved model. In this situation, I don't need to rerunsess.run(init)
And I run code below to adjust model
graph = tf.Graph()
with tf.Session(graph=graph) as sess:
tf.saved_model.loader.load(sess, [tag_constants.SERVING], input_dir)
string_inp = tf.placeholder(tf.string, shape=(None,), name="b64")
img_float = str_proccess(string_inp)
out, = tf.import_graph_def(graph.as_graph_def(),
input_map={'lambda_input:0': img_float},
return_elements=["dense_1/Sigmoid:0"])
sess.run([tf.global_variables_initializer(), tf.tables_initializer()])
builder = tf.saved_model.builder.SavedModelBuilder(export_dir)
signature = tf.saved_model.predict_signature_def(inputs={'input': string_inp},
outputs={"prediction": out})
builder.add_meta_graph_and_variables(sess=sess,
tags=[tag_constants.SERVING],
signature_def_map={'serving_default': signature},
legacy_init_op=tf.tables_initializer())
builder.save()
Please notice that this code also include sess.run([tf.global_variables_initializer(), tf.tables_initializer()])````, without this, error will occur. And prediction result looks like [0.4566, 0.5343, ....] which should be [0.99999, 0.00001, ....]
I'm not very familiar with saved model, and I don't know whether this code is right.
Thanks for the explanation.
The solution is to use
tf.keras.experimental.export_saved_model(model, export_path) for saving and
tf.keras.experimental.load_from_saved_model(export_path, custom_objects={'KerasLayer':hub.KerasLayer}) for restoring.
Then you can just call loaded_model.predict()
@vbardiovskyg
Thanks for reply. I'm using tensorflow 1.13, which may not have this method.
AttributeError: module 'tensorflow._api.v1.keras.experimental' has no attribute 'export_saved_model'
I found another solution :
instead of using Lambda
````
def feature_vector(x):
return module(x)
IMAGE_SIZE = hub.get_expected_image_size(hub.Module(MODEL_PATH))
feature_vector_layer = tf.keras.layers.Lambda(feature_vector, input_shape=IMAGE_SIZE + [3])
feature_vector_layer.trainable = False
model = tf.keras.Sequential([
feature_vector_layer,
tf.keras.layers.Dense(1024, activation='relu'),
tf.keras.layers.Dense(20, activation='sigmoid')
])
use inheritance layer like this
class FeatureLayer(tf.layers.Layer):
def __init__(self, kwargs):
self.trainable = False
super(FeatureLayer, self).__init__(kwargs)
def build(self, input_shape):
self.feature_vector = hub.Module(
MODEL_PATH,
trainable=self.trainable,
name="{}_module".format(self.name)
)
super(FeatureLayer, self).build(input_shape)
def call(self, inputs):
results = self.feature_vector(inputs=inputs)
return results
fv_input = tf.keras.layers.Input(shape=(224, 224, 3))
fv_output = FeatureLayer()(fv_input)
x = tf.keras.layers.Dense(1024, activation='relu')(fv_output)
x = tf.keras.layers.Dense(20, activation='sigmoid')(x)
model = tf.keras.Model(fv_input, x)
````
The .h5 model save won't came out error and both .h5 model and saved model return correct result.
I do not know why this way works.
@HFrost0 ,
Please confirm if your issue has been resolved, or if you still need any clarifications with respect to this issue.
Any update to this? The model save and load process for tf version 1.12 and 1.13 are completely broken when using tf.keras which is meant to be the direction of the overall tensorflow project.
@HFrost0 I can certainly use your model construction instead of the lambda one but when using # new_model = tf.keras.models.load_model('my_new_model.h5',custom_objects={'FeatureLayer': FeatureLayer()})
it still produces random output. Can you give me a full example of how you predicted as well? Thanks!
Hi, @ingramator
I still get random result with .h5 model when I reload. I'm not quite sure what's wrong with it, it seems like varibles in session are not saved or reloaded. But I get correct result by saving my model by saved model using
````
version = 5
export_path = os.path.join('classifier', str(version))
tf.saved_model.simple_save(
tf.keras.backend.get_session(),
export_path,
inputs={'input_image': string_inp},
outputs={'predictions': output})
````
@HFrost0 I seem to be able to save it that way but what is the process for running inference on a sample image. There seems to be next to no documentation on the tensorflow API docs once again
@arnoegw ,
Can you PTAL
Thanks for the explanation.
The solution is to use
tf.keras.experimental.export_saved_model(model, export_path)for saving and
tf.keras.experimental.load_from_saved_model(export_path, custom_objects={'KerasLayer':hub.KerasLayer})for restoring.Then you can just call
loaded_model.predict()
hey when i use this i get AttributeError: module 'tensorflow.keras.experimental' has no attribute 'export_saved_model'
Most helpful comment
hey when i use this i get AttributeError: module 'tensorflow.keras.experimental' has no attribute 'export_saved_model'