tf.data.Dataset.from_generator : value error "not enough values to unpack (expected 2, got 1)" - tensorflow

I am currently trying to do a classification problem using a pre-trained transformer model. I wrote a custom generator using tf.data.Dataset.from_generator method. The model takes two inputs : input_id and attn_mask. While calling model.fit i am getting value error "not enough values to unpack (expected 2, got 1)" The received arguments list shows it got both input_id and attn_mask. Can anyone help me solve this?
import tensorflow.keras as keras
from tensorflow.keras.models import Model
from transformers import TFBertModel,BertConfig
def _input_fn():
x = (train_data.iloc[:,0:512]).to_numpy()
y = (train_data.iloc[:,512:516]).to_numpy()
attn = np.asarray(np.tile(attn_mask,x.shape[0]).reshape(-1,512))
def generator():
for s1, s2, l in zip(x, attn, y):
yield {"input_id": s1, "attn_mask": s2}, l
dataset = tf.data.Dataset.from_generator(generator, output_types=({"input_id": tf.int32, "attn_mask": tf.int32}, tf.int32))
#dataset = dataset.batch(2)
#dataset = dataset.shuffle
return dataset
train_data is the dataframe containing the training data(16000 x 516). Last four columns are one hot encoded labels. Since i am not using the Autotokenizer function, i am passing the attention mask as attn_mask.
my model
bert = 'bert-base-uncased'
config = BertConfig(dropout=0.2, attention_dropout=0.2)
config.output_hidden_states = False
transformer_model = TFBertModel.from_pretrained(bert, config = config)
input_ids_in = tf.keras.layers.Input(shape=(512), name='input_id', dtype='int32')
input_masks_in = tf.keras.layers.Input(shape=(512), name='attn_mask', dtype='int32')
embedding_layer = transformer_model(input_ids_in, attention_mask=input_masks_in)[0]
#cls_token = embedding_layer[:,0,:]
#X = tf.keras.layers.BatchNormalization()(cls_token)
X = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(50, return_sequences=True, dropout=0.1, recurrent_dropout=0.1))(embedding_layer)
X = tf.keras.layers.GlobalMaxPool1D()(X)
#X = tf.keras.layers.BatchNormalization()(X)
X = tf.keras.layers.Dense(50, activation='relu')(X)
X = tf.keras.layers.Dropout(0.2)(X)
X = tf.keras.layers.Dense(4, activation='softmax')(X)
model = tf.keras.Model(inputs=[input_ids_in, input_masks_in], outputs = X)
for layer in model.layers[:3]:
layer.trainable = False
optimizer = tf.keras.optimizers.Adam(0.001, beta_1=0.9, beta_2=0.98,
epsilon=1e-9)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['categorical_accuracy'])
epochs = 1
batch_size =2
history = model.fit(_input_fn(), epochs= epochs, batch_size= batch_size, verbose=2)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_16908/300834086.py in <module>
2 batch_size =2
3 #history = model.fit(trainDataGenerator(batch_size), epochs= epochs, validation_data=valDataGenerator(batch_size), verbose=2) #
----> 4 history = model.fit(_input_fn(), epochs= epochs, batch_size= batch_size, verbose=2) #validation_data=val_ds,
~/.local/lib/python3.8/site-packages/keras/utils/traceback_utils.py in error_handler(*args, **kwargs)
65 except Exception as e: # pylint: disable=broad-except
66 filtered_tb = _process_traceback_frames(e.__traceback__)
---> 67 raise e.with_traceback(filtered_tb) from None
68 finally:
69 del filtered_tb
~/.local/lib/python3.8/site-packages/transformers/models/bert/modeling_tf_bert.py in call(self, input_ids, attention_mask, token_type_ids, position_ids, head_mask, inputs_embeds, encoder_hidden_states, encoder_attention_mask, past_key_values, use_cache, output_attentions, output_hidden_states, return_dict, training, **kwargs)
1124 kwargs_call=kwargs,
1125 )
-> 1126 outputs = self.bert(
1127 input_ids=inputs["input_ids"],
1128 attention_mask=inputs["attention_mask"],
~/.local/lib/python3.8/site-packages/transformers/models/bert/modeling_tf_bert.py in call(self, input_ids, attention_mask, token_type_ids, position_ids, head_mask, inputs_embeds, encoder_hidden_states, encoder_attention_mask, past_key_values, use_cache, output_attentions, output_hidden_states, return_dict, training, **kwargs)
771 raise ValueError("You have to specify either input_ids or inputs_embeds")
772
--> 773 batch_size, seq_length = input_shape
774
775 if inputs["past_key_values"] is None:
ValueError: Exception encountered when calling layer "bert" (type TFBertMainLayer).
not enough values to unpack (expected 2, got 1)
Call arguments received:
• input_ids=tf.Tensor(shape=(512,), dtype=int32)
• attention_mask=tf.Tensor(shape=(512,), dtype=int32)
• token_type_ids=None
• position_ids=None
• head_mask=None
• inputs_embeds=None
• encoder_hidden_states=None
• encoder_attention_mask=None
• past_key_values=None
• use_cache=True
• output_attentions=False
• output_hidden_states=False
• return_dict=True
• training=True
• kwargs=<class 'inspect._empty'>
Edit:
Adding the output of calling _input_fn()
<FlatMapDataset shapes: ({input_id: <unknown>, attn_mask: <unknown>}, <unknown>), types: ({input_id: tf.int32, attn_mask: tf.int32}, tf.int32)>

I solved this error by batching my tf.data.Dataset. This gave the TensorSpec in my dataset a shape that had two values to unpack ->
TensorSpec(shape=(16, 200)...
This is what the error refers to.
Solution
print(train_ds) #Before Batching
new_train_ds = train_ds.batch(16, drop_remainder=True)
print(new_train_ds) #After Batching
# Before Batching
<MapDataset element_spec=({'input_ids': TensorSpec(shape=(200,),
dtype=tf.float64, name=None), 'attention_mask': TensorSpec(shape=
(200,), dtype=tf.float64, name=None)}, TensorSpec(shape=(11,),
dtype=tf.float64, name=None))>
# After Batching
<BatchDataset element_spec=({'input_ids': TensorSpec(shape=(16, 200),
dtype=tf.float64, name=None), 'attention_mask': TensorSpec(shape=(16,
200), dtype=tf.float64, name=None)}, TensorSpec(shape=(16, 11),
dtype=tf.float64, name=None))>

Related

ValueError: Input 0 of layer is incompatible with the layer: expected shape=(None, 224, 224, 3), found shape=(224, 224, 3), what is the problem?

I am trying to build a machine learning model using pre-trained VGG16 with tensorflow, but I keep getting the same problem with the shape of the input. Compared to other public codes, the only difference is that I use a tf.data.dataset to share the data, instead of the DirectoryIterator of tf.image
Here is my code:
zip_ref = ZipFile(zip_file, 'r')
zip_ref.extractall(repository_dir)
zip_ref.close()
train_dir = os.path.join(repository_dir, "seg_train", "seg_train")
test_dir = os.path.join(repository_dir, "seg_test", "seg_test")
os.system(f"rm -r {os.path.join(repository_dir, 'seg_pred')}")
# load variables
validation_percentage = 0.2
label_mode = "int"
# for our model purposes
img_size = (224, 224)
color_mode='rgb'
data_train, data_val = image_dataset_from_directory(
train_dir,
batch_size=None,
label_mode=label_mode,
color_mode=color_mode,
image_size=img_size,
validation_split=validation_percentage,
subset="both",
seed=123,
)
data_test = image_dataset_from_directory(
test_dir,
batch_size=None,
label_mode=label_mode,
color_mode=color_mode,
image_size=img_size,
)
classes = data_train.class_names
print(classes)
scale = 1.0/255
normalization_layer = tf.keras.layers.Rescaling(scale)
data_train_norm = data_train.map(lambda x,y: (normalization_layer(x), y))
data_val_norm = data_val.map(lambda x,y: (normalization_layer(x), y))
data_test_norm = data_test.map(lambda x,y: (normalization_layer(x), y))
input_size = None
for img, label in data_train_norm.take(1).as_numpy_iterator():
input_size = img.shape
print(input_size)
base_model = VGG16(
input_shape=input_size, # Shape of our images
include_top = False, # Leave out the last fully connected layer
weights = 'imagenet'
)
# we do not train the parameters
for layer in base_model.layers:
layer.trainable = False
# Flatten the output layer to 1 dimension
x = layers.Flatten()(base_model.output)
# https://medium.com/analytics-vidhya/car-brand-classification-using-vgg16-transfer-learning-f219a0f09765
# FC layer very simple and with a softmax activation unit
x = layers.Dense(len(classes), activation="softmax")(x)
landscapeModel01 = Model(inputs=base_model.input, outputs=x, name="landscapeModel01")
loss = "sparse_categorical_crossentropy"
optimizer = "adam"
landscapeModel01.compile(
optimizer=optimizer,
loss=loss,
metrics=["loss","accuracy"]
)
#fit data
shuffle=True # variable
epochs=50 # variable, according if it is able to converge
batch_size = 200
print(landscapeModel01.input)
landscapeModel01.fit(
data_train_norm,
validation_data=data_val_norm,
epochs=epochs,
shuffle=shuffle,
batch_size=batch_size
)
and this is the error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In [10], line 8
4 batch_size = 200
6 print(landscapeModel01.input)
----> 8 landscapeModel01.fit(
9 data_train_norm,
10 validation_data=data_val_norm,
11 epochs=epochs,
12 shuffle=shuffle,
13 batch_size=batch_size
14 )
File ~/anaconda3/envs/faa/lib/python3.10/site-packages/keras/utils/traceback_utils.py:70, in filter_traceback.<locals>.error_handler(*args, **kwargs)
67 filtered_tb = _process_traceback_frames(e.__traceback__)
68 # To get the full stack trace, call:
69 # `tf.debugging.disable_traceback_filtering()`
---> 70 raise e.with_traceback(filtered_tb) from None
71 finally:
72 del filtered_tb
File /tmp/__autograph_generated_file8y_bf523.py:15, in outer_factory.<locals>.inner_factory.<locals>.tf__train_function(iterator)
13 try:
14 do_return = True
---> 15 retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope)
16 except:
17 do_return = False
ValueError: in user code:
File "/home/renan/anaconda3/envs/faa/lib/python3.10/site-packages/keras/engine/training.py", line 1160, in train_function *
return step_function(self, iterator)
File "/home/renan/anaconda3/envs/faa/lib/python3.10/site-packages/keras/engine/training.py", line 1146, in step_function **
outputs = model.distribute_strategy.run(run_step, args=(data,))
File "/home/renan/anaconda3/envs/faa/lib/python3.10/site-packages/keras/engine/training.py", line 1135, in run_step **
outputs = model.train_step(data)
File "/home/renan/anaconda3/envs/faa/lib/python3.10/site-packages/keras/engine/training.py", line 993, in train_step
y_pred = self(x, training=True)
File "/home/renan/anaconda3/envs/faa/lib/python3.10/site-packages/keras/utils/traceback_utils.py", line 70, in error_handler
raise e.with_traceback(filtered_tb) from None
File "/home/renan/anaconda3/envs/faa/lib/python3.10/site-packages/keras/engine/input_spec.py", line 295, in assert_input_compatibility
raise ValueError(
ValueError: Input 0 of layer "landscapeModel01" is incompatible with the layer: expected shape=(None, 224, 224, 3), found shape=(224, 224, 3)
What can I fix to make the code work?
versions:
tensorflow==2.10.0
#EDIT
I just found the solution: I was loading images with a batch size equals none, but the trained model demanded that the images had one, even if it was 1.
Solution
I just needed to load images in the image_dataset_from_directory with a batch_size parameter different from None. Considering my investigation did not consider data augmentation in the beginning, I chose 1.

embedding for categorical variable and pass to keras network

I have tabular data with two columns , one is input feature and anther one is target variable.
I have converted the input feature to embeddings and pass on to Keras model layer, getting error while executing fit method.
here is the code which i have used for this.
df is the input dataframe and contains two columns.
X = df.drop(columns = ['data_type']).copy()
y = df['data_type']
X_train, X_rem, y_train, y_rem = train_test_split(X,y, train_size=0.8)
X_valid, X_test, y_valid, y_test = train_test_split(X_rem,y_rem, test_size=0.5)
Y_train=pd.DataFrame({'data_type':y_train})
Y_valid=pd.DataFrame({'data_type':y_valid})
Y_test=pd.DataFrame({'data_type':y_test})
enc = OrdinalEncoder()
X_train[["data"]] = enc.fit_transform(X_train[["data"]])
X_valid[["data"]] = enc.fit_transform(X_valid[["data"]])
X_test[["data"]] = enc.fit_transform(X_test[["data"]])
X_train_actual = []
X_train_actual.append(np.array(X_train["data"]).reshape(-1,1))
X_valid_actual = []
X_valid_actual.append(np.array(X_valid["data"]).reshape(-1,1))
Y_train["data_type"] = LabelEncoder().fit_transform(Y_train["data_type"])
Y_valid["data_type"] = LabelEncoder().fit_transform(Y_valid["data_type"])
Y_test["data_type"] = LabelEncoder().fit_transform(Y_test["data_type"])
Y_train_actual= to_categorical(Y_train.to_numpy())
Y_valid_actual= to_categorical(Y_valid.to_numpy())
embedding_size = 50
categories = 7
inputs = Input(shape=(1,))
embedding_layer = Embedding(categories,
embedding_size,
embeddings_regularizer=regularizers.l2(0.01),
input_length=1)(inputs)
cat_input_layers = Reshape(target_shape=(embedding_size,))(embedding_layer)
building the layers is as follows.
dense_1 = Dense(512, activation='relu', kernel_regularizer=regularizers.l2(0.01))(cat_input_layers)
final_out = Dense(7, activation='softmax')(dense_1)
model = keras.Model(inputs=inputs,outputs=final_out)
optimizer = tf.keras.optimizers.Adam(learning_rate=0.00001)
model.compile(loss='mse', optimizer=optimizer, metrics=['mae', 'mse'])
checkpoint = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
save_weights_only=True,
verbose=1)
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=5)
history = model.fit(X_train_actual,
Y_train_actual,
batch_size=100,
epochs=500,
validation_data =(X_valid_actual, Y_valid_actual),
callbacks=[checkpoint, early_stop],
verbose=1)
getting the error when i am executing the fit call.
InvalidArgumentError Traceback (most recent call last)
Cell In [336], line 1
----> 1 history = model.fit(X_train_actual,
2 Y_train_actual,
3 batch_size=100,
4 epochs=500,
5 validation_data =(X_valid_actual, Y_valid_actual),
6 callbacks=[checkpoint, early_stop],
7 verbose=1)
File ~\Anaconda3\envs\keras-tf-tcb\lib\site-packages\keras\utils\traceback_utils.py:70, in filter_traceback.<locals>.error_handler(*args, **kwargs)
67 filtered_tb = _process_traceback_frames(e.__traceback__)
68 # To get the full stack trace, call:
69 # `tf.debugging.disable_traceback_filtering()`
---> 70 raise e.with_traceback(filtered_tb) from None
71 finally:
72 del filtered_tb
any idea, what exactly the issue,

