Keras Layer Concatenation - tensorflow

I'm trying to see how I can create a model in Keras with multiple Embedding Layers and other inputs. Here's how my model is structured(E=Embedding Layer, [....]=Input Layer):
E E [V V V]
\ | /
\ | /
Dense
|
Dense
Here is my code so far:
model_a = Sequential()
model_a.add(Embedding(...))
model_b = Sequential()
model_b.add(Embedding(...))
model_c = Sequential()
model_c.add(Embedding(...))
model_values = Sequential()
model_values.add(Input(...))
classification_model = Sequential()
classification_layers = [
Concatenate([model_a,model_b,model_c, model_values]),
Dense(...),
Dense(...),
Dense(2, activation='softmax')
]
for layer in classification_layers:
classification_model.add(layer)
classification_model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
classification_model.fit(train_data,one_hot_labels, epochs=1, validation_split=0.2)
However I get the following error:
ValueError: A `Concatenate` layer should be called on a list of at least 2 inputs
I am at a loss at what I'm doing wrong here. Here's the a little more detail for the error log:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-37-d5ab23b17e9d> in <module>()
----> 1 classification_model.fit(train_data,one_hot_labels, epochs=1, validation_split=0.2)
/usr/local/lib/python3.5/dist-packages/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, **kwargs)
953 sample_weight=sample_weight,
954 class_weight=class_weight,
--> 955 batch_size=batch_size)
956 # Prepare validation data.
957 do_validation = False
/usr/local/lib/python3.5/dist-packages/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_array_lengths, batch_size)
674 # to match the value shapes.
675 if not self.inputs:
--> 676 self._set_inputs(x)
677
678 if y is not None:
/usr/local/lib/python3.5/dist-packages/keras/engine/training.py in _set_inputs(self, inputs, outputs, training)
574 assert len(inputs) == 1
575 inputs = inputs[0]
--> 576 self.build(input_shape=(None,) + inputs.shape[1:])
577 return
578
/usr/local/lib/python3.5/dist-packages/keras/engine/sequential.py in build(self, input_shape)
225 self.inputs = [x]
226 for layer in self._layers:
--> 227 x = layer(x)
228 self.outputs = [x]
229
/usr/local/lib/python3.5/dist-packages/keras/engine/base_layer.py in __call__(self, inputs, **kwargs)
430 '`layer.build(batch_input_shape)`')
431 if len(input_shapes) == 1:
--> 432 self.build(input_shapes[0])
433 else:
434 self.build(input_shapes)
/usr/local/lib/python3.5/dist-packages/keras/layers/merge.py in build(self, input_shape)
339 # Used purely for shape validation.
340 if not isinstance(input_shape, list) or len(input_shape) < 2:
--> 341 raise ValueError('A `Concatenate` layer should be called '
342 'on a list of at least 2 inputs')
343 if all([shape is None for shape in input_shape]):
ValueError: A `Concatenate` layer should be called on a list of at least 2 inputs

input1 = Input(input_shape=...)
input2 = Input(...)
input3 = Input(...)
values = Input(...)
out1 = Embedding(...)(input1)
out2 = Embedding(...)(input2)
out3 = Embedding(...)(input3)
#make sure values has a shape compatible with the embedding outputs.
#usually it should have shape (equal_samples, equal_length, features)
joinedInput = Concatenate()([out1,out2,out3,values])
out = Dense(...)(joinedInput)
out = Dense(...)(out)
out = Dense(2, activation='softmax')(out)
model = Model([input1,input2,input3,values], out)

