今天在《自然语言处理实战》一书中看到一个seq2seq实现的Chatbot的例子,感觉可以很好地体现出seq2seq的架构,这里我们一起来实现如何用seq2seq实现Chatbot。
首先,seq2seq架构大家都比较熟悉,我们一起来看看本文的seq2seq的架构是怎样的:

首先是encoder,这里我们使用LSTM,当encoder编码完成序列之后,会生成一个中间向量,然后中间向量连接着decoder,decoder用的也是LSTM,在decoder的部分,以作为解码的开始,作为解码的结束。整个Chatbot的架构其实非常简单,我们看看代码是如何实现的:

from nlpia.loaders import get_data
df = get_data('moviedialog')
# 数组保存从语料库文件中读取的输入文本和目标文本
input_texts, target_texts = [], []
# 这个集合保存输入文本和目标文本中出现的字符
input_vocabulary = set()
output_vocabulary = set()
# 起始和终止的字符
start_token = '\t'
stop_token = '\n'
# max_training_samples定义了训练使用的行数。它是用户定义的最大值和文件中加载总行数中较小的数
max_training_samples = min(25000, len(df) - 1)

这里的语料使用的是nlpia库中自带的语料,我们可以看看语料是什么样子的:

语料都是一对对的,前面是一个句子,后面是这个句子的回复。接下来我们需要构建训练集:

for input_text, target_text in zip(df.statement, df.reply):# target_text需要用起始字符和终止字符包装起来target_text = start_token + target_text + stop_tokeninput_texts.append(input_text)target_texts.append(target_text)# 编译词汇表--input text中出现过的唯一字符集合for char in input_text:if char not in input_vocabulary:input_vocabulary.add(char)for char in target_text:if char not in output_vocabulary:output_vocabulary.add(char)

这里构建了训练集的输入和输出数据,接下来是字符型的训练集数据:

# 将字符集转换为排序后的字符列表,然后使用该列表生成字典
input_vocabulary = sorted(input_vocabulary)
output_vocabulary = sorted(output_vocabulary)
# 确定唯一字符的数量,用于构建独热矩阵
input_vocab_size = len(input_vocabulary)
output_vocab_size = len(output_vocabulary)
# 需要确定序列词条的最大数量
max_encoder_seq_length = max([len(txt) for txt in input_texts])
max_decoder_seq_length = max([len(txt) for txt in target_texts])
# 创建查找字典,用于生成独热向量
input_token_index = dict([(char, i) for i, char in enumerate(input_vocabulary)])
target_token_index = dict([(char, i) for i, char in enumerate(output_vocabulary)])
# 循环创建的字典创建反向查找表
reverse_input_char_index = dict((i, char) for char, i in input_token_index.items())
reverse_target_char_index = dict((i, char) for char, i in target_token_index.items())

在训练集词表构建完成之后,我们需要对序列进行编码:

import numpy as np
# 初始化0张量 [num_samples, max_len_seq, num_unique_tokens_in_vocab]
encoder_input_data = np.zeros((len(input_texts), max_encoder_seq_length, input_vocab_size),dtype='float32')
decoder_input_data = np.zeros((len(input_texts), max_decoder_seq_length, output_vocab_size),dtype='float32')
decoder_target_data = np.zeros((len(input_texts), max_decoder_seq_length, output_vocab_size),dtype='float32')# 对训练样本进行循环遍历,输入文本和目标文本需要对应
for i, (input_text, target_text) in enumerate(zip(input_texts, target_texts)):# 循环遍历每个样本的每个字符for t, char in enumerate(input_text):# 将每个时刻字符的索引设置为1,其他索引为0;浙江创建训练样本的独热编码encoder_input_data[i, t, input_token_index[char]] = 1.# 对解码器的训练数据,创建decoder_input_data和decoder_target_datafor t, char in enumerate(target_text):decoder_input_data[i, t, target_token_index[char]] = 1.if t > 0:decoder_target_data[i, t - 1, target_token_index[char]] = 1

在训练集准备完成之后,就可以定义seq2seq模型进行训练了:

from keras.models import Model
from keras.layers import Input, LSTM, Densebatch_size = 64
epochs = 100
# 神经元数量为256
num_neurons = 256encoder_inputs = Input(shape=(None, input_vocab_size))
encoder = LSTM(num_neurons, return_state=True)
encoder_outputs, state_h, state_c = encoder(encoder_inputs)
encoder_states = [state_h, state_c]decoder_inputs = Input(shape=(None, output_vocab_size))
decoder_lstm = LSTM(num_neurons, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs, initial_state=encoder_states)
decoder_dense = Dense(output_vocab_size, activation='softmax')
decoder_outputs = decoder_dense(decoder_outputs)
model = Model([encoder_inputs, decoder_inputs], decoder_outputs)model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['acc'])
model.summary()
# 每个epoch之后,留下10%的样本用于验证测试
model.fit([encoder_input_data, decoder_input_data], decoder_target_data, batch_size=batch_size, epochs=epochs, validation_split=0.1)
model.save('chatbot.h5')

我们可以看看这个神经网络模型是怎么样的:

这里模型训练需要花费较多的时间,我用CPU训练了近一天的时间才完成,接下来需要构造回复生成器模型,也就是解码器模型:

encoder_model = Model(encoder_inputs, encoder_states)
thought_input = [Input(shape=(num_neurons,)), Input(shape=(num_neurons,))]
decoder_outputs, state_h, state_c = decoder_lstm(decoder_inputs, initial_state=thought_input)
decoder_states = [state_h, state_c]
decoder_outputs = decoder_dense(decoder_outputs)decoder_model = Model(inputs=[decoder_inputs] + thought_input, output=[decoder_outputs] + decoder_states)

然后我们需要对生成的序列进行翻译:

def decode_sequence(input_seq):# 生成思想向量作为解码器的输入thought = encoder_model.predict(input_seq)# 与训练相反,target_seq一开始是一个零张量target_seq = np.zeros((1, 1, output_vocab_size))# 解码器的第一个输入词条是初始词条target_seq[0, 0, target_token_index[stop_token]] = 1.stop_condition = Falsegenerated_sequence = ''while not stop_condition:# 将已生成的词条和最新状态传递给解码器,以预测下一个序列元素output_tokens, h, c = decoder_model.predict([target_seq] + thought)generated_token_idx = np.argmax(output_tokens[0, -1, :])generated_char = reverse_target_char_index[generated_token_idx]generated_sequence += generated_char# stop_condition = True 停止循环if (generated_char == stop_token or len(generated_sequence) > max_decoder_seq_length):stop_condition = True# 更新目标序列,并使用最后生成的词条作为下一生成步骤的输入target_seq = np.zeros((1, 1, output_vocab_size))target_seq[0, 0, generated_token_idx] = 1.# 更新thought向量状态thought = [h, c]return generated_sequence

最后是生成回复的函数:

def response(input_text):input_seq = np.zeros((1, max_encoder_seq_length, input_vocab_size), dtype='float32')# 对输入文本的每个字符进行循环遍历,生成独热张量,以便编码器中生成thought向量for t, char in enumerate(input_text):input_seq[0, t, input_token_index[char]] = 1.# 使用decode_sequence函数调用训练好的模型生成回复序列decode_sentence = decode_sequence(input_seq)print('Reply (Decode sentence):', decode_sentence)

代码完成之后,我们来试试效果如何,因为这种循环神经网络比较受制于训练集的质量以及数量,并且序列没有加入attention,所以生成的回复并不太理想,所以这种模型对训练集有较高的要求:



这里提供一种RNN的seq2seq的算法思想,希望对大家有所帮助,谢谢。