TF2/Keras TextVectorization reshaping dimensions

I was following TensorFlow tutorial on text classification (link), and the example is running fine, but when try to apply same steps on different dataset I'm constantly getting error that I'm unable to debug.
In tutorial they downloaded the data and used different data loader so that might be one of the issues, the other thing I suspect is vectorize_text function where dimensions are getting expanded, but I've tried almost everything I can imagine but no success.
CSV file that I'm using contains 2 columns, one with text data and other one is multiclass label.
From the error below, it seems that TextVectorization outputs tensor of shape (batch_size, 250), while model needs something like (batch_size, 250, 1) I guess?
Below is the code that I used
from sklearn.model_selection import train_test_split
import tensorflow as tf
import re
import numpy as np
import pandas as pd
import string
# load and split data
df = pd.read_csv('train.csv', index_col=[0])
X_train, X_test, y_train, y_test = train_test_split(df[['text']], pd.get_dummies(df['target']).values, test_size=0.2, random_state=1)
X_val, X_test, y_val, y_test = train_test_split(X_test, y_test, test_size=0.5, random_state=1)
# convert to tf dataset
raw_train_ds = tf.data.Dataset.from_tensor_slices((X_train, y_train))
raw_val_ds = tf.data.Dataset.from_tensor_slices((X_val, y_val))
raw_test_ds = tf.data.Dataset.from_tensor_slices((X_test, y_test))
# text cleanup
def custom_standardization(input_data):
new_line_replace = tf.strings.regex_replace(input_data, '\n', ' ')
non_alphanum_replace = tf.strings.regex_replace(new_line_replace, '[^a-zA-Z0-9_ ]', '')
stripped = tf.strings.strip(non_alphanum_replace)
lowercase = tf.strings.lower(stripped)
return tf.strings.regex_replace(lowercase,
'[%s]' % re.escape(string.punctuation),
'')
# creating layer for text vectoriazation
max_features = 10000
sequence_length = 250
vectorize_layer = tf.keras.layers.TextVectorization(
standardize=custom_standardization,
max_tokens=max_features,
output_mode='int',
output_sequence_length=sequence_length)
train_text = raw_train_ds.map(lambda x, y: x)
vectorize_layer.adapt(train_text)
def vectorize_text(text, label):
text = tf.expand_dims(text, -1)
return vectorize_layer(text), label
train_ds = raw_train_ds.map(vectorize_text)
val_ds = raw_val_ds.map(vectorize_text)
test_ds = raw_test_ds.map(vectorize_text)
train_ds = train_ds.cache().prefetch(buffer_size=tf.data.AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=tf.data.AUTOTUNE)
test_ds = test_ds.cache().prefetch(buffer_size=tf.data.AUTOTUNE)
model = tf.keras.Sequential([
vectorize_layer,
tf.keras.layers.Embedding(max_features + 1, 16),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.GlobalAveragePooling1D(),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(4)
])
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
epochs = 10
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs)
And this is the error I'm getting:
Epoch 1/100 WARNING:tensorflow:Model was constructed with shape
(None,) for input KerasTensor(type_spec=TensorSpec(shape=(None,),
dtype=tf.string, name='text_vectorization_2_input'),
name='text_vectorization_2_input', description="created by layer
'text_vectorization_2_input'"), but it was called on an input with
incompatible shape (None, 250). Output exceeds the size limit. Open
the full output data in a text editor
--------------------------------------------------------------------------- ValueError Traceback (most recent call
last) in
1 epochs = 100
----> 2 history = model.fit(
3 train_ds,
4 validation_data=val_ds,
5 epochs=epochs)
c:\Users\panto\anaconda3\lib\site-packages\keras\utils\traceback_utils.py
in error_handler(*args, **kwargs)
65 except Exception as e: # pylint: disable=broad-except
66 filtered_tb = _process_traceback_frames(e.traceback)
---> 67 raise e.with_traceback(filtered_tb) from None
68 finally:
69 del filtered_tb
c:\Users\panto\anaconda3\lib\site-packages\tensorflow\python\framework\func_graph.py
in autograph_handler(*args, **kwargs) 1145 except
Exception as e: # pylint:disable=broad-except 1146 if
hasattr(e, "ag_error_metadata"):
-> 1147 raise e.ag_error_metadata.to_exception(e) 1148 else: 1149 raise
ValueError: in user code: ...
When using TextVectorization to tokenize strings, the input rank must be 1 or the last shape dimension must be 1. Received:
inputs.shape=(None, 250) with rank=2
Call arguments received:
• inputs=tf.Tensor(shape=(None, 250), dtype=string)
Edit:
Update:
Data sample looks like this:
text
target
'such a lovely day'
'a'
'not so great'
'b'
'hello world'
'c'
... etc - in total 4 classes
Instead of vectorize_text function I've moved code to custom_standardization and it works now
def custom_standardization(input_data):
new_line_replace = tf.strings.regex_replace(input_data, '\n', ' ')
non_alphanum_replace = tf.strings.regex_replace(new_line_replace, '[^a-zA-Z0-9_ ]', '')
stripped = tf.strings.strip(non_alphanum_replace)
lowercase = tf.strings.lower(stripped)
return tf.expand_dims(tf.strings.regex_replace(lowercase,
'[%s]' % re.escape(string.punctuation),
''), -1)
new issue is target doesn't match - I get error although I one hot encoded variables
ValueError: Shapes (4, 1) and (None, 4) are incompatible
Try changing "categorical_crossentropy" to "sparse_categortical_crossentropy" as described here

ValueError: The `batch_size` argument must not be specified for the given input type

I have created dummy data for an autoencoder model using tf.data.dataset. I am using tensorflow-1.15.x, keras 2.3.1 and numpy 1.19.5 for running on my GPU.
N = 5000
H = 128
W = 128
C = 2
train_data = np.random.randn(N,H,W,C)
train_data = tf.convert_to_tensor(train_data)
test_data = np.random.randn(500,H,W,C)
test_data = tf.convert_to_tensor(test_data)
batch_size = 1
train_dataset = tf.data.Dataset.from_tensor_slices((train_data, train_data))
train_dataset = train_dataset.batch(batch_size, drop_remainder=True)
test_dataset = tf.data.Dataset.from_tensor_slices((test_data, test_data))
test_dataset = test_dataset.batch(batch_size, drop_remainder=True)
But while fitting this data on the model, I get the following error -
epochs = 5
rms = RMSprop(learning_rate=0.00002,
rho=0.9,
epsilon=1e-07)
model.compile(loss='mean_squared_error', optimizer=rms, metrics=['mean_squared_error'])
callback = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=3)
logs = "logs/"
tboard_callback = tf.keras.callbacks.TensorBoard(log_dir = logs,
histogram_freq = 1)
history = model.fit(train_dataset, epochs=epochs, batch_size=batch_size, callbacks=[callback, tboard_callback],
validation_data=test_dataset)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-25-47134a802115> in <module>()
15
16 history = model.fit(train_dataset, epochs=epochs, batch_size=batch_size, callbacks=[callback, tboard_callback],
---> 17 validation_data=test_dataset)
2 frames
/tensorflow-1.15.2/python3.7/tensorflow_core/python/keras/engine/training.py in _validate_or_infer_batch_size(self, batch_size, steps, x)
1813 'The `batch_size` argument must not be specified for the given '
1814 'input type. Received input: {}, batch_size: {}'.format(
-> 1815 x, batch_size))
1816 return
1817
ValueError: The `batch_size` argument must not be specified for the given input type. Received input: <DatasetV1Adapter shapes: ((1, 128, 128, 2), (1, 128, 128, 2)), types: (tf.float64, tf.float64)>, batch_size: 1
Answers to other questions on this error suggest batching both train and validation datasets, but I have batched both already. What could be causing this error? Thanks.
Remove the batch_size in model.fit()
history = model.fit(train_dataset, epochs=epochs, callbacks=[callback, tboard_callback],validation_data=test_dataset)