You are missing the 'axis' parameter in the call. If you are concatenating on the last dimension (it's unclear what the dimensions of these embeddings and input tensors are), use:
concatenate([model_a,model_b,model_c, model_values], axis=-1)

Related

Error when checking input: expected dense_203_input to have shape (1202,) but got array with shape (1,)

I've made a very simple neural network, which is meant to do reinforcement learning. However, I cannot predict anything as I get an error when trying to predict.
Error in question:
Error when checking input: expected dense_203_input to have shape (1202,) but got array with shape (1,)
Model in questions:
def _build_compile_model(self):
model = Sequential()
model.add(Dense(300, activation='relu', input_dim=1202))
model.add(Dense(300, activation='relu'))
model.add(Dense(200, activation='relu'))
model.add(Dense(self._action_size, activation='softmax'))
model.compile(loss='mse', optimizer=self._optimizer)
return model
error occurs when calling model.predict(state) where state is an array of shape (1202, 1).
Full error message is
ValueError Traceback (most recent call last)
<ipython-input-148-06b7a01facef> in <module>
18 new_state, reward = env.step(action, new_demand_a, new_demand_b) # Take action, get new state and reward
19 new_state = np.reshape(new_state, [1202, -1])
---> 20 agent.update(old_state, new_state, action, reward) # Let the agent update internal
21 average_reward.append(reward) # Keep score
22 if i % 100 == 0 and i != 0: # Print out metadata every 100th iteration
<ipython-input-145-142ae54ce43f> in update(self, old_state, new_state, action, reward)
49 def update(self, old_state, new_state, action, reward):
50 print(old_state.shape)
---> 51 target = self.q_network.predict(old_state)
52 t = self.target_network.predict(new_state)
53 target[0][action] = reward + self.gamma * np.amax(t)
/opt/conda/envs/tensorflow2/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training.py in predict(self, x, batch_size, verbose, steps, callbacks, max_queue_size, workers, use_multiprocessing)
1011 max_queue_size=max_queue_size,
1012 workers=workers,
-> 1013 use_multiprocessing=use_multiprocessing)
1014
1015 def reset_metrics(self):
/opt/conda/envs/tensorflow2/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py in predict(self, model, x, batch_size, verbose, steps, callbacks, max_queue_size, workers, use_multiprocessing, **kwargs)
496 model, ModeKeys.PREDICT, x=x, batch_size=batch_size, verbose=verbose,
497 steps=steps, callbacks=callbacks, max_queue_size=max_queue_size,
--> 498 workers=workers, use_multiprocessing=use_multiprocessing, **kwargs)
499
500
/opt/conda/envs/tensorflow2/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py in _model_iteration(self, model, mode, x, y, batch_size, verbose, sample_weight, steps, callbacks, max_queue_size, workers, use_multiprocessing, **kwargs)
424 max_queue_size=max_queue_size,
425 workers=workers,
--> 426 use_multiprocessing=use_multiprocessing)
427 total_samples = _get_total_number_of_samples(adapter)
428 use_sample = total_samples is not None
/opt/conda/envs/tensorflow2/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py in _process_inputs(model, mode, x, y, batch_size, epochs, sample_weights, class_weights, shuffle, steps, distribution_strategy, max_queue_size, workers, use_multiprocessing)
644 standardize_function = None
645 x, y, sample_weights = standardize(
--> 646 x, y, sample_weight=sample_weights)
647 elif adapter_cls is data_adapter.ListsOfScalarsDataAdapter:
648 standardize_function = standardize
/opt/conda/envs/tensorflow2/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, batch_size, check_steps, steps_name, steps, validation_split, shuffle, extract_tensors_from_dataset)
2381 is_dataset=is_dataset,
2382 class_weight=class_weight,
-> 2383 batch_size=batch_size)
2384
2385 def _standardize_tensors(self, x, y, sample_weight, run_eagerly, dict_inputs,
/opt/conda/envs/tensorflow2/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training.py in _standardize_tensors(self, x, y, sample_weight, run_eagerly, dict_inputs, is_dataset, class_weight, batch_size)
2408 feed_input_shapes,
2409 check_batch_axis=False, # Don't enforce the batch size.
-> 2410 exception_prefix='input')
2411
2412 # Get typespecs for the input data and sanitize it if necessary.
/opt/conda/envs/tensorflow2/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_utils.py in standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
580 ': expected ' + names[i] + ' to have shape ' +
581 str(shape) + ' but got array with shape ' +
--> 582 str(data_shape))
583 return data
584
ValueError: Error when checking input: expected dense_211_input to have shape (1202,) but got array with shape (1,)
There are two approaches when feeding inputs on your model:
1st Option: Using the input_shape
model.add(Dense(300, activation='relu', input_shape=(1202,1)))
Here the input shape is in 2D, but you should feed your network a 3D input (Rank 3) since you need to include the batch_size.
Example input:
state = np.array(np.ones((BATCH_SIZE,1202,1)))
print("Input Rank: {}".format(tf.rank(state))) # Check for the Rank of Input
2nd Option: Using the input_dim
model_dim.add(Dense(300, activation='relu', input_dim=1202))
Here the input shape is in 1D, but you should feed your network a 2D input (Rank 2) since you need to include the batch_size.
Example input :
state = np.array(np.ones((1,1202,)))
print("Input Rank: {}".format(tf.rank(state))) # Check for the Rank of Input

TypeError when trying to use EarlyStopping with f1-metric as stopping criterion

