Python 使用Keras对句子序列进行训练

Python 使用Keras对句子序列进行训练,python,machine-learning,neural-network,keras,Python,Machine Learning,Neural Network,Keras,我正在做一个项目,在这个项目中,我必须在神经网络中使用数字和文本数据的组合来预测下一个小时系统的可用性。我决定使用Keras的合并层和两个网络(一个用于数字数据,一个用于文本),而不是尝试使用单独的神经网络,并在最后做一些奇怪/不清楚的事情来产生所需的输出。我的想法是,我以(批量大小、6小时、数量特征)的形式为模型提供前6小时的一系列性能指标。除了向处理数字数据的网络提供输入之外,我还向第二个网络提供另一个大小的序列(批量大小、每个序列的最大警报、最大句子长度) 在一个时间范围内的任何数字数据序

我正在做一个项目,在这个项目中,我必须在神经网络中使用数字和文本数据的组合来预测下一个小时系统的可用性。我决定使用Keras的合并层和两个网络(一个用于数字数据,一个用于文本),而不是尝试使用单独的神经网络,并在最后做一些奇怪/不清楚的事情来产生所需的输出。我的想法是,我以(批量大小、6小时、数量特征)的形式为模型提供前6小时的一系列性能指标。除了向处理数字数据的网络提供输入之外,我还向第二个网络提供另一个大小的序列(批量大小、每个序列的最大警报、最大句子长度)

在一个时间范围内的任何数字数据序列都可以具有与之关联的可变数量的事件(文本数据)。为了简单起见,我最多只允许50个事件伴随一系列性能数据。每个事件都是按单词进行哈希编码并填充的。我已经尝试使用扁平层将输入形状从(50,30)减少到(1500),这样模型就可以在这些“序列”中的每个事件上进行训练(为了澄清:我为每个性能数据序列传递了50个句子,每个句子包含30个编码元素)

我的问题是:由于我需要NN查看给定性能指标序列的所有事件,因此如何使基于文本的数据序列的NN基于句子序列

我的模型:

#LSTM Module for performance metrics
input = Input(shape=(shape[1], shape[2]))
lstm1 = Bidirectional(LSTM(units=lstm_layer_count, activation='tanh', return_sequences=True, input_shape=shape))(input)
dropout1 = Dropout(rate=0.2)(lstm1)
lstm2 = Bidirectional(LSTM(units=lstm_layer_count, activation='tanh', return_sequences=False))(dropout1)
dropout2 = Dropout(rate=0.2)(lstm2)

#LSTM Module for text based data
tInput = Input(shape=(50, 30))
flatten = Flatten()(tInput)
embed = Embedding(input_dim=vocabsize + 1, output_dim= 50 * 30, input_length=30*50)(flatten)
magic = Bidirectional(LSTM(100))(embed)
tOut = Dense(1, activation='relu')(magic)

#Merge the layers
concat = Concatenate()([dropout2, tOut])
output = Dense(units=1, activation='sigmoid')(concat)

nn = keras.models.Model(inputs=[input, tInput], outputs = output)

opt = keras.optimizers.SGD(lr=0.1, momentum=0.8, nesterov=True, decay=0.001)
nn.compile(optimizer=opt, loss='mse', metrics=['accuracy', coeff_determination])

据我所知,你有一个最多50个事件的序列,你想对其进行预测。这些事件附加了文本数据,可以将其视为另一个单词嵌入序列。是一篇关于类似体系结构的文章

我将提出一个解决方案,其中涉及文本部分的LSTM,以及“真实”序列部分的1D卷积。每个LSTM层都与数值数据连接在一起。这涉及到50个LSTM层,即使使用共享权重,训练也会很耗时。对于文本部分,也可以只使用卷积层,这会更快,但不会建模长期依赖关系。(我的经验是,这些长期依赖性在文本挖掘中通常并不那么重要)

文本->LSTM或1DConv->带数字数据的concat->1DConv->输出 下面是一些exmaple代码,它展示了如何使用碎片权重