keras triplet loss crashes when training

I am trying to implement a simple face recognition application but I have been stuck with a problem for days now. Hopefully someone having more experience in the subject can help. Fingers crossed.
Here is the program:
import tensorflow as tf
#from keras.applications.vgg16 import VGG16
from keras.applications.resnet50 import ResNet50, preprocess_input
from keras.preprocessing import image
#import PIL
#from PIL import Image
from keras.models import Model
from keras.layers import Dense, Input, subtract, concatenate, Lambda, add, maximum
from keras import backend as K
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
import numpy as np
def identity_loss(y_true, y_pred):
return K.mean(y_pred - 0 * y_true)
def triplet_loss(inputs, dist='euclidean', margin='maxplus'):
anchor, positive, negative = inputs
positive_distance = K.square(anchor - positive)
negative_distance = K.square(anchor - negative)
if dist == 'euclidean':
positive_distance = K.sqrt(K.sum(positive_distance, axis=-1, keepdims=True))
negative_distance = K.sqrt(K.sum(negative_distance, axis=-1, keepdims=True))
elif dist == 'sqeuclidean':
positive_distance = K.sum(positive_distance, axis=-1, keepdims=True)
negative_distance = K.sum(negative_distance, axis=-1, keepdims=True)
loss = positive_distance - negative_distance
if margin == 'maxplus':
loss = K.maximum(0.0, 1 + loss)
elif margin == 'softplus':
loss = K.log(1 + K.exp(loss))
return K.mean(loss)
model = ResNet50(weights='imagenet')
model.layers.pop()
x = model.get_layer('flatten_1').output
model_out = Dense(128, activation='relu', name='model_out')(x)
model_out = Lambda(lambda x: K.l2_normalize(x,axis=-1))(model_out)
new_model = Model(inputs=model.input, outputs=model_out)
anchor_input = Input(shape=(224, 224, 3), name='anchor_input')
pos_input = Input(shape=(224, 224, 3), name='pos_input')
neg_input = Input(shape=(224, 224, 3), name='neg_input')
encoding_anchor = new_model(anchor_input)
encoding_pos = new_model(pos_input)
encoding_neg = new_model(neg_input)
loss = Lambda(triplet_loss)([encoding_anchor, encoding_pos, encoding_neg])
siamese_network = Model(inputs = [anchor_input, pos_input, neg_input],
outputs = loss)
siamese_network.compile(optimizer=Adam(lr=.00001), loss=identity_loss)
######################### For reading img path info - start ##########
train_path1 = '/home/cesncn/Desktop/github_projects/face_recog_proj_with_triplet_loss/training_img_pairs.csv'
TRAIN_INPUT_PATHS = [train_path1]
RECORD_DEFAULTS_TRAIN = [[0], [''], [''], ['']]
def decode_csv_train(line):
parsed_line = tf.decode_csv(line, RECORD_DEFAULTS_TRAIN)
anchor_path = parsed_line[1]
pos_path = parsed_line[2]
neg_path = parsed_line[3]
return anchor_path, pos_path, neg_path
######################### For reading img path info - end ##########
batch_size = 16
filenames = tf.placeholder(tf.string, shape=[None])
dataset = tf.data.Dataset.from_tensor_slices(filenames)
dataset = dataset.flat_map(lambda filename: tf.data.TextLineDataset(filename).skip(1).map(decode_csv_train))
dataset = dataset.shuffle(buffer_size=1000)
dataset = dataset.batch(batch_size)
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()
init_global_var = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init_global_var)
nr_epochs = 5
for i in range(0, nr_epochs):
print("\nnr_epoch: ", str(i), "\n")
sess.run(iterator.initializer, feed_dict={filenames: TRAIN_INPUT_PATHS})
while True:
try:
anchor_path, pos_path, neg_path = sess.run(next_element)
anchor_imgs = np.empty((0, 224, 224, 3))
pos_imgs = np.empty((0, 224, 224, 3))
neg_imgs = np.empty((0, 224, 224, 3))
for j in range (0, len(anchor_path)):
anchor_img = image.load_img(anchor_path[j], target_size=(224, 224))
anchor_img = image.img_to_array(anchor_img)
anchor_img = np.expand_dims(anchor_img, axis=0)
anchor_img = preprocess_input(anchor_img)
anchor_imgs = np.append(anchor_imgs, anchor_img, axis=0)
pos_img = image.load_img(pos_path[j], target_size=(224, 224))
pos_img = image.img_to_array(pos_img)
pos_img = np.expand_dims(pos_img, axis=0)
pos_img = preprocess_input(pos_img)
pos_imgs = np.append(pos_imgs, pos_img, axis=0)
neg_img = image.load_img(neg_path[j], target_size=(224, 224))
neg_img = image.img_to_array(neg_img)
neg_img = np.expand_dims(neg_img, axis=0)
neg_img = preprocess_input(neg_img)
neg_imgs = np.append(neg_imgs, neg_img, axis=0)
# HERE IT CRASHES WHEN I CALL THE FIT FUNCTION! ! !
siamese_network.fit([anchor_imgs, pos_imgs, neg_imgs],
batch_size = batch_size,
epochs = 1,
verbose = 2)
except tf.errors.OutOfRangeError:
print("Out of range error triggered (looped through training set 1 time)")
break
When I call the function siamese_network.fit(...), it crashes and gives the following error, which tells me absolutely nothing!!
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-16-65401d04281c> in <module>()
61 batch_size = batch_size,
62 epochs = 1,
---> 63 verbose = 2)
64
65 #siamese_network.fit({'anchor_input': anchor_imgs, 'pos_input': pos_imgs, 'neg_input': neg_imgs},
~/anaconda3/envs/tensorflow/lib/python3.6/site-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)
1628 sample_weight=sample_weight,
1629 class_weight=class_weight,
-> 1630 batch_size=batch_size)
1631 # Prepare validation data.
1632 do_validation = False
~/anaconda3/envs/tensorflow/lib/python3.6/site-packages/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_array_lengths, batch_size)
1485 sample_weights = [_standardize_weights(ref, sw, cw, mode)
1486 for (ref, sw, cw, mode)
-> 1487 in zip(y, sample_weights, class_weights, self._feed_sample_weight_modes)]
1488
1489 if check_array_lengths:
~/anaconda3/envs/tensorflow/lib/python3.6/site-packages/keras/engine/training.py in <listcomp>(.0)
1484 self._feed_output_names)
1485 sample_weights = [_standardize_weights(ref, sw, cw, mode)
-> 1486 for (ref, sw, cw, mode)
1487 in zip(y, sample_weights, class_weights, self._feed_sample_weight_modes)]
1488
~/anaconda3/envs/tensorflow/lib/python3.6/site-packages/keras/engine/training.py in _standardize_weights(y, sample_weight, class_weight, sample_weight_mode)
538 else:
539 if sample_weight_mode is None:
--> 540 return np.ones((y.shape[0],), dtype=K.floatx())
541 else:
542 return np.ones((y.shape[0], y.shape[1]), dtype=K.floatx())
AttributeError: 'NoneType' object has no attribute 'shape'
Does anyone have any idea about how to solve this?
I have been tyring to implement several variations of the triplet loss function. The above version is just one of the tries...
Anyhow, in the version above, the problem appears to be the following:
Here is how I create and compile the model:
siamese_network = Model(inputs = [anchor_input, pos_input, neg_input],
outputs = loss)
siamese_network.compile(optimizer=Adam(lr=.00001), loss=identity_loss)
Obviously, I say here that there is an output from the model, called "loss".
And later when I train the model, I set the y to null in the fit function. Big mistake.
z = [0] # ADDED LINE
siamese_network.fit(x = [anchor_imgs, pos_imgs, neg_imgs],
y = z # ADDED LINE
batch_size = batch_size,
epochs = 1,
verbose = 2)
And this fix solved the problem.
I rather chose to answer rather than deleting the question. Hopefully it helps others who may have a similar problem..
PS. y is set to NULL by default if it is not set to anything in Keras.