I want for training a CNN with Early Stopping and want to use the f1-metric as stopping criterion.
When I compile the code for the CNN model I get the a TypeError as error message.
I'm still using Tensorflow 1.4 would like to avoid an upgrade to 2.0, because I have in mind that my previous code doesn't work anymore.
The error message is as follows:
TypeError Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/sklearn/utils/validation.py in _num_samples(x)
158 try:
--> 159 return len(x)
160 except TypeError:
14 frames
/usr/local/lib/python3.6/dist-
packages/tensorflow_core/python/framework/ops.py in __len__(self)
740 "Please call `x.shape` rather than `len(x)` for "
--> 741 "shape information.".format(self.name))
742
TypeError: len is not well defined for symbolic Tensors. (dense_16_target:0) Please call `x.shape` rather than `len(x)` for shape information.
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
<ipython-input-44-cd3da16e057c> in <module>()
----> 1 model = model_cnn(False,False, False,True,6, 0.2, 0.5)
2 X_train, X_val, y_train, y_val = split_data(X_train, y_train,1)
3 cnn, ep = train_model_es(model, X_train, y_train, X_val, y_val, X_test, y_test, 50, 500,1)
<ipython-input-42-d275d9c69c03> in model_cnn(spat, extra_pool, avg_pool, cw, numb_conv, drop_conv, drop_dense)
36 if cw == True:
37 print("sparse categorical crossentropy")
---> 38 model.compile(loss="sparse_categorical_crossentropy", optimizer=Adam(), metrics=['accuracy', f1_metric])
39 #model.compile(loss="sparse_categorical_crossentropy", optimizer=Adam(), metrics=['accuracy'])
40 print("nothing")
/usr/local/lib/python3.6/dist-packages/keras/engine/training.py in compile(self, optimizer, loss, metrics, loss_weights, sample_weight_mode, weighted_metrics, target_tensors, **kwargs)
452 output_metrics = nested_metrics[i]
453 output_weighted_metrics = nested_weighted_metrics[i]
--> 454 handle_metrics(output_metrics)
455 handle_metrics(output_weighted_metrics, weights=weights)
456
/usr/local/lib/python3.6/dist-packages/keras/engine/training.py in handle_metrics(metrics, weights)
421 metric_result = weighted_metric_fn(y_true, y_pred,
422 weights=weights,
--> 423 mask=masks[i])
424
425 # Append to self.metrics_names, self.metric_tensors,
/usr/local/lib/python3.6/dist-packages/keras/engine/training_utils.py in weighted(y_true, y_pred, weights, mask)
426 """
427 # score_array has ndim >= 2
--> 428 score_array = fn(y_true, y_pred)
429 if mask is not None:
430 # Cast the mask to floatX to avoid float64 upcasting in Theano
<ipython-input-9-b21dc3bd89a6> in f1_metric(y_test, y_pred)
1 def f1_metric(y_test, y_pred):
----> 2 f1 = f1_score(y_test, y_pred, average='macro')
3 return f1
/usr/local/lib/python3.6/dist-packages/sklearn/metrics/_classification.py in f1_score(y_true, y_pred, labels, pos_label, average, sample_weight, zero_division)
1097 pos_label=pos_label, average=average,
1098 sample_weight=sample_weight,
-> 1099 zero_division=zero_division)
1100
1101
/usr/local/lib/python3.6/dist-packages/sklearn/metrics/_classification.py in fbeta_score(y_true, y_pred, beta, labels, pos_label, average, sample_weight, zero_division)
1224 warn_for=('f-score',),
1225 sample_weight=sample_weight,
-> 1226 zero_division=zero_division)
1227 return f
1228
/usr/local/lib/python3.6/dist-packages/sklearn/metrics/_classification.py in precision_recall_fscore_support(y_true, y_pred, beta, labels, pos_label, average, warn_for, sample_weight, zero_division)
1482 raise ValueError("beta should be >=0 in the F-beta score")
1483 labels = _check_set_wise_labels(y_true, y_pred, average, labels,
-> 1484 pos_label)
1485
1486 # Calculate tp_sum, pred_sum, true_sum ###
/usr/local/lib/python3.6/dist-packages/sklearn/metrics/_classification.py in _check_set_wise_labels(y_true, y_pred, average, labels, pos_label)
1299 str(average_options))
1300
-> 1301 y_type, y_true, y_pred = _check_targets(y_true, y_pred)
1302 present_labels = unique_labels(y_true, y_pred)
1303 if average == 'binary':
/usr/local/lib/python3.6/dist-packages/sklearn/metrics/_classification.py in _check_targets(y_true, y_pred)
78 y_pred : array or indicator matrix
79 """
---> 80 check_consistent_length(y_true, y_pred)
81 type_true = type_of_target(y_true)
82 type_pred = type_of_target(y_pred)
/usr/local/lib/python3.6/dist-packages/sklearn/utils/validation.py in check_consistent_length(*arrays)
206 """
207
--> 208 lengths = [_num_samples(X) for X in arrays if X is not None]
209 uniques = np.unique(lengths)
210 if len(uniques) > 1:
/usr/local/lib/python3.6/dist-packages/sklearn/utils/validation.py in <listcomp>(.0)
206 """
207
--> 208 lengths = [_num_samples(X) for X in arrays if X is not None]
209 uniques = np.unique(lengths)
210 if len(uniques) > 1:
/usr/local/lib/python3.6/dist-packages/sklearn/utils/validation.py in _num_samples(x)
159 return len(x)
160 except TypeError:
--> 161 raise TypeError(message)
162
163
TypeError: Expected sequence or array-like, got <class 'tensorflow.python.framework.ops.Tensor'>
And here is the relevant code:
def f1_metric(y_test, y_pred):
f1 = f1_score(y_test, y_pred, average='macro')
return f1
def train_model_es(model, X, y, X_val, y_val, X_test, y_test):
es = EarlyStopping(monitor='f1_metric', mode='max', patience=20, restore_best_weights=True)
y = np.argmax(y, axis=1)
y_val = np.argmax(y_val, axis=1)
y_test = np.argmax(y_test, axis=1)
class_weights = class_weight.compute_class_weight('balanced', np.unique(y), y)
class_weights = dict(enumerate(class_weights))
history = model.fit(X, y, class_weight=class_weights, batch_size=32,epochs=20, verbose=1,
validation_data=(X_val, y_val), callbacks=[es])
def model_cnn():
model = Sequential()
model.add(Conv2D(32, kernel_size=(3,3), input_shape=(28,28,1),padding='same'))
model.add(BatchNormalization())
model.add(ELU())
model.add(Conv2D(32, kernel_size=(3,3), padding='same'))
model.add(BatchNormalization())
model.add(ELU())
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(256))
model.add(BatchNormalization())
model.add(ELU())
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
model.compile(loss="sparse_categorical_crossentroy",optimizer=Adam(),metrics=["accuracy",f1_metric])
return model
Does anyone have a tip on how to fix this error message.
Many thanks for every hint
As the error message suggests,
Error 1) You are doing a len() operation on symbolic tensor. You cannot do that operation on symbolic tensor. You can find difference between a variable tensor and symbolic tensor here.
Error 2) You are using a tensor for the operation which expects array as input. Can you please convert y_true and y_pred from tensor to array and use in the f1_score and other operations.
Example - To convert tensor to array
%tensorflow_version 1.x
print(tf.__version__)
import tensorflow as tf
import numpy as np
x = tf.constant([1,2,3,4,5,6])
print("Type of x:",x)
with tf.Session() as sess:
y = np.array(x.eval())
print("Type of y:",y.shape,y)
Output -
1.15.2
Type of x: Tensor("Const_24:0", shape=(6,), dtype=int32)
Type of y: (6,) [1 2 3 4 5 6]