numeric_input = Input(shape=(x_numeric_train.values.shape[1],), name='numeric_input')
nlp_seq = Input(shape=(number_of_messages ,seq_length,), name='nlp_input'+str(i))

# shared layers
emb = TimeDistributed(Embedding(input_dim=num_features, output_dim=embedding_size,
                input_length=seq_length, mask_zero=True,
                input_shape=(seq_length, )))(nlp_seq)    
x = TimeDistributed(Bidirectional(LSTM(32, dropout=0.3, recurrent_dropout=0.3, kernel_regularizer=regularizers.l2(0.01))))(emb)      

c1 = Conv1D(filter_size, kernel1, padding='valid', activation='relu', strides=1, kernel_regularizer=regularizers.l2(kernel_reg))(x)
p1 = GlobalMaxPooling1D()(c1)
c2 = Conv1D(filter_size, kernel2, padding='valid', activation='relu', strides=1, kernel_regularizer=regularizers.l2(kernel_reg))(x)
p2 = GlobalMaxPooling1D()(c2)
c3 = Conv1D(filter_size, kernel3, padding='valid', activation='relu', strides=1, kernel_regularizer=regularizers.l2(kernel_reg))(x)
p3 = GlobalMaxPooling1D()(c3)

x = concatenate([p1, p2, p3, numeric_input])    
x = Dense(1, activation='sigmoid')(x)        
model = Model(inputs=[nlp_seq, meta_input] , outputs=[x])
model.compile('adam', 'binary_crossentropy', metrics=['accuracy'])    
培训:

model.fit([x_train, x_numeric_train], y_train)
# where x_train is a a array of num_samples * num_messages * seq_length
像这样的复杂模型需要大量数据才能收敛。对于更少的数据,可以通过将事件聚合为只有一个序列来实现更简单的解决方案。例如,可以将所有事件的文本数据视为一个文本(带有分隔符标记),而不是多个文本,而数字数据可以求和、平均,甚至组合成一个固定长度的列表。但这取决于你的数据


由于我正在做一些类似的工作,我将在稍后用代码更新这些答案。

我不太理解您的问题的细节,也许您可以重新措辞?我正在做类似的工作。我也有文本数据和数字数据。在我的例子中,我有n个句子,其中每个句子(嵌入空间中的单词序列)都经过它自己的LSTM,但权重是共享的。最后,我将所有LSTM输出放入1D卷积,然后用数值数据进行concat。看起来你对这个问题理解得很好,但我还是会尝试重新表述它!给定每个数字数据点实例(编码为长度为30的词向量)包含多个句子的数字和文本数据,如何训练利用这两种数据类型的模型?根据你的建议:我将尝试一下这种方法。然而,如果你在为N个句子训练N个LSTM,那么即使你仍在分享权重,训练和预测的速度不是都非常慢吗?是的,那会非常慢,如果你每个句子都有一个LSTM,在我的例子中,我们不完全是在谈论句子,它更像是信息。但从某种程度上说,只要稍作调整,它可能会起作用。你是否描述了你的问题?是的,这个链接确实抓住了我正在尝试做的事情。但是,这种实现似乎只处理数字数据序列和单个消息,而不是消息序列。换句话说,不要从“猫咕噜咕噜”->[1,2,3]->Model。我需要从“猫的咕噜声”->[1,2,3]“狗的吠声”->[1,4,5]“海豚的游泳”->[1,6,7]->[1,2,3;1,4,5;1,6,7]->model谢谢@Digital Thinking的帮助。时间分配会做本质上相同的事情吗?根据我对文档的理解,TimeDistributed层将目标层应用于输入的每个部分。对我来说,这意味着模型将自动为序列中的每个警报创建一个LSTM层,它完成了与上述代码中for循环相同的事情。非常好的提示!我认为TimeDistributed也可以工作,但您输入的数据必须采用正确的格式。我明天会更新答案