Tensorflow Keras图像字幕模型未编译,因为在上一层中掩码_zero=True时连接层

Tensorflow Keras图像字幕模型未编译,因为在上一层中掩码_zero=True时连接层,tensorflow,keras,deep-learning,lstm,word-embedding,Tensorflow,Keras,Deep Learning,Lstm,Word Embedding,我是Keras的新手,我正在尝试为一个图像字幕项目实现一个模型 我试图从(图片取自本文:)(但有一个细微的区别:在每个时间步生成一个单词,而不是在最后只生成一个单词),其中第一个时间步的LSTM输入是嵌入的CNN特征。LSTM应该支持可变输入长度,为了做到这一点,我用零填充了所有序列,以便所有序列都有maxlen时间步长 我现在拥有的模型的代码如下: def get_model(model_name、batch_size、maxlen、voc_size、embed_size、, 美国有线电视新闻

我是Keras的新手,我正在尝试为一个图像字幕项目实现一个模型

我试图从(图片取自本文:)(但有一个细微的区别:在每个时间步生成一个单词,而不是在最后只生成一个单词),其中第一个时间步的LSTM输入是嵌入的CNN特征。LSTM应该支持可变输入长度,为了做到这一点,我用零填充了所有序列,以便所有序列都有maxlen时间步长

我现在拥有的模型的代码如下:

def get_model(model_name、batch_size、maxlen、voc_size、embed_size、,
美国有线电视新闻网(cnn)的成绩(规模、辍学率):
#为cnn功能创建输入层
cnn\u专长\u输入=输入(形状=(cnn\u专长\u大小,)
#标准化CNN特征
标准化功能=批量标准化(轴=-1)(cnn功能输入)
#嵌入CNN特征,使其与单词嵌入具有相同的维度
嵌入式cnn专长=密集(嵌入大小)(标准化cnn专长)
#添加时间维度,使该层输出形状为(无、1、嵌入大小)
最终cnn专长=RepeatVector(1)(嵌入式cnn专长)
#为字幕创建输入层(每个字幕有最大maxlen字)
标题输入=输入(形状=(maxlen,))
#嵌入字幕
嵌入的标题=嵌入(输入尺寸=voc尺寸,
输出尺寸=嵌入尺寸,
输入长度=最大长度(标题输入)
#连接CNN功能和标题。
#输出形状应为(无,最大值+1,嵌入大小)
img_caption_concat=连接([最终的cnn壮举,嵌入的标题],axis=1)
#现在将连接馈送到LSTM层(多对多)
lstm_层=lstm(单位=嵌入尺寸,
输入_形状=(maxlen+1,嵌入_大小),#图像特征的一个额外时间步
return_sequences=True,
辍学率=辍学率(如图所示)
#创建完全连接的层以进行预测
pred_层=时间分布(密集(单位=voc_大小))(lstm_层)
#使用CNN功能和标题作为输入和输入构建模型
#预测输出
模型=模型(输入=[cnn演技输入,字幕输入],
输出=pred_层)
优化器=Adam(lr=0.0001,
β1=0.9,
β2=0.999,
ε=1e-8)
compile(loss='classifical\u crossentropy',optimizer=optimizer)
model.summary()
回归模型
模型(如上所述)编译时没有任何错误(请参阅:),我设法使用我的数据对其进行了训练。但是,它没有考虑到我的序列是零填充的,因此结果不会准确。当我尝试更改嵌入层以支持掩蔽时(同时确保使用voc_大小+1而不是文档中提到的voc_大小),如下所示:

embedded_caption=嵌入(输入尺寸=voc尺寸+1,
输出尺寸=嵌入尺寸,
输入长度=maxlen,掩码=True)(标题输入)
我得到以下错误:

回溯(最近一次呼叫最后一次):
文件“/export/home/../py3_-env/lib/python3.5/site-packages/tensorflow/python/framework/ops.py”,第1567行,在_-create_-c_-op中
c_op=c_api.TF_FinishOperation(操作说明)
tensorflow.python.framework.errors\u impl.InvalidArgumentError:两种形状中的维度0必须相等,但分别为200和1。形状为[200]和[1]。对于“连接_1/concat_1”(op:“ConcatV2”)和输入形状:[?、1200]、?、25,1]、]以及计算的输入张量:输入[2]=
我不知道为什么它说第二个数组的形状是[?,25,1],因为我在连接之前打印它的形状,它是[?,25,200](应该是这样)。 我不明白为什么在没有参数的情况下编译并运行良好的模型会出现问题,但我认为我缺少了一些东西

我也一直在考虑使用掩蔽层而不是mask_zero=True,但它应该在嵌入之前,文档中说嵌入层应该是模型中的第一层(在输入之后)


为了解决这个问题,我有什么可以改变的吗?或者有解决办法吗?

非等形状错误指的是遮罩,而不是张量/输入。由于
串联
支持掩蔽,它需要。您的
最终\u cnn\u壮举
没有掩码(
),而您的
嵌入式字幕
有一个形状为
(?,25)
的掩码。您可以通过执行以下操作来了解这一点:

print(embedded_caption._keras_history[0].compute_mask(caption_input))
由于
final\u cnn\u壮举
没有掩码,
concatenate
将用于正确的掩码传播。虽然这是正确的,但是遮罩的形状与
最终功绩
的形状相同,即
(?,1200)
,而不是
(?,1)
,即在所有时间步屏蔽所有特征,而不仅仅是所有时间步。这就是非等形状错误的来源(
(?,1200)
vs
(?,25)

要修复它,您需要给
final_cnn_features
一个正确/匹配的掩码。现在我不熟悉你的项目。一个选项是将
掩蔽
层应用于
最终功绩
,因为它的设计目的是


只有当
final\u cnn\u专长
中并非所有200个特征都为零时,这才是正确的,即
final\u cnn\u专长
中始终至少有一个非零值。在这种情况下,
屏蔽层将提供一个
(?,1)
屏蔽,并且不会屏蔽
最终功能中的单个时间步

非常感谢您的详细解释,它解决了我的问题!
final_cnn_feats = Masking()(RepeatVector(1)(embedded_cnn_feats))