TF 2.0 Keras fit_generator: data_generator outputs wrong shape

I'm trying to train an image captioning model using TensorFlow 2.0 and tf.keras API. The dataset I'm using is the Flickr 8K dataset and although my computer can hold the entire dataset in RAM I'd like to use fit_generator with a data_generator to load and prepare data by batch (because once I can make it work with this dataset I'll try to train this model with a larger dataset).
The way I'm pre-processing the data and the model definition are OK. I can do model.predict() on a manually generated batch and the model outputs the expected data shape and no errors. I can also use the data_generator manually to prepare the full dataset and use the whole data with model.fit() and it works, the model trains with no error.
The problem comes when I try to train using fit_generator, that will output this error (full length error output at the end of the post):
ValueError: could not broadcast input array from shape (168,2048) into shape (168)
If I call the generator function alone to check type and shape of the generated batch, it seems to me that everything is ok:
generator = data_generator(train_descriptions, train_features, wordtoix, max_length, number_pics_per_bath)
data = next(generator)
print("Total items in data: ", len(data))
# Data[1] is the encoded Y
print("Encodded Y shape: ", data[1].shape)
print("Example Y: ", data[1][0])
# Data[0] is a list of [image_feature, encoded_caption]
print("X1 shape (image feature): ", data[0][0].shape)
print("X2 shape (image caption): ", data[0][1].shape)
Outputs:
-----------------------------------
Total items in data: 2
Encodded Y shape: (168, 1652)
Example Y: [0. 0. 1. ... 0. 0. 0.]
X1 shape (image feature): (168, 2048)
X2 shape (image caption): (168, 34)
This is the code of the data_generator function:
# data generator, intended to be used in a call to model.fit_generator()
# $descriptions: a dictionary containing <image_id> -> [ text_captions_list ]
# photos: list of numpy arrays representing image features
# wordtoix: a dictionary to convert words to word_codes (integers)
# max_length: maximum word count for a caption
def data_generator(descriptions, photos, wordtoix, max_length, num_photos_per_batch):
X1, X2, y = list(), list(), list()
n=0
# loop for ever over images
while 1:
for key, desc_list in descriptions.items():
n+=1
# retrieve the photo feature
photo = photos[key+'.jpg']
for desc in desc_list:
# encode the sequence
seq = [wordtoix[word] for word in desc.split(' ') if word in wordtoix]
# split one sequence into multiple X, y pairs
for i in range(1, len(seq)):
# split into input and output pair
in_seq, out_seq = seq[:i], seq[i]
# pad input sequence
in_seq = pad_sequences([in_seq], maxlen=max_length)[0]
# encode output sequence
out_seq = to_categorical([out_seq], num_classes=vocab_size)[0]
# store
X1.append(photo)
X2.append(in_seq)
y.append(out_seq)
# yield the batch data
if n==num_photos_per_batch:
yield [[array(X1), array(X2)], array(y)]
X1, X2, y = list(), list(), list()
n=0
And this is how I'm calling fit_generator:
epochs = 20
steps = len(train_descriptions)
for i in range(epochs):
generator = data_generator(train_descriptions, train_features, wordtoix, max_length)
model.fit_generator(generator, epochs=1, steps_per_epoch=steps, verbose=1)
model.save('./saved/model_' + str(i) + '.h5')
for i in range(epochs):
generator = data_generator(train_descriptions, train_features, wordtoix, max_length, number_pics_per_bath)
model.fit_generator(generator, epochs=1, steps_per_epoch=steps, verbose=1)
model.save('./saved/model_' + str(i) + '.h5')
I'm using the inceptionv3 model with imagenet pre-trained weights to generate features from images (that are then saved to disk).
Then I use this model assembly that expects "two inputs": an image feature array and an encoded image caption:
inputs1 = tf.keras.Input(shape=(2048,))
fe1 = tf.keras.layers.Dropout(0.5)(inputs1)
fe2 = tf.keras.layers.Dense(256, activation='relu')(fe1)
inputs2 = tf.keras.Input(shape=(max_length,))
se1 = tf.keras.layers.Embedding(vocab_size, embedding_dim, mask_zero=True)(inputs2)
se2 = tf.keras.layers.Dropout(0.5)(se1)
se3 = tf.keras.layers.LSTM(256)(se2)
decoder1 = tf.keras.layers.concatenate([fe2, se3])
decoder2 = tf.keras.layers.Dense(256, activation='relu')(decoder1)
outputs = tf.keras.layers.Dense(vocab_size, activation='softmax')(decoder2)
model = Model(inputs=[inputs1, inputs2], outputs=outputs)
The full length error from fit_generator is the following:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-73-10ea3905954d> in <module>
1 for i in range(epochs):
2 generator = data_generator(train_descriptions, train_features, wordtoix, max_length, number_pics_per_bath)
----> 3 model.fit_generator(generator, epochs=1, steps_per_epoch=steps, verbose=1)
4 model.save('./saved/model_' + str(i) + '.h5')
~/anaconda3/envs/tf2-gpu/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)
1295 shuffle=shuffle,
1296 initial_epoch=initial_epoch,
-> 1297 steps_name='steps_per_epoch')
1298
1299 def evaluate_generator(self,
~/anaconda3/envs/tf2-gpu/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/training_generator.py in model_iteration(model, data, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch, mode, batch_size, steps_name, **kwargs)
263
264 is_deferred = not model._is_compiled
--> 265 batch_outs = batch_function(*batch_data)
266 if not isinstance(batch_outs, list):
267 batch_outs = [batch_outs]
~/anaconda3/envs/tf2-gpu/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/training.py in train_on_batch(self, x, y, sample_weight, class_weight, reset_metrics)
971 outputs = training_v2_utils.train_on_batch(
972 self, x, y=y, sample_weight=sample_weight,
--> 973 class_weight=class_weight, reset_metrics=reset_metrics)
974 outputs = (outputs['total_loss'] + outputs['output_losses'] +
975 outputs['metrics'])
~/anaconda3/envs/tf2-gpu/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/training_v2_utils.py in train_on_batch(model, x, y, sample_weight, class_weight, reset_metrics)
251 x, y, sample_weights = model._standardize_user_data(
252 x, y, sample_weight=sample_weight, class_weight=class_weight,
--> 253 extract_tensors_from_dataset=True)
254 batch_size = array_ops.shape(nest.flatten(x, expand_composites=True)[0])[0]
255 # If `model._distribution_strategy` is True, then we are in a replica context
~/anaconda3/envs/tf2-gpu/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, batch_size, check_steps, steps_name, steps, validation_split, shuffle, extract_tensors_from_dataset)
2470 feed_input_shapes,
2471 check_batch_axis=False, # Don't enforce the batch size.
-> 2472 exception_prefix='input')
2473
2474 # Get typespecs for the input data and sanitize it if necessary.
~/anaconda3/envs/tf2-gpu/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/training_utils.py in standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
504 elif isinstance(data, (list, tuple)):
505 if isinstance(data[0], (list, tuple)):
--> 506 data = [np.asarray(d) for d in data]
507 elif len(names) == 1 and isinstance(data[0], (float, int)):
508 data = [np.asarray(data)]
~/anaconda3/envs/tf2-gpu/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/training_utils.py in <listcomp>(.0)
504 elif isinstance(data, (list, tuple)):
505 if isinstance(data[0], (list, tuple)):
--> 506 data = [np.asarray(d) for d in data]
507 elif len(names) == 1 and isinstance(data[0], (float, int)):
508 data = [np.asarray(data)]
~/anaconda3/envs/tf2-gpu/lib/python3.6/site-packages/numpy/core/_asarray.py in asarray(a, dtype, order)
83
84 """
---> 85 return array(a, dtype, copy=False, order=order)
86
87
ValueError: could not broadcast input array from shape (168,2048) into shape (168)
Thanks in advance for your help!
There should be a return statement for def data_generator. That worked for me TBH!
incase: https://github.com/santoshgopane/Automatic-image-Captioning-using-RNN

Custom model in Keras fails to fit on the first run

I have a custom model in Keras. It's essentially RNN model which on every step computes negative sampling loss, i.e. a sigmoid on positive and negative logits.
from tensorflow.keras.layers import Input, Embedding, GRU, dot, Dense, add, concatenate, multiply, Subtract
class rnn_neg_sampling(keras.models.Model):
def __init__(self, vocab_size, dim, seq_length, num_negatives=10):
super(rnn_neg_sampling, self).__init__()
self.num_negatives = num_negatives
self.embedding_input = Embedding(
input_dim=vocab_size+1,
output_dim=dim,
mask_zero=True,
input_length=seq_length
)
self.embedding_output = Embedding(
input_dim=vocab_size+1,
output_dim=dim,
mask_zero=True,
input_length=seq_length
)
self.gru = GRU(dim, return_sequences=True)
def call(self, input):
inputs, targets, negatives = input
embedded_inputs = self.embedding_input(inputs)
# https://keras.io/layers/recurrent/#gru
gru_output = self.gru(embedded_inputs)
embedded_targets = self.embedding_output(targets)
embedded_negatives = self.embedding_output(negatives)
positive_dots = K.expand_dims(multiply([gru_output, embedded_targets]), axis=1)
negative_dots = multiply([K.repeat_elements(K.expand_dims(gru_output, axis=1),
rep=self.num_negatives,
axis=1),
embedded_negatives
])
positive_logits = K.sum(positive_dots, axis=-1)
negative_logits = -K.sum(negative_dots, axis=-1)
logits = K.concatenate([positive_logits, negative_logits], axis=1)
self.add_loss(-K.mean(K.log(K.sigmoid(logits))))
I create the model like this:
neg_number = 3
vector_dim=10
sequence_length = 5
vocab_size = 100
ns_model = rnn_neg_sampling(vocab_size, vector_dim, sequence_length, neg_number)
The data is created like this:
X_inputs = np.random.randint(0, 5, size=(batch_size, sequence_length))
X_targets = np.random.randint(0, 5, size=(batch_size, sequence_length))
X_negatives = np.random.randint(0, 5, size=(batch_size, neg_number, sequence_length))
And I compile and fit it like this:
ns_model.compile(loss=None, optimizer='rmsprop')
history = ns_model.fit([X_inputs, X_targets, X_negatives], epochs=1)
However, it fails with the following log:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-1343-a8447c14a3a4> in <module>
1 ns_model.compile(loss=None, optimizer='rmsprop')
----> 2 history = ns_model.fit([X_inputs, X_targets, X_negatives], epochs=1)
~/miniconda3/envs/ml.crash-course/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)
966 validation_steps=validation_steps,
967 validation_freq=validation_freq,
--> 968 steps_name='steps_per_epoch')
969
970 def evaluate(self,
~/miniconda3/envs/ml.crash-course/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_arrays.py in model_iteration(model, inputs, targets, sample_weights, batch_size, epochs, verbose, callbacks, val_inputs, val_targets, val_sample_weights, shuffle, initial_epoch, steps_per_epoch, validation_steps, validation_freq, mode, validation_in_fit, prepared_feed_values_from_dataset, steps_name, **kwargs)
147
148 # Get step function and loop type.
--> 149 f = _make_execution_function(model, mode)
150 use_steps = is_dataset or steps_per_epoch is not None
151 do_validation = val_inputs is not None
~/miniconda3/envs/ml.crash-course/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_arrays.py in _make_execution_function(model, mode)
490 if model._distribution_strategy:
491 return distributed_training_utils._make_execution_function(model, mode)
--> 492 return model._make_execution_function(mode)
493
494
~/miniconda3/envs/ml.crash-course/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py in _make_execution_function(self, mode)
2156 def _make_execution_function(self, mode):
2157 if mode == ModeKeys.TRAIN:
-> 2158 self._make_fit_function()
2159 return self._fit_function
2160 if mode == ModeKeys.TEST:
~/miniconda3/envs/ml.crash-course/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py in _make_fit_function(self)
2099 ]
2100 self._make_train_function_helper(
-> 2101 '_fit_function', [self.total_loss] + metrics_tensors)
2102
2103 def _make_test_function_helper(self, fn_name, outputs, metric_updates=None):
AttributeError: 'rnn_neg_sampling' object has no attribute 'total_loss'
What is strange that if I run the same snippet again (just launching this snippet in ipython second time) I will get a model fitted:
ns_model.compile(loss=None, optimizer='rmsprop')
history = ns_model.fit([X_inputs, X_targets, X_negatives], epochs=1)
>>>>
W0208 15:14:44.158487 139940057085760 training.py:304] Output "output_1" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to "output_1".
3/3==============================] - 6s 2s/sample - loss: 0.6930
How can I make a model to fit from the first time?

Keras 'Tensor' object has no attribute 'ndim'

I am trying to implement a siamese network (by using triplet loss method). I just cannot make it train. After many tries, I guess that I have my problem in the generator (where I prepare the input data stream for training) but I could not localize the problem so far. HELP! :)
Here is my model definition (it is based on ResNet50).
model = ResNet50(weights='imagenet')
model.layers.pop()
for layer in model.layers:
layer.trainable = False
x = model.get_layer('flatten_1').output
model_out = Dense(128, activation='sigmoid', name='model_out')(x)
new_model = Model(inputs=model.input, outputs=model_out)
Here I define the model to be trained:
anchor_in = Input(shape=(224, 224, 3))
positive_in = Input(shape=(224, 224, 3))
negative_in = Input(shape=(224, 224, 3))
anchor_out = new_model(anchor_in)
positive_out = new_model(positive_in)
negative_out = new_model(negative_in)
merged_vector = concatenate([anchor_out, positive_out, negative_out], axis=-1)
# Define the model to be trained
siamese_model = Model(inputs=[anchor_in, positive_in, negative_in],
outputs=merged_vector)
siamese_model.compile(optimizer=Adam(lr=.001), loss=triplet_loss)
To be able to train the model. I need to feed it with data with a generator and here is how I define it:
(Note that I intentionally put only 1 picture in each folder just to start with.. I will later increase the # pictures in each folder if I can make it work.)
def generator_three_imgs():
train_path = r'C:\Users\jon\Desktop\AI_anaconda\face_recognition\dataset\train\E'
generator1 = ImageDataGenerator()
generator2 = ImageDataGenerator()
generator3 = ImageDataGenerator()
anchor_train_batches = generator1.flow_from_directory(train_path+'\Ed_A', target_size=(224, 224), batch_size=1)
positive_train_batches = generator2.flow_from_directory(train_path+'\Ed_P', target_size=(224, 224), batch_size=1)
negative_train_batches = generator3.flow_from_directory(train_path+'\Ed_N', target_size=(224, 224), batch_size=1)
while True:
anchor_imgs, anchor_labels = anchor_train_batches.next()
positive_imgs, positive_labels = positive_train_batches.next()
negative_imgs, negative_labels = negative_train_batches.next()
concat_out = concatenate([anchor_out, positive_out, negative_out], axis=-1)
yield ([anchor_imgs, positive_imgs, negative_imgs],
concat_out)
And finally, I try totrain the model as following:
siamese_model.fit_generator(generator_three_imgs(),
steps_per_epoch=1, epochs=15, verbose=2)
which fails right away by giving the following error message:
Epoch 1/15
Found 1 images belonging to 1 classes.
Found 1 images belonging to 1 classes.
Found 1 images belonging to 1 classes.
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-23-7537b4595917> in <module>()
1 siamese_model.fit_generator(generator_three_imgs(),
----> 2 steps_per_epoch=1, epochs=15, verbose=2)
~\Anaconda3\envs\tensorflow\lib\site-packages\keras\legacy\interfaces.py in wrapper(*args, **kwargs)
89 warnings.warn('Update your `' + object_name +
90 '` call to the Keras 2 API: ' + signature, stacklevel=2)
---> 91 return func(*args, **kwargs)
92 wrapper._original_function = func
93 return wrapper
~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)
2228 outs = self.train_on_batch(x, y,
2229 sample_weight=sample_weight,
-> 2230 class_weight=class_weight)
2231
2232 if not isinstance(outs, list):
~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in train_on_batch(self, x, y, sample_weight, class_weight)
1875 x, y,
1876 sample_weight=sample_weight,
-> 1877 class_weight=class_weight)
1878 if self.uses_learning_phase and not isinstance(K.learning_phase(), int):
1879 ins = x + y + sample_weights + [1.]
~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_array_lengths, batch_size)
1478 output_shapes,
1479 check_batch_axis=False,
-> 1480 exception_prefix='target')
1481 sample_weights = _standardize_sample_weights(sample_weight,
1482 self._feed_output_names)
~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in _standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
74 data = data.values if data.__class__.__name__ == 'DataFrame' else data
75 data = [data]
---> 76 data = [np.expand_dims(x, 1) if x is not None and x.ndim == 1 else x for x in data]
77
78 if len(data) != len(names):
~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in <listcomp>(.0)
74 data = data.values if data.__class__.__name__ == 'DataFrame' else data
75 data = [data]
---> 76 data = [np.expand_dims(x, 1) if x is not None and x.ndim == 1 else x for x in data]
77
78 if len(data) != len(names):
AttributeError: 'Tensor' object has no attribute 'ndim'
There is maybe someone out there who has more experience on this..?
I recognized that I pasted the wrong data above. But that still would not solve the problem. The solution Daniel Möller suggested below solved the problem.
There was a typo in the content of generator function above. The corrected one (incl. Daniel's suggestion below) looks as folowing:
def generator_three_imgs(batch_size=1):
train_path = r'C:\Users\sinthes\Desktop\AI_anaconda\face_recognition\dataset\train\E'
generator1 = ImageDataGenerator()
generator2 = ImageDataGenerator()
generator3 = ImageDataGenerator()
anchor_train_batches = generator1.flow_from_directory(train_path+'\Ed_A', target_size=(224, 224), batch_size=batch_size)
positive_train_batches = generator2.flow_from_directory(train_path+'\Ed_P', target_size=(224, 224), batch_size=batch_size)
negative_train_batches = generator3.flow_from_directory(train_path+'\Ed_N', target_size=(224, 224), batch_size=batch_size)
while True:
anchor_imgs, anchor_labels = anchor_train_batches.next()
positive_imgs, positive_labels = positive_train_batches.next()
negative_imgs, negative_labels = negative_train_batches.next()
concat_out = np.concatenate([anchor_labels, positive_labels, negative_labels], axis=-1)
yield ([anchor_imgs, positive_imgs, negative_imgs],
concat_out)
Yes, your generator is using a keras function (for tensors) to concatenate numpy data.
Use numpy.concatenate([anchor_labels, positive_labels, negative_labels], axis=-1).