Tensorflow expected 2 inputs but received 1 input tensor - python

Hey guys so I'm building a model based on the Roberta-Base and at the end when I try to fit the model I get a error saying: ValueError: Layer model_39 expects 2 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(16, 128) dtype=float64>]
I'm using tf.data.Dataset to make the dataset:
def map_dataset(ids, masks, labels):
return {'input_ids': ids, 'input_mask': masks}, labels
# Create dataset
dataset = tf.data.Dataset.from_tensor_slices((ids, mask, labels))
dataset.map(map_dataset)
dataset = dataset.shuffle(10000).batch(BATCH_SIZE, drop_remainder=True)
Supposedly dataset is generating 2 inputs properly but for some reason fit is refusing to work and I'm not sure why.
Full code:
LEN_SEQ = 128
BATCH_SIZE = 16
TEST_TRAIN_SPLIT = 0.9
TRANSFORMER = 'roberta-base'
# Load roberta model
base_model = TFAutoModel.from_pretrained('roberta-base')
for layer in base_model.layers:
layer.trainable = False
# Define input layers
input_ids = tf.keras.layers.Input(shape=(LEN_SEQ,), name='input_ids', dtype='int32')
input_mask = tf.keras.layers.Input(shape=(LEN_SEQ,), name='input_mask', dtype='int32')
# Define hidden layers
embedding = base_model([input_ids, input_mask])[1]
layer = tf.keras.layers.Dense(LEN_SEQ * 2, activation='relu')(embedding)
layer = tf.keras.layers.Dense(LEN_SEQ, activation='relu')(layer)
# Define output
output = tf.keras.layers.Dense(1, activation='softmax', name='output')(layer)
model = tf.keras.Model(inputs=[input_ids, input_mask], outputs=[output])
model.compile(
optimizer = Adam(learning_rate=1e-3, decay=1e-4),
loss = CategoricalCrossentropy(),
metrics = [
CategoricalAccuracy('accuracy')
]
)
# Load data
df = pd.read_csv('train-processed.csv')
df = df.head(100)
samples_count = len(df)
# Tokenize data
tokenizer = AutoTokenizer.from_pretrained(TRANSFORMER)
tokens = tokenizer(
df['first_Phrase'].tolist(),
max_length=LEN_SEQ,
truncation=True,
padding='max_length',
add_special_tokens=True,
return_tensors='tf'
)
ids = tokens['input_ids']
mask = tokens['attention_mask']
def map_dataset(ids, masks, labels):
return {'input_ids': ids, 'input_mask': masks}, labels
# Create dataset
dataset = tf.data.Dataset.from_tensor_slices((ids, mask, labels))
dataset.map(map_dataset)
dataset = dataset.shuffle(10000).batch(BATCH_SIZE, drop_remainder=True)
# Split data intro train and test
train_size = int((samples_count / BATCH_SIZE) * TEST_TRAIN_SPLIT)
train = dataset.take(train_size)
test = dataset.skip(train_size)
# Train model
history = model.fit(
train,
validation_data=test,
epochs=2
)
Inside dataset -> <BatchDataset shapes: ((16, 128), (16, 128), (16, 5)), types: (tf.float64, tf.float64, tf.float64)>
Inside train -> <TakeDataset shapes: ((16, 128), (16, 128), (16, 5)), types: (tf.float64, tf.float64, tf.float64)>
Data example:
Any help appreciated. I'm new to transformers so please feel free to point any extra considerations.

So I managed to fix this as far as I know with the help of #Djinn.
I did remove dataset API and instead built my own datasets manually using the following code:
# Split into training and validation sets
train_size = int(samples_count * TEST_TRAIN_SPLIT)
train = [ids[:train_size], mask[:train_size]]
train_labels = labels[:train_size]
test = [ids[train_size:], mask[train_size:]], labels[train_size:]
# Train model
history = model.fit(
train, train_labels,
validation_data=test,
epochs=10
)
This seems to be working and fit() accepted this data, but feel free to point out if this is wrong or could be made differently.

Related

a mismatch between the current graph and the graph

