【问题标题】:How to structure an LSTM neural network for classification如何构建 LSTM 神经网络进行分类
【发布时间】:2017-07-09 03:05:16
【问题描述】:

我有两个人之间进行各种对话的数据。每个句子都有某种类型的分类。我正在尝试使用 NLP 网络对对话的每个句子进行分类。我尝试了一个卷积网络并获得了不错的结果(不是开创性的)。我想,既然这是一个来回的对话,LSTM 网络可能会产生更好的结果,因为之前所说的可能会对后面的内容产生很大的影响。

如果我遵循上面的结构,我会假设我在做多对多。我的数据看起来像。

X_train = [[sentence 1],  
           [sentence 2],
           [sentence 3]]
Y_train = [[0],
           [1],
           [0]]

已使用 word2vec 处理数据。然后我按如下方式设计我的网络..

model = Sequential()      
model.add(Embedding(len(vocabulary),embedding_dim,
          input_length=X_train.shape[1]))
model.add(LSTM(88))
model.add(Dense(1,activation='sigmoid'))
model.compile(optimizer='rmsprop',loss='binary_crossentropy',
              metrics['accuracy'])
model.fit(X_train,Y_train,verbose=2,nb_epoch=3,batch_size=15)

我假设此设置将一次输入一批句子。但是,如果在 model.fit 中,shuffle 不等于 false,它接收的随机批次,那么为什么 LSTM 网络在这种情况下甚至有用呢?从对该主题的研究来看,要实现多对多结构,也需要更改 LSTM 层

model.add(LSTM(88,return_sequence=True))

输出层需要...

model.add(TimeDistributed(Dense(1,activation='sigmoid')))

切换到此结构时,输入大小出现错误。我不确定如何重新格式化数据以满足此要求,以及如何编辑嵌入层以接收新的数据格式。

任何意见将不胜感激。或者,如果您对更好的方法有任何建议,我非常乐意听到!

【问题讨论】:

    标签: python neural-network nlp keras lstm


    【解决方案1】:

    您的第一次尝试很好。洗牌发生在句子之间,唯一的是将它们之间的训练样本洗牌,这样它们就不会总是以相同的顺序出现。句子中的单词不会被打乱。

    或者我没有正确理解这个问题?

    编辑

    在对问题有了更好的理解之后,这是我的提议。

    数据准备:您将语料库切成n 句子块(它们可以重叠)。 然后你应该有一个像(number_blocks_of_sentences, n, number_of_words_per_sentence) 这样的形状,所以基本上是一个包含n 句子块的二维数组列表。 n 不应该太大,因为 LSTM 在训练时无法处理序列中的大量元素(梯度消失)。 您的目标应该是一个形状为(number_blocks_of_sentences, n, 1) 的数组,因此也是一个二维数组列表,其中包含句子块中每个句子的类。

    型号:

    n_sentences = X_train.shape[1]  # number of sentences in a sample (n)
    n_words = X_train.shape[2]      # number of words in a sentence
    
    model = Sequential()
    # Reshape the input because Embedding only accepts shape (batch_size, input_length) so we just transform list of sentences in huge list of words
    model.add(Reshape((n_sentences * n_words,),input_shape = (n_sentences, n_words)))
    # Embedding layer - output shape will be (batch_size, n_sentences * n_words, embedding_dim) so each sample in the batch is a big 2D array of words embedded 
    model.add(Embedding(len(vocabaulary), embedding_dim, input_length = n_sentences * n_words ))
    # Recreate the sentence shaped array
    model.add(Reshape((n_sentences, n_words, embedding_dim))) 
    # Encode each sentence - output shape is (batch_size, n_sentences, 88)
    model.add(TimeDistributed(LSTM(88)))
    # Go over lines and output hidden layer which contains info about previous sentences - output shape is (batch_size, n_sentences, hidden_dim)
    model.add(LSTM(hidden_dim, return_sequence=True))
    # Predict output binary class - output shape is (batch_size, n_sentences, 1)
    model.add(TimeDistributed(Dense(1,activation='sigmoid')))
    ...
    

    这应该是一个好的开始。

    希望对你有帮助

    【讨论】:

    • 那么你是说 LSTM 层一次只能输入一个单词?所以即使句子被打乱了,句子中的每个单词也会单独传递给 LSTM 以学习整个句子之间的整体上下文?
    • 如果我没有正确表达我的问题,我很抱歉。由于数据是对话,因此上一句中所说的内容对下一句具有重要意义。所以我试图设置网络来学习对话流并对每个句子进行分类。这就是我尝试使用 return_sequence 的原因,因此网络将保存有关前一个句子的信息,同时对当前句子进行分类。
    • 一个 LSTM 被输入一个向量序列。在您的情况下,它是一系列单词嵌入。在您的情况下,它将为每个句子返回一个长度为 88 的向量,您可以使用密集层将其减少到 1 个输出。所以它一次只关心一个句子。这就是你目前所做的。那是你想做的吗?
    • 好吧,这是一个全新的故事。然后你应该重塑你的 inout 数据并将其作为多个句子的块发送。然后使用分布在每个句子上的 LSTM 使用时间对每一行进行编码。你会得到一个句子序列,全部由一个 88 长度的向量表示。然后使用第二个 LSTM,返回序列 = True,它将再次为每个句子输出一个向量,但考虑到前面的句子。然后像现在一样在最后一层分配时间
    • 我理解您解释的总体概念,但我不确定如何实现它。这是我第一次尝试 LSTM。正如我看到其他人所建议的那样,我尝试重塑数组,但是我从中得到了错误,尤其是在似乎只能接受 2D 输入的嵌入层上。如果您可以添加代码示例,我将不胜感激。
    猜你喜欢
    • 2020-05-16
    • 2014-05-20
    • 1970-01-01
    • 2019-07-17
    • 2019-01-14
    • 2020-02-25
    • 2022-08-15
    • 2018-07-26
    • 2017-08-31
    相关资源
    最近更新 更多