三十八、原来聊天机器人是这么做出来的



tensorflow自带的seq2seq模型基于one-hot的词嵌入,每个词用一个数字代替不足以表示词与词之间的关系,word2vec通过多维向量来做词嵌入,能够表示出词之间的关系,比如:男-女≈王子-公主。基于seq2seq的思想,利用多维词向量来实现模型,预期会有更高的准确性。

请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址

seq2seq模型原理

主要参考《Sequence to Sequence Learning with Neural Networks》这篇论文,核心思想如下图:

ABC是输入语句,WXYZ是输出语句,EOS是标识一句话结束,图中的训练单元是lstm,lstm的特点是有长短时记忆,所以能够根据输入的多个字来确定后面的多个字,有关lstm的知识可以参考《http://deeplearning.net/tutorial/lstm.html》

上面的模型中编码器和解码器共用了同一个lstm层,也就是共享了参数,牛人们尝试把他们分开像https://github.com/farizrahman4u/seq2seq中提到的样子:

其中绿色是编码器,黄色是解码器,橙色的箭头传递的是lstm层的状态信息也就是记忆信息,编码器唯一传给解码器的就是这个状态信息

我们看到解码器每一时序的输入都是前一个时序的输出,从整体上来看就是:我通过不同时序输入“How are you <EOL>”,模型就能自动一个字一个字的输出“W I am fine <EOL>”,这里的W是一个特殊的标识,它既是编码器最后的输出,同时又是解码器的一个触发信号

那么我们训练的时候输入的X,Y应该是什么呢?X="How are you <EOL>",Y="W I am fine <EOL>"?

这是不行的,因为在解码器还没有训练出靠谱的参数之前,我们无法保证第一个时序的输出就是“I”,那么传给第二个时序的输入就不一定是I,同样第三、四个时序的输入就无法保证是am和fine,那么是无法训练出想要的模型的

我们要这样来做:我们直接把解码器中每一时序的输入强制改为"W I am fine",也就是把这部分从我们训练样本的输入X中传过来,而Y依然是预测输出的"W I am fine <EOL>",这样训练出来的模型就是我们设计的编码器解码器模型了

那么在使用训练好的模型做预测的时候,我们改变处理方式:在解码时以前一时序的输出为输入做预测,这样就能输出我们希望输出的"W I am fine <EOL>"了

基于以上的原理,下面开始我们的工程实践

 

语料准备工作

准备至少300w的聊天语料用于词向量的训练和seq2seq模型的训练,语料越丰富训练出来的词向量质量越好,如果想通过影视剧字幕来获取语料可以参考《自己动手做聊天机器人 二十九-重磅:近1GB的三千万聊天语料供出》

获取到原始语料后需要做一些加工处理,首先需要做切词,方法如下:

python word_segment.py ./corpus.raw ./corpus.segment

其中word_segment.py是我写的切词工具,仅供参考

之后要把切词好的文件转成“|”分隔的问答对,如下:

cat ./corpus.segment | awk '{if(last!="")print last"|"$0;last=$0}' | sed 's/| /|/g' > ./corpus.segment.pair

这样语料准备工作就齐全了

 

训练词向量

我们直接利用google的word2vec来训练词向量,如下:

word2vec -train ./corpus.segment -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-5 -threads 20 -binary 1 -iter 15

其中corpus.raw是原始语料数据,vectors.bin是生成的词向量二进制文件

了解word2vec的原理请见《自己动手做聊天机器人 二十五-google的文本挖掘深度学习工具word2vec的实现原理》

生成的词向量二进制加载方法可以参考我写的:word_vectors_loader.py

 

创建模型

下面就是重点的模型创建过程,这里面我们直接使用tensorflow+tflearn库来实现:

# 首先我们为输入的样本数据申请变量空间,如下。其中self.max_seq_len是指一个切好词的句子最多包含多少个词,self.word_vec_dim是词向量的维度,这里面shape指定了输入数据是不确定数量的样本,每个样本最多包含max_seq_len*2个词,每个词用word_vec_dim维浮点数表示。这里面用2倍的max_seq_len是因为我们训练是输入的X既要包含question句子又要包含answer句子
input_data = tflearn.input_data(shape=[None, self.max_seq_len*2, self.word_vec_dim], dtype=tf.float32, name = "XY")
# 然后我们将输入的所有样本数据的词序列切出前max_seq_len个,也就是question句子部分,作为编码器的输入
encoder_inputs = tf.slice(input_data, [0, 0, 0], [-1, self.max_seq_len, self.word_vec_dim], name="enc_in")
# 再取出后max_seq_len-1个,也就是answer句子部分,作为解码器的输入。注意,这里只取了max_seq_len-1个,是因为还要在前面拼上一组GO标识来告诉解码器我们要开始解码了,也就是下面加上go_inputs拼成最终的go_inputs
decoder_inputs_tmp = tf.slice(input_data, [0, self.max_seq_len, 0], [-1, self.max_seq_len-1, self.word_vec_dim], name="dec_in_tmp")
go_inputs = tf.ones_like(decoder_inputs_tmp)
go_inputs = tf.slice(go_inputs, [0, 0, 0], [-1, 1, self.word_vec_dim])
decoder_inputs = tf.concat(1, [go_inputs, decoder_inputs_tmp], name="dec_in")
# 之后开始编码过程,返回的encoder_output_tensor展开成tflearn.regression回归可以识别的形如(?, 1, 200)的向量;返回的states后面传入给解码器
(encoder_output_tensor, states) = tflearn.lstm(encoder_inputs, self.word_vec_dim, return_state=True, scope='encoder_lstm')
encoder_output_sequence = tf.pack([encoder_output_tensor], axis=1)
# 取出decoder_inputs的第一个词,也就是GO
first_dec_input = tf.slice(decoder_inputs, [0, 0, 0], [-1, 1, self.word_vec_dim])
# 将其输入到解码器中,如下,解码器的初始化状态为编码器生成的states,注意:这里的scope='decoder_lstm'是为了下面重用同一个解码器
decoder_output_tensor = tflearn.lstm(first_dec_input, self.word_vec_dim, initial_state=states, return_seq=False, reuse=False, scope='decoder_lstm')
# 暂时先将解码器的第一个输出存到decoder_output_sequence_list中供最后一起输出
decoder_output_sequence_single = tf.pack([decoder_output_tensor], axis=1)
decoder_output_sequence_list = [decoder_output_tensor]
# 接下来我们循环max_seq_len-1次,不断取decoder_inputs的一个个词向量作为下一轮解码器输入,并将结果添加到decoder_output_sequence_list中,这里面的reuse=True, scope='decoder_lstm'说明和上面第一次解码用的是同一个lstm层
for i in range(self.max_seq_len-1):next_dec_input = tf.slice(decoder_inputs, [0, i+1, 0], [-1, 1, self.word_vec_dim])decoder_output_tensor = tflearn.lstm(next_dec_input, self.word_vec_dim, return_seq=False, reuse=True, scope='decoder_lstm')decoder_output_sequence_single = tf.pack([decoder_output_tensor], axis=1)decoder_output_sequence_list.append(decoder_output_tensor)
# 下面我们把编码器第一个输出和解码器所有输出拼接起来,作为tflearn.regression回归的输入
decoder_output_sequence = tf.pack(decoder_output_sequence_list, axis=1)
real_output_sequence = tf.concat(1, [encoder_output_sequence, decoder_output_sequence])
net = tflearn.regression(real_output_sequence, optimizer='sgd', learning_rate=0.1, loss='mean_square')
model = tflearn.DNN(net)

至此模型创建完成,让我们汇总一下里面的思想:

1)训练输入的X、Y分别是编码器解码器的输入和预测的输出;

2)X切分两半,前一半是编码器输入,后一半是解码器输入;

3)编码解码器输出的预测值用Y做回归训练

4)训练时通过样本的真实值作为解码器输入,实际预测时将不会有上图中WXYZ部分,因此上一时序的输出将作为下一时序的输入(后面会详述预测的实现)

 

训练模型

下面我们来实例化模型并喂数据做训练,如下:

model = self.model()
model.fit(trainXY, trainY, n_epoch=1000, snapshot_epoch=False, batch_size=1)
model.load('./model/model')

这里的trainXY和trainY通过加载上面我们准备的语料来赋值

请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址

首先我们加载词向量并存到word_vector_dict中,然后读取语料文件并挨个词查word_vector_dict并赋值向量给question_seq和answer_seq,如下:

def init_seq(input_file):"""读取切好词的文本文件,加载全部词序列"""file_object = open(input_file, 'r')vocab_dict = {}while True:question_seq = []answer_seq = []line = file_object.readline()if line:line_pair = line.split('|')line_question = line_pair[0]line_answer = line_pair[1]for word in line_question.decode('utf-8').split(' '):if word_vector_dict.has_key(word):question_seq.append(word_vector_dict[word])for word in line_answer.decode('utf-8').split(' '):if word_vector_dict.has_key(word):answer_seq.append(word_vector_dict[word])else:breakquestion_seqs.append(question_seq)answer_seqs.append(answer_seq)file_object.close()

有了question_seq和answer_seq,我们来构造trainXY和trainY,如下:

    def generate_trainig_data(self):xy_data = []y_data = []for i in range(len(question_seqs)):question_seq = question_seqs[i]answer_seq = answer_seqs[i]if len(question_seq) < self.max_seq_len and len(answer_seq) < self.max_seq_len:sequence_xy = [np.zeros(self.word_vec_dim)] * (self.max_seq_len-len(question_seq)) + list(reversed(question_seq))sequence_y = answer_seq + [np.zeros(self.word_vec_dim)] * (self.max_seq_len-len(answer_seq))sequence_xy = sequence_xy + sequence_ysequence_y = [np.ones(self.word_vec_dim)] + sequence_yxy_data.append(sequence_xy)y_data.append(sequence_y)return np.array(xy_data), np.array(y_data)

构造了训练数据也创建好了模型,训练的效果如下:

[root@centos #] python my_seq2seq_v2.py train
begin load vectors
words = 70937
size = 200
load vectors finish
---------------------------------
Run id: 9PZWKM
Log directory: /tmp/tflearn_logs/
---------------------------------
Training samples: 368
Validation samples: 0
--
Training Step: 47  | total loss: 0.62260
| SGD | epoch: 001 | loss: 0.62260 -- iter: 047/368

最终会生成./model/model模型文件

 

效果预测

训练好模型,我们希望能输入一句话来预测一下回答,如下:

predict = model.predict(testXY)

因为我们只有question没有answer,所以testXY中是没有Y部分的,所以需要在程序中做一些改变,即用上一句的输出作为下一句的输入,如下:

for i in range(self.max_seq_len-1):# next_dec_input = tf.slice(decoder_inputs, [0, i+1, 0], [-1, 1, self.word_vec_dim])这里改成下面这句next_dec_input = decoder_output_sequence_singledecoder_output_tensor = tflearn.lstm(next_dec_input, self.word_vec_dim, return_seq=False, reuse=True, scope='decoder_lstm')decoder_output_sequence_single = tf.pack([decoder_output_tensor], axis=1)decoder_output_sequence_list.append(decoder_output_tensor)

因为词向量是多维浮点数,预测出的词向量需要通过余弦相似度来匹配,余弦相似度匹配方法如下:

def vector2word(vector):max_cos = -10000match_word = ''for word in word_vector_dict:v = word_vector_dict[word]cosine = vector_cosine(vector, v)if cosine > max_cos:max_cos = cosinematch_word = wordreturn (match_word, max_cos)

其中的vector_cosine实现如下:

def vector_cosine(v1, v2):if len(v1) != len(v2):sys.exit(1)sqrtlen1 = vector_sqrtlen(v1)sqrtlen2 = vector_sqrtlen(v2)value = 0for item1, item2 in zip(v1, v2):value += item1 * item2return value / (sqrtlen1*sqrtlen2)

其中的vector_sqrtlen实现如下:

def vector_sqrtlen(vector):len = 0for item in vector:len += item * itemlen = math.sqrt(len)return len

预测效果如下:

输入是“真 讨厌”

预测结果:

[root@centos #] python my_seq2seq_v2.py test test.data
begin load vectors
words = 70937
size = 200
load vectors finish
predict answer
竟然 0.796628661264 8.131882444280.361905373571 4.723168831810.416023172832 3.782655079830.454288467277 3.13229596833
不是 0.424590214456 2.906882310620.489174557107 2.627338024980.501460288258 2.879901784390.560230783333 3.09066126524

输出的第一列是预测的每个时序产生的词,第二列是预测输出向量和最近的词向量的余弦相似度,第三列是预测向量的欧氏距离

因为我们设计的max_seq_len是定长8,所以输出的序列最后会多余一些字,可以根据余弦相似度或者其他指标设定一个阈值来截断

以上列出的是部分代码,全部代码分享在my_seq2seq_v2.py欢迎点击观看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/72316.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

练手小项目(1)——智能聊天机器人

我一直坚信着&#xff0c;即使一个最简单的APP&#xff0c;也有他的难点&#xff0c;如果一个复杂的APP你无法做出来&#xff0c;那肯定是你基础不扎实&#xff0c;我身边的人总是问我&#xff0c;安卓为什么学了有忘记了&#xff0c;总是学不好&#xff0c;有些东西记不住&…

python微信聊天机器人,再也不怕被夸情商高了

编写本聊天机器人纯属乐趣&#xff0c;它并不实用&#xff01;&#xff01;&#xff01; 文章有点长&#xff0c;代码分析只把完整代码拆分解释&#xff0c;没有新的东西&#xff0c;大佬可忽略 目录 实现思路完整代码代码分析导入要使用的模块获取窗口句柄获取窗口左上角和右…

一个基于智能问答的聊天机器人实现

智能问答应当是未来智能化发展中人机交互的主要方式&#xff0c;目前无论是在开源社区或者企业应用中&#xff0c;都有广泛的应用。 项目名称是Iveely.Brain&#xff0c;本次源码可以在Github的这里下载&#xff0c;,是主要用于聊天服务的一个项目&#xff0c;本次开源版本的示…

【开源】一个基于智能问答的聊天机器人实现

智能问答应当是未来智能化发展中人机交互的主要方式&#xff0c;目前无论是在开源社区或者企业应用中&#xff0c;都有广泛的应用。 项目名称是Iveely.Brain&#xff0c;本次源码可以在Github的这里下载&#xff0c;,是主要用于聊天服务的一个项目&#xff0c;本次开源版本的示…

【NLP-ChatBot】能干活的聊天机器人-对话系统概述

我们之前介绍过&#xff0c;按照应用场景的不同&#xff0c;聊天机器人可以分为问答系统&#xff0c;对话系统以及闲聊机器人三类。今天我们就来详细讲一讲其中的对话系统。 作者&编辑 | 小Dream哥 1 什么是对话系统 通常来讲&#xff0c;对话系统会面向某一个任务&#xf…

【NLP】自己搭一个多轮对话聊天机器人(附实现源码)

【NLP】自己搭一个多轮对话聊天机器人&#xff08;附实现源码&#xff09; 01 项目框架02 模型2.1 粗排2.1.1BM252.1.1 Bool检索 2.2 精排意图识别 03 API交互04 微信前端 本文的内容如下 本篇介绍一个检索类型的 多轮问答系统/聊天机器人&#xff0c;通过API异步通信&#xf…

手把手教你写一个中文聊天机器人

本文来自作者 赵英俊&#xff08;Enjoy&#xff09; 在 GitChat 上分享 「手把手教你写一个中文聊天机器人」&#xff0c;「阅读原文」查看交流实录。 「文末高能」 编辑 | 哈比 一、前言 发布这篇 Chat 的初衷是想和各位一起分享一下动手来做聊天机器人的乐趣&#xff0c;因此…

NLP聊天机器人的搭建(chatbot)(一)

最近在学习研发QA系统&#xff0c;本人单纯想记录一下。项目源码和思路主要参考知乎专栏&#xff1a; PyTorch搭建聊天机器人&#xff08;一&#xff09;词表与数据加载器 - 知乎 PyTorch搭建聊天机器人&#xff08;二&#xff09;定义seq2seq网络前向逻辑 - 知乎 PyTorch搭…

全国大学生英语竞赛培训:听力、词汇语法、完形填空、阅读理解、翻译、改错、IQ题、大小作文、语法等部分快速得分、备战策略和获奖技巧讲解!

目 录 大学生英语竞赛培训——介绍、学习网址 PPT课件、视频——下载 【2020-04-05】P1 如何准备大学生英语竞赛才能拿奖&#xff1f;2:27:54【竞赛简介vs赛前准备】 【2020-04-11】P2 如何快速搞定大英赛大小作文&#xff1f;2:06:18【大小作文&#xff0c;快速表达~】 …

【情态动词练习题】 May 与 might

1. May 1.Sarah may be ill 2.We may not go out. 3.It may not rain. 4.We may buy a car. 5.Joe may not be at home 6.Anna may need help. 注&#xff1a;情态动词一定要加上动词原型 7.The baby may be hungry. 8.I may not change my job. 9.She may be married. 10.He…

初中七年级上计算机试题答案,人教版初中英语七年级英语上册期中模拟试题检测(含答案)...

原标题&#xff1a;人教版初中英语七年级英语上册期中模拟试题检测(含答案) 七年级英语期中测试题 1、 单项选择(10分) ( ) 1. 下列单词中含有相同元音因素的是_____. A that; these B thank; that C this; those ( ) 2. --________, Gina! --Good morning, Bob! A Good aftern…

初中七年级下英语期中备考单选题(外教出题并附助教经典解析)

1. My sister bought a present _______ her best friends birthday. A. for B. of C. about D. to 选出正确的介词&#xff0c;完成句子。问题&#xff1a; 我妹妹买了一份礼物给她最好的朋友庆祝生日。 答案&#xff1a;A 解析&#xff1a;在这个句子中&#xff0c;“fo…

ChatGPT 爆火 小扎、马斯克纷纷迎战ChatGPT

ChatGPT爆火&#xff0c;直接改变了整个硅谷大厂的格局。近日&#xff0c;马斯克、小扎也纷纷下场&#xff0c;正式对ChatGPT宣战&#xff01;据The Information报道&#xff0c;马斯克最近几周与一直在于AI研究人员接洽&#xff0c;希望组建一个新的研究实验室&#xff0c;以开…

百度「文心一言」阿里「通义千问」腾讯的AI将会叫什么呢

阿里于昨天2023.4.7下午上线通义千问&#xff0c;与ChatGPT类似&#xff0c;同样是基于语言模型训练的人工智能聊天平台。通义千问的核心功能分为四个大类&#xff1a;撰写短文、职场助理、电影脚本和写封邮件。 通义千问通义千问https://tongyi.aliyun.com/ 首页如下&#xf…

ChatGPT Chat Assist: 职场智能利器,提升工作效率

在当今快节奏的职场生活中&#xff0c;高效率是每位职场人士追求的目标。而现代科技的进步&#xff0c;尤其是人工智能的快速发展&#xff0c;为我们带来了前所未有的便利。ChatGPT作为一款智能核心&#xff0c;推出了Chat Assist插件&#xff0c;成为职场中的得力助手&#xf…

ChatGPT通过图灵测试,图灵测试要重写

近日《Nature》在一篇文章中称&#xff0c;ChatGPT 已经攻破了图灵测试&#xff0c;是时候要启用其他新的方法来评估人工智能技术了。 图灵测试(Turing Test)是著名计算机科学家阿兰图灵在1950年提出的一个测试,用于判断机器是否能展现出与人类智能相当的能力。其测试方法是: 让…

亚马逊云科技X创业邦:专访图灵量子创始人金贤敏

假设你现在正准备去相亲,走进了一家坐满人的咖啡厅。你拿着Ta的照片,一个个地审视着每一个人,看谁对得上号,结果找了半个小时也没找到和照片相似的那个人。这时候,相亲对象给你打来了电话,告诉你Ta正坐在靠窗的角落里,你的目光顺着ta的指引,一下子就找到了Ta。 验证一个问题的答…

马斯克与马云对谈:一场科技乐观主义者的尬聊

硅谷Live / 实地探访 / 热点探秘 / 深度探讨 即使同为技术信徒&#xff0c;话不投机也在所难免。 本文由极客公园原创&#xff0c;阅读更多内容请关注极客公园微信公众号&#xff08;ID&#xff1a;GeekPark&#xff09; 在昨天开幕的 2019 世界人工智能大会上&#xff0c;阿里…

马斯克:我抽大麻、藐视SEC,但我是个好CEO

原文&#xff1a;CBS《60分钟》编译&#xff1a;新浪科技 樵夫 导语&#xff1a;特斯拉CEO马斯克&#xff08;Elon Musk&#xff09;被人称为天才&#xff0c;人们都认为他非常具有远见卓识。 但是今年&#xff0c;相比于他的卓越才华&#xff0c;人们似乎更加关注他的行为&…

马云对话马斯克:福报变成了一周工作12小时?

燃财经&#xff08;ID:rancaijing&#xff09;整理 作者 | 刘景丰 编辑 | 魏佳 8月29日&#xff0c;2019世界人工智能大会&#xff08;WAIC&#xff09;在上海举行。开幕式后&#xff0c;美国卡内基梅隆大学计算机学院院长汤姆米切尔&#xff08;Tom Mitchell&#xff09;、腾讯…