I am trying to train encoder decoder model with multispectral images having 9 channels but the code that i am running is downloading pretrained resnet101 weights which is trained on 3 channel images.
Input Given by me:
net_input = tf.placeholder(tf.float32,shape=[None,None,None,9])
net_output = tf.placeholder(tf.float32,shape=[None,None,None,num_classes])
code for getting pretrained weights for Resnet101:
if args.model == "ResNet101" or args.model == "ALL":
subprocess.check_output(['wget','http://download.tensorflow.org/models/resnet_v2_101_2017_04_14.tar.gz', "-P", "models"])
try:
subprocess.check_output(['tar', '-xvf', 'models/resnet_v2_101_2017_04_14.tar.gz', "-C", "models"])
subprocess.check_output(['rm', 'models/resnet_v2_101_2017_04_14.tar.gz'])
except Exception as e:
print(e)
pass
error that i am getting is:
error:
Invalid argument: Assign requires shapes of both tensors to match. lhs shape= [7,7,9,64] rhs
shape= [7,7,3,64]
what can be the solution here?
If you do not want to change the channels of input from 9 to 3, you need to change ResNet architecture input and second layer from 3 to 9 channels and add the final layers for inference. Notice, you will have to train it again.
Here is a full code, as an example, you just have to change channels to 9:
import matplotlib.pyplot as plt
import numpy as np
import os
import tensorflow as tf
_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)
PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')
train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')
BATCH_SIZE = 32
IMG_SIZE = (160, 160)
train_dataset = tf.keras.utils.image_dataset_from_directory(train_dir,
shuffle=True,
batch_size=BATCH_SIZE,
image_size=IMG_SIZE)
validation_dataset = tf.keras.utils.image_dataset_from_directory(validation_dir,
shuffle=True,
batch_size=BATCH_SIZE,
image_size=IMG_SIZE)
class_names = train_dataset.class_names
val_batches = tf.data.experimental.cardinality(validation_dataset)
test_dataset = validation_dataset.take(val_batches // 5)
validation_dataset = validation_dataset.skip(val_batches // 5)
AUTOTUNE = tf.data.AUTOTUNE
train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)
validation_dataset = validation_dataset.prefetch(buffer_size=AUTOTUNE)
test_dataset = test_dataset.prefetch(buffer_size=AUTOTUNE)
preprocess_input = tf.keras.applications.ResNet50.preprocess_input
# Create the base model from the pre-trained model ResNet50
############### HERE YOU CHANGE TO 9 CHANNELS ###############
channels=3
IMG_SHAPE = IMG_SIZE + (channels,)
base_model = tf.keras.applications.ResNet50(input_shape=IMG_SHAPE,
include_top=True,
weights='imagenet')
image_batch, label_batch = next(iter(train_dataset))
feature_batch = base_model(image_batch)
print(feature_batch.shape)
base_model.summary()
## HERE IS WHERE THE MAGIC HAPPENS
base_model_config = base_model.get_config()
#### HERE THE CHANNELS WILL BE ALTERED TO 9 ####
base_model_config['layers'][0]["config"]["batch_input_shape"]=(None, 160, 160, channels)
base_model_config['layers'][1]["config"]["padding"]=((channels,channels), (channels,channels))
#######################################################
model=tf.keras.Model().from_config(base_model_config)
model.summary()
### HERE YOU ADD THE FINAL LAYERS FOR INFERENCE
inputs = tf.keras.Input(shape=(160, 160, channels))
x = base_model(inputs, training=False)
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dropout(0.2)(x)
outputs = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, outputs)
base_learning_rate = 0.0001
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=base_learning_rate),
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(x=train_dataset, epochs=2)
If there is any shape mismatch in the middle of the way, you know how to change it: base_model_config['layers'][x]....=........
There are a few resources about this idea, such as a blog post about transferring a ResNet on RGB data to multi-channel images here, and a relevant Colab Notebook. Below is a working example based on those resources:
import numpy as np
import tensorflow as tf
def tile_kernels(kernel, out_channels, batch_dim=-2):
mean_1d = np.mean(kernel, axis=batch_dim).reshape(kernel[:, :, -1:, :].shape)
tiled = np.tile(mean_1d, (out_channels, 1))
return tiled
def reshape_model_input(model_orig, custom_model, input_channels):
conf = custom_model.get_config()
layer_to_modify = conf["layers"][2]["config"]["name"]
layer_names = [conf['layers'][x]['name'] for x in range(len(conf['layers']))]
for layer in model_orig.layers:
if layer.name in layer_names:
if layer.get_weights() != []:
target_layer = custom_model.get_layer(layer.name)
if layer.name == layer_to_modify:
kernels, biases = layer.get_weights()
kernels_extra_channels = np.concatenate((kernels,
tile_kernels(kernels, input_channels - 3)),
axis=-2)
target_layer.set_weights([kernels_extra_channels, biases])
else:
target_layer.set_weights(layer.get_weights())
if __name__ == "__main__":
from tensorflow.keras.applications import ResNet50V2
resnet50 = ResNet50V2(weights='imagenet', include_top=False) # load resnet50 here - can be done differently
config = resnet50.get_config()
img_height = ...
img_width = ...
input_channels = 7
config["layers"][0]["config"]["batch_input_shape"] = (None, img_height, img_width, input_channels) # change the batch input shape to handle the different channel dimensions
custom_resnet = tf.keras.models.Model.from_config(config)
reshape_model_input(resnet50, custom_resnet, input_channels) # modify the custom model by reference
custom_resnet(np.zeros((1, img_width, img_height, input_channels))) # just verifying that predicting with the new shape works in the custom model
This process just iterates over each layer in the original model and sets the corresponding weights in the custom model. To produce the additional n 3 x 3 channels (in your case, n = 4, as you want 7 total channels) for the input, the mean is taken across the 3 RGB dimensions then replicated (as can be seen in the tile_kernels function). Another aggregation function could be used, such as the max, min, median, etc. If you don't want any of the weights from the original model (as in, not pretraining but just require the architecture), just modifying the original model's configuration and creating a new model from it will create a randomly initialized model:
resnet50 = ...
config = resnet50.get_config()
img_height = ...
img_width = ...
input_channels = ...
config["layers"][0]["config"]["batch_input_shape"] = (None, img_height, img_width, input_channels)
custom_resnet = tf.keras.models.Model.from_config(config)

