具有辅助输入的Keras中的LSTM模型

具有辅助输入的Keras中的LSTM模型,keras,keras-layer,Keras,Keras Layer,我有一个包含两列的数据集-每列包含一组文档。我必须将A栏中的文件与B栏中提供的文件进行匹配。这是一个监督分类问题。因此,我的培训数据包含一个标签列,指示文档是否匹配 为了解决这个问题,我创建了一组特征,比如f1-f25(通过比较两个文档),然后根据这些特征训练了一个二进制分类器。这种方法工作得相当好,但现在我想评估关于这个问题的深度学习模型(特别是LSTM模型) 我正在使用Python中的keras库。在阅读了keras文档和其他在线教程后,我成功地做到了以下几点: from keras.lay

我有一个包含两列的数据集-每列包含一组文档。我必须将A栏中的文件与B栏中提供的文件进行匹配。这是一个监督分类问题。因此,我的培训数据包含一个标签列,指示文档是否匹配

为了解决这个问题,我创建了一组特征,比如f1-f25(通过比较两个文档),然后根据这些特征训练了一个二进制分类器。这种方法工作得相当好,但现在我想评估关于这个问题的深度学习模型(特别是LSTM模型)

我正在使用Python中的
keras
库。在阅读了keras文档和其他在线教程后,我成功地做到了以下几点:

from keras.layers import Input, Embedding, LSTM, Dense
from keras.models import Model

# Each document contains a series of 200 words 
# The necessary text pre-processing steps have been completed to transform  
  each doc to a fixed length seq
main_input1 = Input(shape=(200,), dtype='int32', name='main_input1')
main_input2 = Input(shape=(200,), dtype='int32', name='main_input2')

# Next I add a word embedding layer (embed_matrix is separately created    
for each word in my vocabulary by reading from a pre-trained embedding model)
x = Embedding(output_dim=300, input_dim=20000, 
input_length=200, weights = [embed_matrix])(main_input1)
y = Embedding(output_dim=300, input_dim=20000, 
input_length=200, weights = [embed_matrix])(main_input2)

# Next separately pass each layer thru a lstm layer to transform seq of   
vectors into a single sequence
lstm_out_x1 = LSTM(32)(x)
lstm_out_x2 = LSTM(32)(y)

# concatenate the 2 layers and stack a dense layer on top
x = keras.layers.concatenate([lstm_out_x1, lstm_out_x2])
x = Dense(64, activation='relu')(x)
# generate intermediate output
auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(x)

# add auxiliary input - auxiliary inputs contains 25 features for each document pair
auxiliary_input = Input(shape=(25,), name='aux_input')

# merge aux output with aux input and stack dense layer on top
main_input = keras.layers.concatenate([auxiliary_output, auxiliary_input])
x = Dense(64, activation='relu')(main_input)
x = Dense(64, activation='relu')(x)

# finally add the main output layer
main_output = Dense(1, activation='sigmoid', name='main_output')(x)

model = Model(inputs=[main_input1, main_input2, auxiliary_input], outputs= main_output)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

model.fit([x1, x2,aux_input], y,
      epochs=3, batch_size=32)
然而,当我在训练数据上得分时,我得到了同样的问题。所有病例的得分。问题似乎在于辅助输入的输入方式(因为当我删除辅助输入时,它会生成有意义的输出)。 我还尝试在网络的不同位置插入辅助输入。但不知怎的,我没法让它工作


有什么建议吗?

好吧,这个网站开放了几个月,人们都在投票支持它。
我最近做了一件非常类似的事情,可以用来预测信用卡违约,它包含客户的分类数据(性别、教育水平、婚姻状况等),以及付款历史和时间序列。所以我不得不将时间序列与非序列数据合并。我的解决方案与您的非常相似,通过将LSTM与稠密模型相结合,我尝试采用这种方法解决您的问题。对我有效的是辅助输入上的密集层

此外,在您的情况下,共享层是有意义的,因此使用相同的权重来“读取”两个文档。我建议对您的数据进行测试:

from keras.layers import Input, Embedding, LSTM, Dense
from keras.models import Model

# Each document contains a series of 200 words 
# The necessary text pre-processing steps have been completed to transform  
  each doc to a fixed length seq
main_input1 = Input(shape=(200,), dtype='int32', name='main_input1')
main_input2 = Input(shape=(200,), dtype='int32', name='main_input2')

