'tf' is not defined on load_model() - using lambda - python

I have a Keras model that I am trying to export and use in a different python code.
Here is my code:
from keras.models import Sequential
from keras.layers import Dense, Embedding, LSTM, GRU, Flatten, Dropout, Lambda
from keras.layers.embeddings import Embedding
import tensorflow as tf
EMBEDDING_DIM = 100
model = Sequential()
model.add(Embedding(vocab_size, 300, weights=[embedding_matrix], input_length=max_length, trainable=False))
model.add(Lambda(lambda x: tf.reduce_mean(x, axis=1)))
model.add(Dense(8, input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train_pad, y_train, batch_size=128, epochs=25, validation_data=(X_val_pad, y_val), verbose=2)
model.save('my_model.h5')
In another file, when I import my_model.h5 :
from keras.models import load_model
from keras.layers import Lambda
import tensorflow as tf
def learning(test_samples):
model = load_model('my_model.h5')
#ERROR HERE
#rest of the code
The error is the following:
in <lambda>
model.add(Lambda(lambda x: tf.reduce_mean(x, axis=1)))
NameError: name 'tf' is not defined
After research, I got that the fact that I used lambda in my model is the reason for this problem, but I added these references and it didn't help:
from keras.models import load_model
from keras.layers import Lambda
import tensorflow as tf
What could be the problem?
Thank you

When loading the model, you need to explicitly handle custom objects or custom layers (CTRL+f the docs for Handling custom layers):
import tensorflow as tf
import keras
model = keras.models.load_model('my_model.h5', custom_objects={'tf': tf})

It happened to me too. You need to import tensorflow inside your lambda function. So you probably want to put the code in a separate function:
def reduce_mean(x):
import tensorflow as tf
return tf.reduce_mean(x, axis=1)
model = Sequential()
model.add(Embedding(vocab_size, 300, weights=[embedding_matrix], input_length=max_length, trainable=False))
model.add(Lambda(reduce_mean))
model.add(Dense(8, input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train_pad, y_train, batch_size=128, epochs=25, validation_data=(X_val_pad, y_val), verbose=2)
model.save('my_model.h5')

Besides, when you try to load the model structure from a json file, passing custom objects solves the problem.
model = model_from_json(open("model_structure.json", "r").read(), custom_objects={'tf': tf})

One weird solution that has worked for me is to import the module used to create the model. So say you have file you use to create a model and save it.
make_model.py
from keras.models import Sequential
from keras.layers import Dense, Embedding, LSTM, GRU, Flatten, Dropout, Lambda
from keras.layers.embeddings import Embedding
import tensorflow as tf
EMBEDDING_DIM = 100
model = Sequential()
model.add(Embedding(vocab_size, 300, weights=[embedding_matrix], input_length=max_length, trainable=False))
model.add(Lambda(lambda x: tf.reduce_mean(x, axis=1)))
...
model.fit(X_train_pad, y_train, batch_size=128, epochs=25, validation_data=(X_val_pad, y_val), verbose=2)
model.save('my_model.h5')
If you load the model in another file load_model.py, you may be able to get around the error via import of the first module.
from keras.models import load_model
from keras.layers import Lambda
import tensorflow as tf
import make_model
def learning(test_samples):
model = load_model('my_model.h5')
This worked for me since the error read
UserWarning: make_model is not loaded, but a Lambda layer uses it. It may cause errors.
...
NameError: name 'tf' is not defined

Happened to me as well - however problem was that the code was refactored and the Lambda layer was replaced by something else. In this case, you can always rollback to the point where it worked.
The simple workaround in case you are not able to restore the previous solution is adding: custom_objects={'tf': tf} to restore_model call

Related

TypeError: object of type 'NoneType' has no len() when trying to fit a KerasCLassifier

I am trying to create a partial dependence plot for a neural network I created with keras. To archieve this I have to create a KerasClassifier or KerasRegressor. After having trouble with getting this working using this import:
from keras.wrappers.scikit_learn import KerasClassifier
I tried to use scikeras but with the following code
import numpy as np
import lime
import lime.lime_tabular
import matplotlib.pyplot as plt
df=pd.read_csv("heart.csv")
df.columns=["age", "sex", "chest_pain_type", "resting_blood_pressure", "cholesterol", "fasting_blood_sugar",
"resting_ecg", "max_heart_rate", "exercise_induced_angina", "st_depression", "st_slope",
"number_major_vessels", "thalassemia", "heart_attack"]
X=df.drop("heart_attack", axis=1).to_numpy()
y=df["heart_attack"].to_numpy()
from sklearn.model_selection import train_test_split
import keras
from keras.layers import Dense, Dropout, BatchNormalization
from keras.models import Sequential
from keras.callbacks import EarlyStopping
from scikeras.wrappers import KerasClassifier
def split_data(X, y):
return train_test_split(X, y, train_size=0.8, random_state=10)
# KerasClassifier for PDP
###############################################################################
def create_model_classifier():
model=Sequential()
model.add(BatchNormalization())
model.add(Dense(70, activation="relu", input_shape=(13,)))
model.add(Dense(70, activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(70, activation="relu"))
model.add(Dense(70, activation="relu"))
model.add(Dense(1,activation="sigmoid"))
opt=keras.optimizers.Adam(learning_rate=0.0001)
model.compile(optimizer=opt, loss="binary_crossentropy", metrics=["accuracy", keras.metrics.FalseNegatives(), keras.metrics.FalsePositives()])
return model
X_train, X_test, y_train, y_test=split_data(X, y)
model_reg = KerasClassifier(model=create_model_classifier)
early_stopping=EarlyStopping(monitor="val_loss", patience=10, verbose=0, mode="auto")
history=model_reg.fit(
X_train,
y_train,
epochs=500,
batch_size=32,
shuffle=True,
validation_data=(X_test, y_test),
callbacks=[early_stopping]
)
I get this Errorcode:
Traceback (most recent call last):
File "C:\Users\Leonard\Desktop\X AI - Heart Attacks\main.py", line 95, in <module>
history=model_reg.fit(
File "C:\Users\Leonard\anaconda3\lib\site-packages\scikeras\wrappers.py", line 1416, in fit
super().fit(X=X, y=y, sample_weight=sample_weight, **kwargs)
File "C:\Users\Leonard\anaconda3\lib\site-packages\scikeras\wrappers.py", line 747, in fit
self._fit(
File "C:\Users\Leonard\anaconda3\lib\site-packages\scikeras\wrappers.py", line 866, in _fit
self._check_model_compatibility(y)
File "C:\Users\Leonard\anaconda3\lib\site-packages\scikeras\wrappers.py", line 536, in _check_model_compatibility
if self.n_outputs_expected_ != len(self.model_.outputs):
TypeError: object of type 'NoneType' has no len()
And a few warnings because of the parameters in my fit method which don't seem to be the problem. I also get this error even if I only have X_train and y_train in my fit method.
To fix the issue, you need to specify the parameter input_dim in the input layer. Therefore if your X has 13 columns, change your first layer from
model.add(Dense(70, activation="relu", input_shape=(13,)))
to
model.add(Dense(70, activation="relu", input_dim=13))
and it should work
scikeras.wrappers.KerasClassifier is different from keras.wrappers.scikit_learn.KerasClassifier. It requires a tf.keras.Model, which has a different syntax.
Below is just an example
import tensorflow as tf
def create_model_classifier():
inputs = tf.keras.Input(shape=(13,))
x = tf.keras.layers.Dense(70, activation=tf.nn.relu)(inputs)
outputs = tf.keras.layers.Dense(70, activation=tf.nn.relu)(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
return model
Documentation:
https://scikeras.readthedocs.io/en/latest/generated/scikeras.wrappers.KerasClassifier.html
SciKeras supports Sequential models.
The issue seems to be that the batch norm layer messes with the the tf.keras.Model.outputs attribute. I think it's supposed to go after your input.
Here's a minimal reproducible example:
import numpy as np
X = np.ones((100,1))
y = np.zeros((100,))
from keras.layers import Dense, BatchNormalization
from keras.models import Sequential
from scikeras.wrappers import KerasClassifier
def create_model_classifier():
model=Sequential()
model.add(BatchNormalization())
model.add(Dense(1, activation="relu", input_shape=(1,)))
model.add(Dense(1,activation="sigmoid"))
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
return model
model_reg = KerasClassifier(model=create_model_classifier)
model_reg.fit(X, y)
Comment out or move your BatchNormalization layer after your input layer and it should work (the latter is probably what you want).
Also, you should be using import tensorflow.keras ... not import keras ....

Keras Tuner - Model-building function did not return a valid Keras Model instance

I'm trying to search Hyperparameters for a model using Keras Tuner, but I'm getting this error when I run the code: "RuntimeError: Model-building function did not return a valid Keras Model instance, found < keras.engine.sequential.Sequential object at 0x000001E9C2903F28 >"
I've searched on Internet but didn't found anything that could help, also I've followed the tutorial in the Keras Tuner gitHub page (https://github.com/keras-team/keras-tuner), but it dind't work either.
Here is my code:
class MyHyperModel(HyperModel):
def __init__(self, num_classes):
self.num_classes = num_classes
def build(self, hp):
model=Sequential()
model.add(Dense(units=hp.Int('units_0', 30, 900, step=30),
activation=hp.Choice('act_0', ['relu', 'tanh']),
input_dim=12))
for i in range(hp.Int('layers', 3, 9)):
model.add(Dense(units=hp.Int('units_' + str(i), 30, 900, step=30),
activation=hp.Choice('act_' + str(i), ['relu', 'tanh'])))
model.add(Dense(6, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer=hp.Choice('optimizer', ['adam', 'sgd']),
metrics=['categorical_accuracy'])
return model
hypermodel = MyHyperModel(num_classes=6)
tuner = kt.tuners.bayesian.BayesianOptimization(
hypermodel,
objective='val_accuracy',
max_trials=5,
executions_per_trial=3,
seed=(np.random.seed(1)),
directory='Tests',
project_name='test')
tuner.search_space_summary()
tuner.search(data[:200], labels[:200],
verbose=2,
epochs=3,
validation_data=(data[200:], labels[200:]))
models = tuner.get_best_models(num_models=2).summary()
tuner.get_best_hyperparameters()[0].values
tuner.results_summary()
data is an list of 300 vector with 12 values and on labels there are 6 classes which was converted to tensor with the function tensorflow.convert_to_tensor().
I appreciate any help.
If you import module members from keras, you must import from tensorflow.keras instead of keras. For example, if you write:
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from keras.optimizers import Adam
Then change them to:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation, Dropout
from tensorflow.keras.optimizers import Adam
I know what's wrong and is not the code, my model have 6 neurons on the last layer and I've used the loss as 'categorical_crossentropy', but this only works when the labels are 0 and 1, so I've changed the loss to 'sparse_categorical_crossentropy' and metrics to 'accuracy' and it worked.
Thanks everyone for the reply, I appreciate the help.

How to get weights from tensorflow fully_connected with Google Colab

I'm trying to extract the weights from a model after training it. Here's a code.
1- how to save the model in the previously uploaded directory path?
2. how to get weights?
3. I have some csv file as the same used for modeling but without class. how can I estimate the classes with this model?
# Preprocess
import pandas as pd
import keras
from sklearn.model_selection import train_test_split
# Prepare data
churn = pd.read_csv('Churn_Modelling3.csv')
# split data into train and test sets
x_train, x_test, y_train, y_test = train_test_split(churn.iloc[:,0:10],churn.iloc[:, 10], test_size=0.2)
# Create a Model
import tensorflow as tf
from keras.models import Sequential
from keras.layers import Dense
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPool2D
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense
model = Sequential()
# Input layer
model.add(Dense(32, activation=tf.nn.sigmoid,input_dim=x_train.shape[1]))
# Hidden layers
model.add(Dense(64, activation=tf.nn.sigmoid))
model.add(Dense(32, activation=tf.nn.sigmoid))
# Output layer
model.add(Dense(1, activation=tf.nn.sigmoid))
# Compile the Model
from keras.optimizers import SGD
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile( optimizer= 'sgd', loss='binary_crossentropy', metrics=['accuracy'])
# Fit the model
history = model.fit(x_train, y_train, epochs=20, batch_size=128,validation_data=(x_test, y_test))
# ٍEvaluate the Model
score = model.evaluate(x_test, y_test, batch_size=128)
How to save the model in the previously uploaded directory path? => You can use any of the below commands,
`model.save_weights('./Weights/Weights')` or
`tf.keras.experimental.export_saved_model` or
`model.save`
How to get weights? => We can Load the Weights using any of the below commands:
model.load_weights('my_model_weights.h5') or
keras.models.load_model('my_model.h5') or
tf.keras.experimental.load_from_saved_model
I have some csv file as the same used for modeling but without class. how can I estimate the classes with this model? => One of the ways to do it is to iterate the below code for each instance of CSV data Label.
ynew = model.predict(Xnew)
Fore more information, you can refer to the below links:
https://www.tensorflow.org/tutorials/keras/save_and_restore_models
https://www.tensorflow.org/guide/saved_model
https://www.tensorflow.org/api_docs/python/tf/keras/Model

tensorboard ModuleNotFoundError when initialising function

Even though Ive tried to initialise Tensorboard several ways - from tensorflow.keras.callbacks import TensorBoard , from keras.callbacks import TensorBoard , atd. when initialising right before model.fit function I always get ModuleNotFoundError or similar.
I've tried several different directories for Tensorboard logs, several ways to initialize via Keras layer
import tensorflow as tf
#sess = tf.Session()
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D
# more info on callbakcs: https://keras.io/callbacks/ model saver is cool too.
#from tensorflow.keras.callbacks import TensorBoard
from keras.callbacks import TensorBoard
import pickle
import time
NAME = "Cats-vs-dogs-CNN"
pickle_in = open("X.pickle","rb")
X = pickle.load(pickle_in)
pickle_in = open("y.pickle","rb")
y = pickle.load(pickle_in)
X = X/255.0
model = Sequential()
model.add(Conv2D(256, (3, 3), input_shape=X.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(256, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'],
)
tensor_board = TensorBoard(log_dir='./Graph', histogram_freq=0, write_graph=True, write_images=True)
model.fit(X, y,
batch_size=16,
epochs=1,
validation_split=0.3,
callbacks=[tensor_board])
Its based on tutorial https://pythonprogramming.net/tensorboard-analysis-deep-learning-python-tensorflow-keras/?completed=/convolutional-neural-network-deep-learning-python-tensorflow-keras/
Original code was written like this:
tensorboard = TensorBoard(log_dir="logs/{}".format(NAME))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'],
)
model.fit(X, y,
batch_size=32,
epochs=10,
validation_split=0.3,
callbacks=[tensorboard])
But I was getting an error that callbacks=[tensorboard]) is not found so I've kinda deducted it is because I use Tensorflow2.0 and this is based on r1 version.
Dave,
You have to use
tensorflow.keras.callbacks.TensorBoard
you are using directly keras api, like you try to use two different APIs.
Please try to follow the documentation of tf 2.0 api, it works well.
https://www.tensorflow.org/tensorboard/r2/get_started

Unable to add two layers in Keras of Tensorflow

I have a simple regression model as below. The layers layer_abc and layer_efg both have (None, 5) as output, so their output have same dimension and can be added. Thus I want to unhide the code #keras.layers.Add()(['layer_abc', 'layer_efg']). But whenever I do this, I got an error AttributeError: 'str' object has no attribute 'get_shape'. If I didn't unhide this line, then the code is fine.
How can I add the two layers without having error? Many thanks!
from __future__ import absolute_import, division, print_function
from scipy import misc
import tensorflow as tf
from tensorflow import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D, BatchNormalization, Activation
import numpy as np
import matplotlib.pyplot as plt
train_images=np.array([[[0],[1],[2]],[[0],[0],[2]],[[1],[1],[1]],[[1],[0],[1]]])
train_labels=np.array([[1],[0],[1],[0]])
model = keras.Sequential([
keras.layers.Flatten(input_shape=(3, 1)),
keras.layers.Dense(5, activation=tf.nn.relu,name='layer_abc'),
keras.layers.Dense(5, activation=tf.nn.relu,name='layer_efg'),
#keras.layers.Add()(['layer_abc', 'layer_efg']),
keras.layers.Dense(1, activation=tf.nn.softmax),
])
model.compile(optimizer='adam',
loss='mean_squared_error',
metrics=['accuracy','mean_squared_error'])
print(model.summary())
model.fit(train_images, train_labels, epochs=2)
You can use the functional API like this to do the Add, for single output between 0 and 1, use the sigmoid activation for the output:
input = keras.layers.Input((3,1))
x1 = keras.layers.Dense(5, activation=tf.nn.relu, name='layer_abc')(input)
x2 = keras.layers.Dense(5, activation=tf.nn.relu, name='layer_efg')(input)
x = keras.layers.Add()([x1, x2])
x = keras.layers.Flatten()(x)
output = keras.layers.Dense(1, activation=tf.nn.sigmoid)(x)
model = keras.models.Model(input, output)
This might work:
model = keras.Sequential([
keras.layers.Flatten(input_shape=(3, 1)),
keras.layers.Dense(5, activation=tf.nn.relu,name='layer_abc'),
keras.layers.Dense(5, activation=tf.nn.relu,name='layer_efg')])
model.add(keras.layers.Lambda(lambda x: tf.add(model.layers[1].output, x)))
model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid))

Categories