save signature of keras multi input Model with predict_signature_def - python-3.x

I am building a multi input model in the following way (simplified model)
model_heads = []
input1 = Input(shape=(batch_input_shape[1], batch_input_shape[2]))
input2 = Input(shape=(batch_input_shape[1], batch_input_shape[2]))
inputs = [input1, input2]
model_layer = Conv1D(filters=8, kernel_size=2, padding='causal', dilation_rate=1, activation='relu', input_shape=(batch_input_shape[1], batch_input_shape[2]), kernel_initializer='he_normal')(inputs[0])
model_layer = MaxPooling1D(2)(model_layer)
model_heads.append(model_layer)
model_layer = Conv1D(filters=16, kernel_size=4, padding='causal', dilation_rate=1, activation='relu', input_shape=(batch_input_shape[1], batch_input_shape[2]), kernel_initializer='he_normal')(inputs[1])
model_layer = MaxPooling1D(4)(model_layer)
model_heads.append(model_layer)
flat_out = []
for j in model_heads:
flat_out.append(Flatten()(j))
merged = concatenate(flat_out)
merged = Dense(100, activation=self.activation)(merged)
self.model = Model(inputs=inputs, outputs=output)
self.model.compile(loss='binary_crossentropy', optimizer=self.opt, metrics=['accuracy'])
I feed the input and run training with runs fine, but then I save the model like so:
builder = tf.saved_model.builder.SavedModelBuilder(persistencydir + '/saved.' + str(start_prediction) + "." + str(end_prediction))
signature = tf.saved_model.signature_def_utils.predict_signature_def(inputs={'the_input': self.model.input}, outputs={'the_output': self.model.output})
builder.add_meta_graph_and_variables(sess, [tf.saved_model.tag_constants.SERVING], signature_def_map={tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: signature})
builder.save()
This of course complains because predict_signature_def expects a tensor for inputs but receives a python list instead:
File "/home/myname/myutils/anaconda3/envs/tmp_merge/lib/python3.6/site-packages/tensorflow/python/saved_model/signature_def_utils_impl.py", line 205, in predict_signature_def
for key, tensor in inputs.items()}
File "/home/myname/myutils/anaconda3/envs/tmp_merge/lib/python3.6/site-packages/tensorflow/python/saved_model/signature_def_utils_impl.py", line 205, in <dictcomp>
for key, tensor in inputs.items()}
File "/home/myname/myutils/anaconda3/envs/tmp_merge/lib/python3.6/site-packages/tensorflow/python/util/deprecation.py", line 324, in new_func
return func(*args, **kwargs)
File "/home/myname/myutils/anaconda3/envs/tmp_merge/lib/python3.6/site-packages/tensorflow/python/saved_model/utils_impl.py", line 58, in build_tensor_info
dtype=dtypes.as_dtype(tensor.dtype).as_datatype_enum,
AttributeError: 'list' object has no attribute 'dtype'
Is there another way I can save the signature?
Alternatively is it possible to build a Model with multi input using a single Tensor composed of the original inputs (input1 and input2 in my example). All examples I've seen are similar to what I have here, but I haven't found an example that also saves the signature...

Based on here: https://github.com/tensorflow/tensorflow/issues/39568#issuecomment-631120656, you can do:
signature = tf.saved_model.predict_signature_def(
inputs = {'input1':x1,'input2':x2},
outputs = {'output1':y1,'output2':y2})

Related

Problem using tf.keras.utils.timeseries_dataset_from_array in Functional Keras API