# Next I add a word embedding layer (embed_matrix is separately created    
for each word in my vocabulary by reading from a pre-trained embedding model)
x1 = Embedding(output_dim=300, input_dim=20000, 
input_length=200, weights = [embed_matrix])(main_input1)
x2 = Embedding(output_dim=300, input_dim=20000, 
input_length=200, weights = [embed_matrix])(main_input2)

# Next separately pass each layer thru a lstm layer to transform seq of   
vectors into a single sequence
# Comment Manngo: Here I changed to shared layer
# Also renamed y as input as it was confusing
# Now x and y are x1 and x2
lstm_reader = LSTM(32)
lstm_out_x1 = lstm_reader(x1)
lstm_out_x2 = lstm_reader(x2)

# concatenate the 2 layers and stack a dense layer on top
x = keras.layers.concatenate([lstm_out_x1, lstm_out_x2])
x = Dense(64, activation='relu')(x)
x = Dense(32, activation='relu')(x)
# generate intermediate output
# Comment Manngo: This is created as a dead-end
# It will not be used as an input of any layers below
auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(x)

# add auxiliary input - auxiliary inputs contains 25 features for each document pair
# Comment Manngo: Dense branch on the comparison features
auxiliary_input = Input(shape=(25,), name='aux_input')
auxiliary_input = Dense(64, activation='relu')(auxiliary_input)
auxiliary_input = Dense(32, activation='relu')(auxiliary_input)

# OLD: merge aux output with aux input and stack dense layer on top
# Comment Manngo: actually this is merging the aux output preparation dense with the aux input processing dense
main_input = keras.layers.concatenate([x, auxiliary_input])
main = Dense(64, activation='relu')(main_input)
main = Dense(64, activation='relu')(main)

# finally add the main output layer
main_output = Dense(1, activation='sigmoid', name='main_output')(main)

# Compile
# Comment Manngo: also define weighting of outputs, main as 1, auxiliary as 0.5
model.compile(optimizer=adam,
              loss={'main_output': 'w_binary_crossentropy', 'aux_output': 'binary_crossentropy'},
              loss_weights={'main_output': 1.,'auxiliary_output': 0.5},
              metrics=['accuracy'])

# Train model on main_output and on auxiliary_output as a support
# Comment Manngo: Unknown information marked with placeholders ____
# We have 3 inputs: x1 and x2: the 2 strings
# aux_in: the 25 features
# We have 2 outputs: main and auxiliary; both have the same targets -> (binary)y


model.fit({'main_input1': __x1__, 'main_input2': __x2__, 'auxiliary_input' : __aux_in__}, {'main_output': __y__, 'auxiliary_output': __y__}, 
              epochs=1000, 
              batch_size=__, 
              validation_split=0.1, 
              callbacks=[____])
我不知道这有多大帮助,因为我没有你的数据,所以我无法尝试。尽管如此,这是我的最佳拍摄。

出于明显的原因,我没有运行上面的代码。

不确定这是否是有意的,但辅助输出仅为(1,)。这真的是你所期望的吗?将25个辅助输入合并为一个结果?--辅助输出之前的模型是否打算“不可训练”,而您只训练最终部分?是的。这是一个二元分类模型,因此最终输出为(1,)。辅助输出是否应不同?我只是简单地输入25个特征作为辅助输入,因此是(25,)形状你尝试了更多的时代吗?我正在研究纵向医学数据,我试图了解你做了什么。两个串联的lstm层拾取两组不同的输入。我说得对吗?是的,我的措辞是x1和x2。@Manngo嗨,我还必须将时间序列与非序列数据合并,以预测不同位置的气象变量(由非序列数据区分)。您是否可以分享您在这方面所做的工作?在我的例子中,时间序列数据的长度在不同的位置不同。@Basilique您的意思是从一个模型中进行多个预测,每个位置一个?对于不同长度的时间序列,您可能可以查看支持可变采样但在同一时间窗口内的PLSTM。@Manngo我有两个时间相关特性T,P和两个非时间因变量S和D。目标也是一个时间因变量Q。我希望有一个全局模型,该模型是根据我所有的500个站点的信息进行训练的,而不是训练500个本地单独的模型。我希望全局模型有两个分支:一个上游分支,向其提供非时间序列变量,然后是下游分支,向其提供500个位置的时间序列。我使用了
generator
作为本地型号。我不知道如何将生成器与嵌入层结合起来。