前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >语言生成实战:自己训练能讲“人话”的神经网络(下)

语言生成实战:自己训练能讲“人话”的神经网络(下)

作者头像
AiTechYun
发布2019-09-16 16:57:48
5790
发布2019-09-16 16:57:48
举报
文章被收录于专栏:ATYUN订阅号ATYUN订阅号

在昨天的学习当中,我们了解了培养一个会说话的语言生成模型所需要的如何创建数据集这一模块,今天我们继续学习构建语言生成模型。

前文链接:语言生成实战:自己训练能讲“人话”的神经网络(上)

2.构建模型

我们将使用长短期记忆网络(LSTM)。LSTM的一个重要优点是能够理解对整个序列的依赖性,因此,句子的开头可能会对要预测的第15个单词产生影响。另一方面,递归神经网络(RNNs)只意味着依赖于网络的前一个状态,只有前一个词才能帮助预测下一个状态。如果选择RNNs,我们很快就会错过上下文,因此,LSTMs似乎是正确的选择。

a.模型架构

由于训练可以非常(非常)(非常)(非常)(非常)(非常)(非常)(不开玩笑)长,我们将构建一个简单的1嵌入+ 1 LSTM层+ 1密集网络:

代码语言:javascript
复制
def create_model(max_sequence_len, total_words):

      input_len = max_sequence_len - 1

      model = Sequential()

      # Add Input Embedding Layer
      model.add(Embedding(total_words, 10, input_length=input_len))

      # Add Hidden Layer 1 - LSTM Layer
      model.add(LSTM(100))
      model.add(Dropout(0.1))

      # Add Output Layer
      model.add(Dense(total_words, activation='softmax'))

      model.compile(loss='categorical_crossentropy', optimizer='adam')

      return model

model = create_model(max_sequence_len, total_words)
model.summary()

首先,我们添加一个嵌入层。我们将其传递到一个有100个神经元LSTM中,添加一个dropout来控制神经元的协同适应,最后是一个致密层。注意,我们在最后一层应用一个softmax激活函数来获得输出属于每个类的概率。所使用的损失是分类交叉熵,因为它是一个多类分类问题。

模型总结如下:

b.训练模型

我们现在(终于)准备好训练模型了!

代码语言:javascript
复制
model.fit(X, y, batch_size=256, epochs=100, verbose=True)

然后将开始训练模型:

代码语言:javascript
复制
Epoch 1/10
164496/164496 [==============================] - 471s 3ms/step -

loss: 7.0687
Epoch 2/10
73216/164496 [============>.................] - ETA: 5:12 - loss:

7.0513

在CPU上,一个时期大约需要8分钟。在GPU上(例如在Colab中), 您应该修改使用的Keras LSTM网络,因为它不能在GPU上使用。相反,您需要:

代码语言:javascript
复制
# Modify Import
from keras.layers import Embedding, LSTM, Dense, Dropout, CuDNNLSTM

# In the Moddel
...
      model.add(CuDNNLSTM(100))
...

我倾向于在几个步骤中停止训练来进行样本预测,并控制给定几个交叉熵值的模型的质量。

以下是我的观察:

3.生成序列

如果你读过这篇文章,这就是你所期待的:创造新的句子!要生成句子,我们需要对输入文本应用相同的转换。我们将建立一个循环,为给定的迭代次数生成下一个单词:

代码语言:javascript
复制
input_txt = "Machine"

for _ in range(10):

     # Get tokens
     token_list = tokenizer.texts_to_sequences([input_txt])[0]   

     # Pad the sequence
     token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre')   

     # Predict the class
     predicted = model.predict_classes(token_list, verbose=0)

     output_word = ""

     # Get the corresponding work
     for word,index in tokenizer.word_index.items():
           if index == predicted:
               output_word = word
               break

input_txt += " "+output_word

当损失在3.1左右时,以“谷歌”作为输入,生成如下句子:

谷歌是世界范围内产生的大量数据

这并没有什么实际意义,但它成功地将谷歌与大量数据的概念联系起来。这是相当令人印象深刻的,因为它仅仅依赖于单词的共现,而没有整合任何语法概念。

如果我们在训练中再等一段时间,让损失减小到2.5,然后输入“Random Forest”:

Random Forest是一个完全托管的服务,旨在支持大量初创企业的愿景基础设施

同样,生成的内容没有意义,但语法结构相当正确。

损失在大约50个时期后开始分化,并从未低于2.5。

我想我们已经达到了发展方法的极限:

同样,生成的东西没有任何意义,但是语法结构是相当正确的。

这种损失在大约50个时期之后就会出现分歧,而且从未低于2.5。

  • 模型仍然很简单
  • 培训数据不够清晰
  • 数据量非常有限

也就是说,我发现结果非常有趣,例如,经过训练的模型可以很容易地部署在Flask Web App上。

结论

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ATYUN订阅号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2.构建模型
    • a.模型架构
      • b.训练模型
      • 3.生成序列
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档