I am working on building a LSTM model on M5 Forecasting Challenge (a Kaggle dataset)
I using functional keras API to build my model. I have attached picture of my model. Input is generated using 'tf.keras.utils.timeseries_dataset_from_array' and the error I receive is
ValueError: Layer "model_4" expects 18 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, None, 18) dtype=float32>]
This is the code I am using to generate a time series dataset.
dataset = tf.keras.utils.timeseries_dataset_from_array(data=array, targets=None,
sequence_length=window, sequence_stride=1, batch_size=32)
My NN model
input_tensors = {}
for col in train_sel.columns:
if col in cat_cols:
input_tensors[col] = layers.Input(name = col, shape=(1,),dtype=tf.string)
else:
input_tensors[col]=layers.Input(name = col, shape=(1,), dtype = tf.float16
embedding = []
for feature in input_tensors:
if feature in cat_cols:
embed = layers.Embedding(input_dim = train_sel[feature].nunique(), output_dim = int(math.sqrt(train_sel[feature].nunique())))
embed = embed(input_tensors[feature])
else:
embed = layers.BatchNormalization()
embed = embed(tf.expand_dims(input_tensors[feature], -1))
embedding.append(embed)
temp = embedding
embedding = layers.concatenate(inputs = embedding)
nn_model = layers.LSTM(128)(embedding)
nn_model = layers.Dropout(0.1)(nn_model)
output = layers.Dense(1, activation = 'tanh')(nn_model)
model = tf.keras.Model(inputs=split_input,outputs = output)
Presently, I am fitting the model using
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
loss=tf.keras.losses.MeanSquaredError(),
metrics=[tf.keras.losses.MeanSquaredError()])
model.fit(dataset,epochs = 5)
I am receiving a value error
ValueError: in user code:
File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1051, in train_function *
return step_function(self, iterator)
File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1040, in step_function **
outputs = model.distribute_strategy.run(run_step, args=(data,))
File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1030, in run_step **
outputs = model.train_step(data)
File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 889, in train_step
y_pred = self(x, training=True)
File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 67, in error_handler
raise e.with_traceback(filtered_tb) from None
File "/usr/local/lib/python3.8/dist-packages/keras/engine/input_spec.py", line 200, in assert_input_compatibility
raise ValueError(f'Layer "{layer_name}" expects {len(input_spec)} input(s),'
ValueError: Layer "model_4" expects 18 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, None, 18) dtype=float32>]

Keras CNN: Incompatible shapes [batch_size*2,1] vs. [batch_size,1] with any batch_size > 1