Bidirectional LSTM and problems with incorrect text output

Good afternoon everyone. I started studying recursive neural networks not long ago, so I will be glad for any advice.
Today I tried to use bidirectional LSTM layers and ran into the problem of poor text generation.
Used my 400kBt dataset for testing.
<pre>
BUFFER_SIZE = 10000
BATCH_SIZE = 64
dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE, drop_remainder=True)
vocab_size = len(vocab)
embedding_dim = 512 #256
rnn_units = 512
def build_model( vocab_size, embedding_dim, rnn_units, batch_size):
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim,
batch_input_shape=[batch_size, None]),
tf.keras.layers.LSTM(rnn_units,
return_sequences=True, stateful=True,
recurrent_initializer='glorot_uniform'),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(rnn_units, return_sequences=True, input_shape=expanded_input.shape)),
tf.keras.layers.Dense(vocab_size)
])
return model
model = build_model(
vocab_size = len(vocab),
embedding_dim=embedding_dim,
rnn_units=rnn_units,
batch_size=BATCH_SIZE)
model.summary()
</pre>
to define expanded_input.shape i used this code
<pre>
input_data = tf.random.normal((BATCH_SIZE, 32))
repeated_input = tf.reshape(tf.repeat(input = input_data, repeats = 5, axis=1), shape=(BATCH_SIZE, 5, 32))
expanded_input = tf.expand_dims(input=input_data, axis=1)
</pre>
for the text generation function, this part of the code was used
<pre>
def generate_text(model, num_generate, temperature, start_string):
input_eval = [char2idx[s] for s in start_string] # string to numbers (vectorizing)
input_eval = tf.expand_dims(input_eval, 0) # dimension expansion
text_generated = [] # Empty string to store our results
model.reset_states() # Clears the hidden states in the RNN
for i in range(num_generate): #Run a loop for number of characters to generate
predictions = model(input_eval) # prediction for single character
predictions = tf.squeeze(predictions, 0) # remove the batch dimension
predictions = predictions / temperature
predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy()
input_eval = tf.expand_dims([predicted_id], 0)
text_generated.append(idx2char[predicted_id])
return (start_string + ''.join(text_generated))
</pre>
As a result, the output is mostly similar to this
чЦОMm🙌"f
😩✌👐jБУ🔥р'!🏻i{⬇dё6😂👆nU52г
👉И🏻T➕И7😁y👐рг😬л🏻Хж‍<tCП⃣“Уи🔻п😕н—В👆И2⏩💪RТ😬Ют🙂Ё♂5jЩpКГлш-nu5Цf⏩
NёФЁУЁ"🔥n⬇4🙃r😬uy⏩😂ч⏩C​ALfЛФcЁё»йx😤М

