Error converting keras model to tfjs: duplicate weight name Variable - tensorflow

Follwing the tutorial at https://www.tensorflow.org/tutorials/images/hub_with_keras resulted in a file model.h5. Converting to tensorflow-js with the command
tensorflowjs_converter --input_format keras ./model.h5 /tmp/jsmodel/
failed with
Exception: Error dumping weights, duplicate weight name Variable
Why is this and how can it be fixed?
MCVE
from __future__ import absolute_import, division, print_function
import tensorflow as tf
import tensorflow_hub as hub
from tensorflow.keras import layers
import numpy as np
data_root = tf.keras.utils.get_file(
'flower_photos','https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
untar=True)
image_generator = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1/255)
IMAGE_SHAPE = (224, 224)
image_data = image_generator.flow_from_directory(str(data_root), target_size=IMAGE_SHAPE)
feature_extractor_url = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/2" ##param {type:"string"}
feature_extractor_layer = hub.KerasLayer(feature_extractor_url,
input_shape=(224,224,3))
for image_batch, label_batch in image_data:
print("Image batch shape: ", image_batch.shape)
print("Labe batch shape: ", label_batch.shape)
break
feature_extractor_layer.trainable = False
model = tf.keras.Sequential([
feature_extractor_layer,
layers.Dense(image_data.num_classes, activation='softmax')
])
model.compile(
optimizer=tf.keras.optimizers.Adam(),
loss='categorical_crossentropy',
metrics=['acc'])
steps_per_epoch = np.ceil(image_data.samples/image_data.batch_size)
history = model.fit(image_data, epochs=2,
steps_per_epoch=steps_per_epoch) # removed callback
model.save("/tmp/so_model.h5")
This fails with a
RuntimeError: Unable to create link (name already exists)
but the model is created. Calling the above tensorflowjs_converter --input_format keras /tmp/model.h5 /tmp/jsmodel fails with the above
Exception: Error dumping weights, duplicate weight name Variable
UPDATE: see also Retrain image detection with MobileNet

Related

AttributeError: Can't get attribute 'create_model' on <module '__main__'>