I am Fitting a Siamese CNN with the following structure:
def get_siamese_model(input_shape):
"""
Model architecture
"""
# Define the tensors for the three input images
A_input = Input(input_shape)
B_input = Input(input_shape)
C_input = Input(input_shape)
# Convolutional Neural Network
#Initialzers
initializer = 'random_uniform'
initializer0 = 'zeros'
model = Sequential()
model.add(Conv2D(64, (10,10), activation='relu', input_shape=input_shape,
kernel_initializer=initializer , kernel_regularizer=l2(2e-4)))
model.add(MaxPooling2D())
model.add(Conv2D(128, (7,7), activation='relu', kernel_initializer=initializer ,
bias_initializer=initializer0, kernel_regularizer=l2(2e-4)))
model.add(MaxPooling2D())
model.add(Conv2D(128, (4,4), activation='relu', kernel_initializer=initializer ,
bias_initializer=initializer0, kernel_regularizer=l2(2e-4)))
print("C3 shape: ", model.output_shape)
model.add(MaxPooling2D())
print("P3 shape: ", model.output_shape)
model.add(Conv2D(256, (4,4), activation='relu', kernel_initializer=initializer ,
bias_initializer=initializer0, kernel_regularizer=l2(2e-4)))
model.add(Flatten())
model.add(Dense(4096, activation='sigmoid',
kernel_regularizer=l2(1e-3),
kernel_initializer=initializer,
bias_initializer=initializer0))
# Generate the encodings (feature vectors) for the three images
encoded_A = model(A_input)
encoded_B = model(B_input)
encoded_C = model(C_input)
#Custom Layer for L1-norm
L1_layer = Lambda(lambda tensors: K.sum(K.abs(tensors[0] - tensors[1]), axis=1,keepdims=True))
L_layerAB = L1_layer([encoded_A, encoded_B])
L2_layer = Lambda(lambda tensors: K.sum(K.abs(tensors[0] - tensors[1]), axis=1,keepdims=True))
L_layerAC = L2_layer([encoded_A, encoded_C])
merge6 = concatenate([L_layerAB, L_layerAC], axis = 0)
prediction = Dense(1,activation='sigmoid')(merge6)
siamese_net = Model(inputs=[A_input,B_input, C_input],outputs= prediction)
# return the model
return siamese_net
The training data is are triplets of pictures in array form with following dimensions: (128,128,3).
And the target data is a label (0,1).
Then we fit the model:
model = siam.get_siamese_model((128,128,3))
model.fit([tripletA,tripletB, tripletC], targets , epochs=2, verbose=1,
batch_size = 1)
This works for batch_size = 1 but anything over batchsize >1 produces the following error:
Epoch 1/5
Traceback (most recent call last):
File "<ipython-input-147-8959bad9406a>", line 2, in <module>
batch_size = 2)
File "C:\Users\valan\Anaconda3\lib\site-packages\keras\engine\training.py", line 1239, in fit
validation_freq=validation_freq)
File "C:\Users\valan\Anaconda3\lib\site-packages\keras\engine\training_arrays.py", line 196, in fit_loop
outs = fit_function(ins_batch)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\keras\backend.py", line 3727, in _call_
outputs = self._graph_fn(*converted_inputs)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\function.py", line 1551, in _call_
return self._call_impl(args, kwargs)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\function.py", line 1591, in _call_impl
return self._call_flat(args, self.captured_inputs, cancellation_manager)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\function.py", line 1692, in _call_flat
ctx, args, cancellation_manager=cancellation_manager))
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\function.py", line 545, in call
ctx=ctx)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\execute.py", line 67, in quick_execute
six.raise_from(core._status_to_exception(e.code, message), None)
File "<string>", line 3, in raise_from
InvalidArgumentError: Incompatible shapes: [4,1] vs. [2,1]
[[node loss_16/dense_47_loss/binary_crossentropy/logistic_loss/mul (defined at C:\Users\valan\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:3009) ]] [Op:__inference_keras_scratch_graph_33258]
Does anybody know where the Problem is with batch_size > 1?
EDIT1:
We found out that the following lines caused the error:
L1_layer = Lambda(lambda tensors: K.sum(K.abs(tensors[0] - tensors[1]), axis=1,keepdims=True))
L_layerAB = L1_layer([encoded_A, encoded_B])
L2_layer = Lambda(lambda tensors: K.sum(K.abs(tensors[0] - tensors[1]), axis=1,keepdims=True))
L_layerAC = L2_layer([encoded_A, encoded_C])
Removing these lines and just using sigmoid on encoded A and thus, making the model simpler makes it work for batchsizes >1 .
But does anybody know how to re-add those customized layers properly?
Mentioning the solution in this (Answer) section even though it is present in the Comments section, for the benefit of the community.
For the above code, with batch_size > 1, it is resulting in error,
InvalidArgumentError: Incompatible shapes: [4,1] vs. [2,1]
[[node loss_16/dense_47_loss/binary_crossentropy/logistic_loss/mul (defined at C:\Users\valan\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:3009) ]] [Op:__inference_keras_scratch_graph_33258]
Changing the code from
merge6 = concatenate([L_layerAB, L_layerAC], axis = 0)
to
merge6 = Concatenate()([L_layerAB, L_layerAC])
has resolved the error.

ValueError: Graph disconnected in vgg16

Traceback:
model = Model(input_tensor,x,name = 'vgg16_trunk')
File "/usr/local/lib/python3.6/dist-packages/keras/legacy/interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/keras/engine/network.py", line 93, in __init__
self._init_graph_network(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/keras/engine/network.py", line 231, in _init_graph_network
self.inputs, self.outputs)
File "/usr/local/lib/python3.6/dist-packages/keras/engine/network.py", line 1443, in _map_graph_network
str(layers_with_complete_input))
ValueError: Graph disconnected: cannot obtain value for tensor Tensor("input_2:0", shape=(?, 32, 32, 3), dtype=float32) at layer "input_2". The following previous layers were accessed without issue: []
How to solve this problem in vgg16 ??
def create_model(input_shape):
channel_axis = 1 if K.image_data_format() == "channels_first" else -1
input_tensor = Input(shape=input_shape)
base_model = VGG16(classes=10,input_tensor=None,input_shape=input_shape,include_top=False)
x = base_model.output
x = BatchNormalization(axis=channel_axis, momentum=mom,
epsilon=eps, gamma_initializer=gamma)(x)
x = LeakyReLU(leakiness)(x)
model = Model(input_tensor,x,name = 'vgg16_trunk')
return model
Pass the input_tensor you created here:
input_tensor = Input(shape=input_shape)
where base_model is created:
base_model = VGG16(classes=10,input_tensor=input_tensor,include_top=False)
Please note also, that the tensor will already have the input_shape so it's not necessary to give it as parameter again when creating the base_model.