how do you pass text to tensorflow model to return prediction

New to tf/python and have created a model that classifies text with a toxicity level (obscene, toxic, threat, etc). This is what I have so far and it does produce the summary, so I know it is loading correctly. How do I pass text to the model to return a prediction? Any help would be much appreciated.
import os
import numpy as np
import tensorflow as tf
from tensorflow import keras
checkpoint_path = "tf_model/the_model/saved_model.pb"
checkpoint_dir = os.path.dirname(checkpoint_path)
new_model = tf.keras.models.load_model(checkpoint_dir)
# Check its architecture
new_model.summary()
inputs = [
"tenserflow seems like it fits the bill but there are zero tutorials that outline how to reuse a model in a production environment "
]
predictions = new_model.predict(inputs)
print(predictions)
I get many error messages, some of the long winded ones are as follows:
WARNING:tensorflow:Model was constructed with shape (None, 150) for input KerasTensor(type_spec=TensorSpec(shape=(None, 150), dtype=tf.float32, name='input_1'), name='input_1', description="created by layer 'input_1'"), but it was called on an input with incompatible shape (None, 1).
ValueError: Negative dimension size caused by subtracting 3 from 1 for '{{node model/conv1d/conv1d}} = Conv2D[T=DT_FLOAT, data_format="NHWC", dilations=[1, 1, 1, 1], explicit_paddings=[], padding="VALID", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](model/conv1d/conv1d/ExpandDims, model/conv1d/conv1d/ExpandDims_1)' with input shapes: [?,1,1,256], [1,3,256,64].
This is the py code used to create and test it/prediction which works perfectly:
import tensorflow as tf
import numpy as np
import pandas as pd
import os
TRAIN_DATA = "datasets/train.csv"
GLOVE_EMBEDDING = "embedding/glove.6B.100d.txt"
train = pd.read_csv(TRAIN_DATA)
train["comment_text"].fillna("fillna")
x_train = train["comment_text"].str.lower()
y_train = train[["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"]].values
max_words = 100000
max_len = 150
embed_size = 100
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=max_words, lower=True)
tokenizer.fit_on_texts(x_train)
x_train = tokenizer.texts_to_sequences(x_train)
x_train = tf.keras.preprocessing.sequence.pad_sequences(x_train, maxlen=max_len)
embeddings_index = {}
with open(GLOVE_EMBEDDING, encoding='utf8') as f:
for line in f:
values = line.rstrip().rsplit(' ')
word = values[0]
embed = np.asarray(values[1:], dtype='float32')
embeddings_index[word] = embed
word_index = tokenizer.word_index
num_words = min(max_words, len(word_index) + 1)
embedding_matrix = np.zeros((num_words, embed_size), dtype='float32')
for word, i in word_index.items():
if i >= max_words:
continue
embedding_vector = embeddings_index.get(word)
if embedding_vector is not None:
embedding_matrix[i] = embedding_vector
input = tf.keras.layers.Input(shape=(max_len,))
x = tf.keras.layers.Embedding(max_words, embed_size, weights=[embedding_matrix], trainable=False)(input)
x = tf.keras.layers.Bidirectional(tf.keras.layers.GRU(128, return_sequences=True, dropout=0.1,
recurrent_dropout=0.1))(x)
x = tf.keras.layers.Conv1D(64, kernel_size=3, padding="valid", kernel_initializer="glorot_uniform")(x)
avg_pool = tf.keras.layers.GlobalAveragePooling1D()(x)
max_pool = tf.keras.layers.GlobalMaxPooling1D()(x)
x = tf.keras.layers.concatenate([avg_pool, max_pool])
preds = tf.keras.layers.Dense(6, activation="sigmoid")(x)
model = tf.keras.Model(input, preds)
model.summary()
model.compile(loss='binary_crossentropy', optimizer=tf.keras.optimizers.Adam(lr=1e-3), metrics=['accuracy'])
batch_size = 128
checkpoint_path = "tf_model/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
save_weights_only=True,
verbose=1)
callbacks = [
tf.keras.callbacks.EarlyStopping(patience=5, monitor='val_loss'),
tf.keras.callbacks.TensorBoard(log_dir='logs'),
cp_callback
]
model.fit(x_train, y_train, validation_split=0.2, batch_size=batch_size,
epochs=1, callbacks=callbacks, verbose=1)
latest = tf.train.latest_checkpoint(checkpoint_dir)
model.load_weights(latest)
# Save the entire model as a SavedModel.
model.save('tf_model/the_model')
predictions = model.predict(np.expand_dims(x_train[42], 0))
print(tokenizer.sequences_to_texts([x_train[42]]))
print(y_train[42])
print(predictions)
Final solution:
import os
import numpy as np
import tensorflow as tf
from tensorflow import keras
checkpoint_path = "tf_model/the_model/saved_model.pb"
checkpoint_dir = os.path.dirname(checkpoint_path)
new_model = tf.keras.models.load_model(checkpoint_dir)
max_words = 100000
max_len = 150
# Check its architecture
# new_model.summary()
inputs = ["tenserflow seems like it fits the bill but there are zero tutorials that outline how to reuse a model in a production environment."]
# use same tokenizer used to build model
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=max_words, lower=True)
tokenizer.fit_on_texts(inputs)
# pass string to tokenizer and that 'array' is passed to predict
sequence = tokenizer.texts_to_sequences(inputs) # same tokenizer which is used on train data.
sequence = tf.keras.preprocessing.sequence.pad_sequences(sequence, maxlen = max_len)
predictions = new_model.predict(sequence)
print(predictions)
# [[0.0365479 0.01275077 0.02102855 0.00647011 0.02302513 0.00406089]]
It needs to be processed in the same way. This can be done with:
inputs = [
"tenserflow seems like it fits the bill but there are zero tutorials that outline
how to reuse a model in a production environment"]
sequence = tokenizer.texts_to_sequences(inputs) # same tokenizer which is used on train data.
sequence = pad_sequences(sequence, maxlen = max_len)
predictions = new_model.predict(sequence)

Keras Graph disconnected

Well, I have a problem setting up a network consisting of a CNN + Autoencoder for a classification task. The main idea is to use CNN-generated embedding as the input of an autoencoder for the embedding reconstruction process. Well, I was able to define both architectures, but I couldn't merge them into a single graph.
def autoencoder(cnn_out):
xreal = keras.layers.Input(tensor=cnn_out)
(...)
xhat = keras.layers.Dense(cnn_out.shape[1], activation='sigmoid')(dec)
ae = keras.models.Model(inputs=xreal, outputs=xhat)
loss_mse = mse_loss(xreal, xhat)
ae.add_loss(loss_mse)
return ae
def cnnae_model(input_shape):
h1 = keras.layers.Conv2D(8,strides=(1,1), kernel_size=kernel, kernel_regularizer=r.l2(kl), padding='same')(X)
(...)
h5 = keras.layers.AveragePooling2D(pool_size = (2, 2))(h5)
xreal = keras.layers.Flatten()(h5)
cnn = keras.models.Model(inputs=X, outputs=xreal)
cnn_ae = keras.models.Model(inputs=cnn.input, outputs=autoencoder(cnn.output).output)
return cnn_ae
input_shape = (128, 64, 3)
model = cnnae_siamesa(input_shape)
model.compile(loss=contrastve_loss,bacth_size = 16, optimizer=rms, metrics=[accuracy], callbacks=[reduce_lr])
The following error message appears when I try to compile the model:
ValueError: Graph disconnected: cannot obtain value for tensor Tensor("flatten_11/Identity:0", shape=(None, 2048), dtype=float32) at layer "input_50". The following previous layers were accessed without issue: []
I did some modifications to your code and produced a working version (one without the error you reported). There are a few changes that have to do with how the output layers are called when connecting up the different submodels, but hopefully you can relate it back to your original model. There is some additional information here that might help clarify: https://www.tensorflow.org/guide/keras/functional#using_the_same_graph_of_layers_to_define_multiple_models. I hope this helps. :
import tensorflow as tf
import numpy as np
print(tf.__version__)
tf.keras.backend.clear_session()
# Code with issue:
def autoencoder(cnn_out):
xreal = cnn_out # tf.keras.layers.Input(tensor=cnn_out)
dec = xreal
xhat = tf.keras.layers.Dense(cnn_out.shape[1], activation='sigmoid', name='AE_Dense')(dec)
# ae = tf.keras.models.Model(inputs=xreal, outputs=xhat, name='AE_Model')
# loss_mse = mse_loss(xreal, xhat)
# ae.add_loss(loss_mse)
return xhat # return last layer of model
def cnnae_model(input_shape):
#CNN model start:
X = tf.keras.layers.Input(input_shape, name='CNN_Input')
h1 = tf.keras.layers.Conv2D(8,kernel_size=(2,2), padding='same', name='CNN_Conv2D')(X)
h5 = h1
h5 = tf.keras.layers.AveragePooling2D(pool_size = (2, 2), name='CNN_AvgPooling2D')(h5)
xreal = tf.keras.layers.Flatten(name='CNN_myFlatten')(h5)
cnn = tf.keras.models.Model(inputs=X, outputs=xreal, name='CNN_Model')
#CNN model end:
ae_model = autoencoder(xreal)
cnn_ae = tf.keras.models.Model(inputs=cnn.input, outputs=ae_model, name='cnn_ae_model')
return cnn_ae
input_shape = (128, 64, 3)
model = cnnae_model(input_shape)
print('model.summary():')
print(model.summary())
model.compile(optimizer='rmsprop', loss='mse')
x_train=np.random.random((2,128,64,3))
y_train=np.random.random((2,16384))
print('x_train.shape:')
print(x_train.shape)
print('y_train.shape:')
print(y_train.shape)
model.fit(x_train, y_train, epochs=1)

ValueError: Error when checking model target: expected dense_4

i have an error:
ValueError: Error when checking model target: expected dense_4 to have shape (None, 2) but got array with shape (12956, 1)
When i run this script.
def image_text_model(image_features, text_features, n_classes):
# fine-tune the last layer
image_features = Input(shape=image_features.shape[1:], dtype='float32')
n_text_features = text_features.shape[1]
text_features = Input(shape=text_features.shape[1:], dtype='float32')
# text model
x_text = Dense(256, activation='elu', kernel_regularizer=l2(1e-5))(text_features)
x_text = Dropout(0.5)(x_text)
# image model
x_img = Dense(256, activation='elu')(image_features)
x_img = Dropout(0.5)(x_img)
x_img = Dense(256, activation='elu')(x_img)
x_img = Dropout(0.5)(x_img)
merged = concatenate([x_img, x_text])
predictions = Dense(n_classes, activation='softmax')(merged)
model = Model(inputs=[image_features, text_features], outputs=[predictions])
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
return model
# dev
df = pd.read_csv(os.path.join(data_dir, 'amazon_products_dev.csv'))
dev_image_list = df['image_file'].values
dev_text = df['title'].values.tolist()
dev_categories = df['product_category'].values
# encode labels (binary labels)
encoder = LabelBinarizer()
train_labels = encoder.fit_transform(train_categories)
dev_labels = encoder.transform(dev_categories)
# get features from a pre-trained resnet model
vec = ResNetVectorizer(batch_size=500,
image_dir=image_dir,
use_cache=True,
cache_dir=cache_dir)
train_image_features = vec.transform(train_image_list)
dev_image_features = vec.transform(dev_image_list)
# get text features
tfidf = TfidfVectorizer(ngram_range=(1,1), stop_words='english', max_features=5000)
train_text_features = tfidf.fit_transform(train_text)
dev_text_features = tfidf.transform(dev_text).toarray()
# fine-tune the last layer
n_classes = encoder.classes_.shape[0]
model = image_text_model(train_image_features, train_text_features, n_classes)
data_gen = sparse_batch_generator(train_image_features, train_text_features, train_labels, shuffle=True)
steps_per_epoch = int(np.ceil(train_image_features.shape[0]/32.))
model.fit_generator(data_gen,
steps_per_epoch=steps_per_epoch,
epochs=50,
validation_data=[[dev_image_features, dev_text_features], dev_labels])
I See this topic : ValueError: Error when checking model target: expected dense_4 to have shape (None, 4) but got array with shape (13252, 1)
But i don't know how can use it into my script.
Thank you in advance for your answer.
Currently you must only have two classes as you output is expecting (None, 2). However, when working with two classes, you matrix structure can either be
[[0,1],
[1,0],
[1,0]]
or
[[0],
[1],
[1]]
Sklearns LabelBinarizer converts a matrix with two classes into a column of zeros and one's. 0 for class one and 1 for class two. So your output layer should just be
predictions = Dense(1, activation='sigmoid')(merged)

Categories