keras实现seq2seq做Chatbot相关推荐

  1. 玩转Keras之Seq2Seq自动生成标题 | 附开源代码

    作者丨苏剑林 单位丨广州火焰信息科技有限公司 研究方向丨NLP,神经网络 个人主页丨kexue.fm 话说自称搞了这么久的 NLP,我都还没有真正跑过 NLP 与深度学习结合的经典之作--Seq2Se ...

  2. keras的seq2seq

    前面讲到seq2seq,网上有很多seq2seq的例子,今天具体解析一下keras的seq2seq(character-level)例子,代码是keras的github上的地址: https://gi ...

  3. 基于keras的seq2seq中英文翻译实现

    1. seq2seq概述 1.1 seq2seq简介 1.2 seq2seq结构 2. 中英文翻译实战 2.1 数据处理 2.2 encoder-decoder模型搭建 2.2.1 用于训练的模型 2 ...

  4. Keras实现seq2seq案例代码:Bi-LSTM

    目录 1. 案例介绍 2. 代码实现 代码一:为模型创建输入 代码二:构建模型 代码三:检验模型性能 1. 案例介绍 为便于讲解seq2seq模型用例,我们采用一篇研究论文中所使用的注释预料库的文本内 ...

  5. 用深度学习keras的cnn做图像识别分类,准确率达97%

    Keras是一个简约,高度模块化的神经网络库. 可以很容易和快速实现原型(通过总模块化,极简主义,和可扩展性) 同时支持卷积网络(vision)和复发性的网络(序列数据).以及两者的组合. 无缝地运行 ...

  6. 使用Seq2Seq做统计机器翻译

    Title Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation ...

  7. 智能客服系列3 seq2seq+attention【Python十分钟写出聊天机器人】基于Keras实现seq2seq模型

    开篇导读 首先复习下前面聊天机器人系列: <一>聊天机器人/翻译系统系列一梳理了聊天机器人网络设计模型原理 (理论篇-图文解锁seq2seq+attention模型原理) <二> ...

  8. seq2seq与Attention机制

    学习目标 目标 掌握seq2seq模型特点 掌握集束搜索方式 掌握BLEU评估方法 掌握Attention机制 应用 应用Keras实现seq2seq对日期格式的翻译 4.3.1 seq2seq se ...

  9. Seq2Seq中Exposure Bias现象的浅析与对策

    ©PaperWeekly 原创 · 作者|苏剑林 单位|追一科技 研究方向|NLP.神经网络 前些天笔者写了CRF用过了,不妨再了解下更快的MEMM?,里边提到了 MEMM 的局部归一化和 CRF 的 ...

最新文章

  1. python—unittest—数据驱动详细讲解(ddt)
  2. [小程序]小程序框架的简单页面布局
  3. 关于爬虫中常见的两个网页解析工具的分析 —— lxml / xpath 与 bs4 / BeautifulSoup...
  4. centos7源码安装mysql报错_CentOS7 下源码安装MySQL数据库 8.0.11
  5. 005 - react
  6. linux mail使用笔记
  7. mac文件修改权限设置
  8. paip.数据库发邮件通知配置
  9. fit me app Android,「最美应用」国庆专题:—这些习惯养成 App,让你离更好的自己更进一步!...
  10. 步进电机驱动电路设计精华_电动机控制电路图讲解
  11. 华为荣耀6 root
  12. 大恒相机连续采集并保存图片
  13. Mysql 学习教程
  14. P、*P和P三者的区别
  15. EduCoder-程序设计技术R-循环结构程序设计2-(第1关:C循环-求平均成绩)(第2关:C循环-求各位数字)(第3关:C循环-求阶乘之和)(第4关:C循环-水仙花数)(第5关:C循环
  16. 世界末日那天,我们才能拿到Lytro的光场相机
  17. 结构 Structure
  18. Java Swing的简单学习学习
  19. select中文件描述符上限为什么是1024?
  20. MODIS卫星遥感数据下载处理

热门文章

  1. Java最新面试题100道,包含答案示例(41-50题)
  2. linux实用的磁盘大文件及大文件夹查找命令
  3. 数据分析 - 单表简单查询
  4. 4 Bootstrap4组件——徽章(Badges)
  5. NSIS (NullSoft Scriptable Install System)使用指北(超详细)
  6. 3.vue开发实例演示
  7. mysql创建用户表的sql语句,mysql创建表的sql语句
  8. Ueditor上传图片文件大小上限问题
  9. (转)纵观国内外证券公司IT发展史
  10. Day16:hash表