我一直试图在Keras中实现这个BiLSTM:https://github.com/ffancellu/NegNN
这就是我所在的地方,它的作用是:
inputs_w = Input(shape=(sequence_length,), dtype='int32')
inputs_pos = Input(shape=(sequence_length,), dtype='int32')
inputs_cue = Input(shape=(sequence_length,), dtype='int32')
w_emb = Embedding(vocabulary_size+1, embedding_dim, input_length=sequence_length, trainable=False)(inputs_w)
p_emb = Embedding(tag_voc_size+1, embedding_dim, input_length=sequence_length, trainable=False)(inputs_pos)
c_emb = Embedding(2, embedding_dim, input_length=sequence_length, trainable=False)(inputs_cue)
summed = keras.layers.add([w_emb, p_emb, c_emb])
BiLSTM = Bidirectional(CuDNNLSTM(hidden_dims, return_sequences=True))(summed)
DPT = Dropout(0.2)(BiLSTM)
outputs = Dense(2, activation='softmax')(DPT)
checkpoint = ModelCheckpoint('bilstm_one_hot.hdf5', monitor='val_loss', verbose=1, save_best_only=True, mode='auto')
early = EarlyStopping(monitor='val_loss', min_delta=0.0001, patience=5, verbose=1, mode='auto')
model = Model(inputs=[inputs_w, inputs_pos, inputs_cue], outputs=outputs)
model.compile('adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit([X_train, X_pos_train, X_cues_train], Y_train, batch_size=batch_size, epochs=num_epochs, verbose=1, validation_split=0.2, callbacks=[early, checkpoint])在原代码中,在Tensorflow中,作者使用了带logits的掩蔽和softmax交叉熵。我还不知道如何在Keras中实现这一点。如果你有任何建议,不要犹豫。
我这里的主要问题是关于return_sequences=True的。作者似乎并没有在他的tensorflow实现中使用它,当我将它转换为False时,我得到了以下错误:
ValueError: Error when checking target: expected dense_1 to have 2 dimensions, but got array with shape (820, 109, 2)我还试着使用:
outputs = TimeDistributed(Dense(2, activation='softmax'))(BiLSTM)返回和不提供任何信息的AssertionError。
有什么想法吗?
谢谢
发布于 2019-04-15 10:27:14
作者使用掩蔽和软最大交叉熵与逻辑。我还不知道如何在Keras中实现这一点。
对于具有logits的softmax交叉熵,您是正确的。softmax_cross_entropy_with_logits作为损失函数+最后一层上没有激活函数,与您在最后一层上使用categorical_crossentropy作为损失+ softmax激活的方法相同。唯一的区别是后者在数值上不太稳定。如果这对您来说是个问题,您可以(如果您的Keras后端是tensorflow)传递tf.softmax_cross_entropy_with_logits作为您的损失。如果您有另一个后端,您将不得不在那里寻找一个等价的。
关于掩蔽,我不确定我是否完全明白作者在做什么。但是,在Keras中,Embedding层有一个可以设置为True的mask_zero参数。在这种情况下,所有具有0的时间步骤都将在所有进一步的计算中被忽略。但是,在您的源代码中,被蒙蔽的不是0,因此您必须相应地调整索引。如果这样做不起作用,那么您可以将Masking层放在您的递归层之前,但是我对此几乎没有经验。
我这里的主要问题是关于return_sequences=True的。作者似乎并没有使用它
你凭什么认为他不使用它?仅仅因为这个关键字没有出现在代码中,并不意味着什么。但我也不确定。代码非常老,我在文档中找不到它,它可以判断默认值是什么。
无论如何,如果您想使用return_sequences=False (无论出于什么原因),请注意这会改变层的输出形状:
return_sequences=True,输出形状为(batch_size, timesteps, features)return_sequences=False,输出形状为(batch_size, features)您所得到的错误基本上是告诉您,您的网络输出的一维小于您要输入的目标y值。因此,在我看来,return_sequences=True似乎正是您所需要的,但是如果没有更多的信息,就很难判断。
然后,关于TimeDistributed。我不太清楚你想用它实现什么,但引用了文档中的话:
此包装器将一个层应用于输入的每个时态切片。 输入应至少为三维,索引1的维数应视为时间维。
(重点是我的)
我不能从您的问题中确定,在哪种情况下会出现空断言。
如果您以前有一个带有return_sequences=False的递归层,那么您将再次缺少一个维度(不过,我不能告诉您为什么断言是空的)。
如果您以前有一个带有return_sequences=True的递归层,它应该可以工作,但是它是完全无用的,因为Dense是以一种时间分布式的方式应用的。如果我没有弄错的话,Dense层的这种行为在一些较旧的Keras版本中发生了改变(他们应该在那里更新示例,停止使用Dense!)。由于您所指的代码已经相当陈旧,很有可能那时需要TimeDistributed,但不再需要了。
如果您的计划是恢复缺少的维度,TimeDistributed不会帮助您,但是RepeatVector会帮助您。但是,如前所述,在这种情况下,最好首先使用return_sequences=True。
发布于 2019-04-15 09:17:00
问题是目标值似乎是时间分布的。所以你有109个时间步骤,有一个大小为2的热目标向量。这就是你需要return_sequences=True的原因。否则,您将只需将最后一个时间步骤提供给密集层,您将只有一个输出。
因此,取决于您需要什么,您需要保持它现在的样子,或者如果仅仅是最后一个时间步骤就足够了,您可以摆脱它,但是您需要相应地调整y值。
https://stackoverflow.com/questions/55685867
复制相似问题