Keras Flatten layer in Functional API?

model = Sequential()
model.add(Flatten(input_shape=(1,) + (52,)))
model.add(Dense(100))
model.add(Activation('relu'))
model.add(Dense(2))
model.add(Activation('linear'))
print(model.summary())
I want to change this keras code in sequential version to same code with functional version like the following.
input = Input(shape=(1,) + (52,))
i = Flatten()(input)
h = Dense(100, activation='relu')(i)
o = Dense(2, activation='linear')(h)
model = Model(inputs=i, outputs=o)
model.summary()
But it got error
File "C:\Users\SDS\Anaconda3\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "C:\Users\SDS\Anaconda3\lib\site-packages\keras\engine\network.py", line 93, in __init__
self._init_graph_network(*args, **kwargs)
File "C:\Users\SDS\Anaconda3\lib\site-packages\keras\engine\network.py", line 237, in _init_graph_network
self.inputs, self.outputs)
File "C:\Users\SDS\Anaconda3\lib\site-packages\keras\engine\network.py", line 1430, in _map_graph_network
str(layers_with_complete_input))
ValueError: Graph disconnected: cannot obtain value for tensor Tensor("input_1:0", shape=(?, 1, 52), dtype=float32) at layer "input_1". The following previous layers were accessed without issue: []
Your model definition is incorrect, the inputs parameter of Model should go to your Input layer, like this:
input = Input(shape=(1,) + (52,))
i = Flatten()(input)
h = Dense(100, activation='relu')(i)
o = Dense(2, activation='linear')(h)
model = Model(inputs=inputs, outputs=o)
I believe you cannot put any tensor other than the Input layer as input to a model.
The input for model should be input layer(first layer without any dense layer).
So it should be like :
model = Model(inputs=input, outputs=o)

Using LSTM in Keras and tensorflow for time series predictions

I want to define a LSTM layers using tensorflow in keras. The code as following:
model = Sequential()
inputs = Input(shape=(time_steps, 1))
cell = tf.nn.rnn_cell.LSTMCell(n_neurons)
multi_cell = tf.nn.rnn_cell.MultiRNNCell([cell] * n_layers)
lstm_outputs, states = tf.nn.dynamic_rnn(multi_cell, inputs, dtype=tf.float32)
outputs = TimeDistributed(Dense(1))(lstm_outputs)
model = Model(inputs=inputs, outputs=outputs)
adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
model.compile(loss='mean_squared_error', optimizer=adam)
print(model.summary())
when running, an error occurred:
Using TensorFlow backend.
Traceback (most recent call last):
File "/Users/zhjmdcjk/Desktop/Untitled.py", line 81, in <module>
model = Model(inputs=inputs, outputs=outputs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/keras/legacy/interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/keras/engine/topology.py", line 1734, in __init__
build_map_of_graph(x, finished_nodes, nodes_in_progress)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/keras/engine/topology.py", line 1724, in build_map_of_graph
layer, node_index, tensor_index)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/keras/engine/topology.py", line 1695, in build_map_of_graph
layer, node_index, tensor_index = tensor._keras_history
AttributeError: 'Tensor' object has no attribute '_keras_history'
I am not clear about these, can anyone give me some advice. Thanks a lot!
Is there any particular reason you're using Tensorflow's LSTM in Keras? You can directly use Keras LSTM layers.
inputs = Input(shape=(time_steps, 1))
lstm1 = LSTM(n_neurons, return_sequences=True)(inputs)
lstm_outputs = LSTM(n_neurons, return_sequences=True)(lstm1)
outputs = TimeDistributed(Dense(1))(lstm_outputs)
model = Model(inputs=inputs, outputs=outputs)
Also, you don't need to use model = Sequential() in case of Keras' functional API.

Resources