I have created a neural network model and created an ensemble learning model which is the voting model. I have combined a Neural network with random forest,and xgboost. Now I saved the model and try to load it to another Jupiter notebook but I get this error AttributeError: Can't get attribute 'create_model' on <module 'main'>
Here is the code to create the models and it in 1st notebook
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_val_score
import numpy
# Function to create model, required for KerasClassifier
def create_model(input_shape=66):
#x_shape= data_x.shape
#input_dim=x_shape[1]
# create model
model = Sequential()
model.add(Dense(12, input_dim=66, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1,activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
seed = 7
numpy.random.seed(seed)
Kc_model = KerasClassifier(
create_model, # Pass in function
input_shape=66, # Pass in the dimensions to above function
epochs=100,
batch_size=32,
verbose=False)
Kc_model._estimator_type = "classifier"
Kc_model.fit(x_train, y_train, epochs=100,batch_size=10)
rf = RandomForestClassifier(max_depth=15, random_state=0)
rf.fit(x_train,y_train)
rf_y_pred = rf.predict(x_test)
#Model Score
print("The accuracy score for Random Forest Classifier is")
print("Accuracy:{}%".format(round(metrics.accuracy_score(y_test, rf_y_pred)*100)))
print("Training:{}%".format(round(rf.score(x_train, y_train)*100)))
print("Test set: {}%".format(round(rf.score(x_test, y_test)*100)))
xgboost_model = XGBClassifier()
xgboost_model.fit(x_train, y_train)
xgboost_y_pred = xgboost_model.predict(x_test)
print("The accuracy score for Voting XGB Classifier is")
print("Accuracy:{}%".format(round(metrics.accuracy_score(y_test, xgboost_y_pred)*100)))
print("Training:{}%".format(round(xgboost_model.score(x_train, y_train)*100)))
print("Test set: {}%".format(round(xgboost_model.score(x_test, y_test)*100)))
from keras.wrappers.scikit_learn import KerasClassifier
import scikeras
from tensorflow import keras
voting = VotingClassifier(
estimators = [('rf',rf),('xgboost_model',xgboost_model),('Kc_model',Kc_model) ],
voting='soft')
#reshaping=y_test.reshape(2712,1)
voting_model =voting.fit(x_train, y_train)
voting_pred = voting_model.predict(x_test)
#Model Score
print("The accuracy score for Voting Classifier is")
print("Training:{}%".format(round(voting_model.score(x_train, y_train)*100)))
print("Test set: {}%".format(round(voting_model.score(x_test, y_test)*100)))
import pickle
# save
with open('voting_model.pkl','wb') as f:
pickle.dump(Kc_model,f)
In the second notebook that I try to load the model , I get an error as you can see below
import pickle
import pandas as pd
with open('voting_model.pkl', 'rb') as f:
Kc_model = pickle.load(f)
The reason this happens is that the keras.wrappers.scikit_learn.KerasClassifier wrapper cannot be pickled. The model building function is not saved. Instead, you should pickle the fitted model:
import pickle
# save
with open('voting_model.pkl','wb') as f:
pickle.dump(Kc_model.model, f)
Now, you can load your model and use it as you wish.
with open('voting_model.pkl', 'rb') as f:
model = pickle.load(f)
# Predict something.
model.predict(X_test)
However, if you need a KerasClassifier instance after loading then you should re-wrap it. Then, you also need to save the classes_ attribute. Finally, now the build function would return the loaded pickle:
# Save this as well.
with open('voting_model_classes.pkl', 'wb') as f:
pickle.dump(Kc_model.classes_, f)
import pickle
from keras.wrappers.scikit_learn import KerasClassifier
def load_model():
with open('voting_model.pkl', 'rb') as f:
return pickle.load(f)
def load_classes():
with open('voting_model_classes.pkl', 'rb') as f:
return pickle.load(f)
Kc_model = KerasClassifier(
load_model,
epochs=100,
batch_size=32,
verbose=False)
Kc_model._estimator_type = "classifier"
# We need to manually call it because it will only be called once the classifier is re-fitted.
Kc_model.model = load_model()
Kc_model.classes_ = load_classes()
# Now you can use Kc_model as KerasClassifier.
The error is expected: the model building function gets pickled by name, and that name doesn't exist in your new notebook.
You could try SciKeras which has an initialize method (docs) which you can call to restore stuff like classes_ if you choose to serialize your Keras model using SavedModel directly (SciKeras's KerasClassifier will gladly accept a model instance).

How do convert data type of Tensorflow Dataset [EMNIST/balanced] (From uint8 to float32)

I am using Tensorflow dataset "emnist/balanced". The data type of features value is uint8 by default. However, Tensorflow model accept only float values.
How can I convert the features and labels data type to float32.
The code is here:
#########################################################3
import tensorflow as tf
import tensorflow_datasets as tfds
datasets, info = tfds.load(name="emnist/balanced", with_info=True, as_supervised=True)
emnist_train, emnist_test = datasets['train'], datasets['test']
.
.
.
.
.
.
history = model.fit(emnist_train, epochs = 10)
#validation
test_loss, test_acc = model.evaluate(emnist_test, verbose=2)
print(test_acc)
Error --
2
3
----> 4 history = model.fit(emnist_train, epochs = 10)
5
6 #validation
TypeError: Value passed to parameter 'features' has DataType uint8 not in list of allowed values: float16, bfloat16, float32, float64
TypeError: Value passed to parameter 'features' has DataType uint8 not in list of allowed values: float16, bfloat16, float32, float64
Please refer working code to train a ANN for MNIST dataset
try:
# %tensorflow_version only exists in Colab.
%tensorflow_version 2.x
except Exception:
pass
from __future__ import absolute_import, division, print_function, unicode_literals
# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
print("T/F Version:",tf.__version__)
#### Import the Fashion MNIST dataset
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
##Scale these values to a range of 0 to 1 before feeding them to the neural network model
train_images = train_images / 255.0
test_images = test_images / 255.0
###Build the model
##the neural network requires configuring the layers of the model
##Set up the layers
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(10)
])
###Compile the model
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
###Train the model
##Feed the model
model.fit(train_images, train_labels, epochs=10)
###Evaluate accuracy
##compare how the model performs on the test dataset
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nTest accuracy:', test_acc)
output:
T/F Version: 2.1.0
Train accuracy:91.06
Test accuracy: 0.8871

load_model error: ValueError: Improperly formatted model config when tensorflow.keras

I can load the model with load_model("model.h5") in colab and do a model.predict which works. But when I download the h5 file and run load_model locally, the load_model call gets an error "ValueError: Improperly formatted model config."
This is the model:
base_model=MobileNet(weights='imagenet',include_top=False) #imports the mobilenet model and discards the last 1000 neuron layer.
x=base_model.output
x=GlobalAveragePooling2D()(x)
x=Dense(1024,activation='relu')(x) #we add dense layers so that the model can learn more complex functions and classify for better results.
x=Dense(1024,activation='relu')(x) #dense layer 2
x=Dense(512,activation='relu')(x) #dense layer 3
preds=Dense(2,activation='softmax')(x) #final layer with softmax activation
using transfer learning
model=Model(inputs=base_model.input,outputs=preds)
for layer in model.layers[:20]:
layer.trainable=False
for layer in model.layers[20:]:
layer.trainable=True
then trained
train_generator=train_datagen.flow_from_directory('/content/chest_xray/train/',
target_size=(224,224),
color_mode='rgb',
batch_size=32,
class_mode='categorical', shuffle=True)
model.compile(optimizer='Adam',loss='categorical_crossentropy',metrics=['accuracy'])
# Adam optimizer
# loss function will be categorical cross entropy
# evaluation metric will be accuracy
step_size_train=train_generator.n//train_generator.batch_size
model.fit_generator(generator=train_generator,
steps_per_epoch=step_size_train,
epochs=5)
model saved
model.save('chest-xray-pneumonia.h5')
prediction works
ill_path = "/content/chest_xray/train/PNEUMONIA/"
good_path = "/content/chest_xray/train/NORMAL/"
ill_pic = ill_path + os.listdir(ill_path)[1]
good_pic = good_path + os.listdir(good_path)[1]
print(get_rez(ill_pic))
print(get_rez(good_pic))
But locally running in a Flask app python script main.py, it doesn't
from flask import render_template, jsonify, Flask, redirect, url_for, request
from app import app
import random
import os
from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.mobilenet import preprocess_input, decode_predictions
import numpy as np
import ipdb
weightsPath = app.config['UPLOAD_FOLDER']
get error on the next line: ValueError: Improperly formatted model config.
new_model = load_model(os.path.join(app.config['UPLOAD_FOLDER'],"chest-xray-pneumonia.h5"))
def upload_file():
if request.method == 'POST':
f = request.files['file']
path = os.path.join(app.config['UPLOAD_FOLDER'], f.filename)
#f.save(os.path.join(app.config['UPLOAD_FOLDER'], f.filename))
ill_pic = os.path.join(app.config['UPLOAD_FOLDER'],
f.filename)
print(get_rez(ill_pic))

Keras,models.add() missing 1 required positional argument: 'layer'

I'm classifying digits of the MNIST dataset using a simple feed forward neural net with Keras. So I execute the code below.
import os
import tensorflow as tf
import keras
from keras.models import Sequential
from keras.layers import Dense, Activation
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('/tmp/data', one_hot=True)
# Path to Computation graphs
LOGDIR = './graphs_3'
# start session
sess = tf.Session()
#Hyperparameters
LEARNING_RATE = 0.01
BATCH_SIZE = 1000
EPOCHS = 10
# Layers
HL_1 = 1000
HL_2 = 500
# Other Parameters
INPUT_SIZE = 28*28
N_CLASSES = 10
model = Sequential
model.add(Dense(HL_1, input_dim=(INPUT_SIZE,), activation="relu"))
#model.add(Activation(activation="relu"))
model.add(Dense(HL_2, activation="relu"))
#model.add(Activation("relu"))
model.add(Dropout(rate=0.9))
model.add(Dense(N_CLASSES, activation="softmax"))
model.compile(
optimizer="Adam",
loss="categorical_crossentropy",
metrics=['accuracy'])
# one_hot_labels = keras.utils.to_categorical(labels, num_classes=10)
model.fit(
x=mnist.train.images,
y=mnist.train.labels,
epochs=EPOCHS,
batch_size=BATCH_SIZE)
score = model.evaluate(
x=mnist.test.images,
y=mnist.test.labels)
print("score = ", score)
However, I get the following error:
model.add(Dense(1000, input_dim=(INPUT_SIZE,), activation="relu"))
TypeError: add() missing 1 required positional argument: 'layer'
The syntax is exactly as shown in the keras docs. I am using keras 2.0.9, so I don't think it's a version control problem. Did I do something wrong?
It seems perfect indeed....
But I noticed you're not creating "an instance" of a sequential model, your using the class name instead:
#yours: model = Sequential
#correct:
model = Sequential()
Since the methods in a class are always declared containing self as the first argument, calling the methods without an instance will probably require the instance as the first argument (which is self).
The method's definition is def add(self,layer,...):

Keras model to Tensorflow to input b64 encoded data instead of numpy ml-engine predict

I am trying to convert a keras model to use it for predictions on google cloud's ml-engine. I have a pre-trained classifier that takes in a numpy array as input. The normal working data I send to model.predict is named input_data.
I convert it to base 64 and dump it to a json file using the following few lines:
data = {}
data['image_bytes'] = [{'b64':base64.b64encode(input_data.tostring())}]
with open('weights/keras/example.json', 'w') as outfile:
json.dump(data, outfile)
Now, I try to create the TF model from my existing model:
from keras.models import model_from_json
import tensorflow as tf
from keras import backend as K
from tensorflow.python.saved_model import builder as saved_model_builder
from tensorflow.python.saved_model import utils
from tensorflow.python.saved_model import tag_constants, signature_constants
from tensorflow.python.saved_model.signature_def_utils_impl import build_signature_def, predict_signature_def
init = tf.global_variables_initializer()
with tf.Session() as sess:
K.set_session(sess)
sess.run(init)
print("Keras model & weights loading...")
K.set_learning_phase(0)
with open(json_file_path, 'r') as file_handle:
model = model_from_json(file_handle.read())
model.load_weights(weight_file_path)
builder = saved_model_builder.SavedModelBuilder(export_path)
raw_byte_strings = tf.placeholder(dtype=tf.string, shape=[None], name='source')
decode = lambda raw_byte_str: tf.decode_raw(raw_byte_str, tf.float32)
input_images = tf.map_fn(decode, raw_byte_strings)
print(input_images)
signature = predict_signature_def(inputs={'image_bytes': input_images},
outputs={'output': model.output})
builder.add_meta_graph_and_variables(
sess=sess,
tags=[tag_constants.SERVING],
signature_def_map={
signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: signature
}
)
builder.save()
When I try to test this locally I get the following error:
ERROR:root:Exception during running the graph: You must feed a value for placeholder tensor 'input_1' with dtype float and shape [?,473,473,3]
[[Node: input_1 = Placeholder[dtype=DT_FLOAT, shape=[?,473,473,3], _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]
Help?