【发布时间】:2022-11-29 05:30:02
【问题描述】:
我正在使用带有 TensorFlow 的 Flick8k 数据集开发一个图像字幕模型,我遇到了一个问题,即模型为每个图像输出相同的字幕。
我正在使用 Xception 网络首先提取所有图像的特征向量。然后,我创建了一个包含特征向量以及经过清理和矢量化的字幕的 TF 数据集。
以下是生成数据集的代码,其中 encoded_img_train/test 是特征向量列表,cap_train/test 是向量化字幕列表。
def create_dataset(images, captions, batch_size):
def map_func(decoder_input, decoder_output, feature):
x = {'decoder_in': decoder_input, 'encoder_in': feature}
y = {'decoder_out': decoder_output}
return x, y
decoder_input = []
decoder_output = []
for caption in captions:
in_seq = [token_start] + caption[:-1]
out_seq = caption[1:] + [token_end]
# Add padding to input captions
in_seq = tf.keras.preprocessing.sequence.pad_sequences([in_seq], maxlen=38, padding='post')[0]
# Add padding to output captions
out_seq = tf.keras.preprocessing.sequence.pad_sequences([out_seq], maxlen=38, padding='post')[0]
decoder_input.append(in_seq)
decoder_output.append(out_seq)
dataset = tf.data.Dataset.from_tensor_slices((decoder_input, decoder_output, images))
dataset = dataset.map(map_func)
dataset = dataset.repeat()
dataset = dataset.shuffle(1000).batch(64)
dataset = dataset.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
return dataset
train_dataset = create_dataset(encoded_img_train,cap_train,BATCH_SIZE)
val_dataset = create_dataset(encoded_img_test,cap_test,BATCH_SIZE)
这是我的模型
inputs1 = Input(shape=(2048,), name='encoder_in')
fe1 = tf.keras.layers.Dropout(0.5)(inputs1)
fe2 = tf.keras.layers.Dense(units, activation='relu', name='encoder_dense')(inputs1)
inputs2 = tf.keras.layers.Input(shape=(None,), name='decoder_in')
se1 = tf.keras.layers.Embedding(input_dim=vocab_size, output_dim=embedding_dim)(inputs2)
decoder_gru1 = GRU(units, name='decoder_gru1',
return_sequences=True)(se1)
decoder_gru2 = GRU(units, name='decoder_gru2',
return_sequences=True)(decoder_gru1)
decoder_gru3 = GRU(units, name='decoder_gru3',
return_sequences=True)(decoder_gru2)
decoder_dense = Dense(vocab_size, activation='linear', name='decoder_out')(decoder_gru3)
model = tf.keras.models.Model(inputs=[inputs1, inputs2], outputs=decoder_dense)
model.summary()
这就是我训练模型的方式
optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)
model.compile(loss='sparse_categorical_crossentropy', optimizer=optimizer)
epochs = 20
history = model.fit(train_dataset,validation_data=val_dataset, epochs=epochs, validation_steps=3, steps_per_epoch=steps_per_epoch)
最后这就是我从图像生成预测的方式
def generate_caption(image_id,true_caption,max_tokens=30):
encoder_input = features[image_id]
encoder_input = np.expand_dims(encoder_input, axis=0)
shape = (1, max_tokens)
decoder_input = np.zeros(shape=shape, dtype=np.int)
token_id = token_start
output=[]
count_tokens = 0
while token_id != token_end and count_tokens < max_tokens:
decoder_input[0, count_tokens] = token_id
input_data ={'encoder_in':encoder_input ,'decoder_in': decoder_input}
predict = model.predict(input_data)
token_id = np.argmax(predict[0, count_tokens, :])
output.append(token_id)
count_tokens += 1
print('Predicted caption',tokenizer.sequences_to_texts([output]))
print(len(output))
print('True captions',tokenizer.sequences_to_texts([true_caption]))
img = mpimg.imread(image_path+image_id)
imgplot = plt.imshow(img)
plt.show()
generate_caption(img_test[1],cap_test[1])
在训练期间,训练损失稳定在 2.17 左右,当对图像生成预测时,输出如下:
这个解决方案的整体架构是不是错了?还是我缺少一些东西来使这项工作顺利进行?
【问题讨论】:
标签: python tensorflow machine-learning keras