端到端的对话系统

环境

Python 3.7
TensorFlow 1.14

模型结构

使用seq2seq + attention 模型

NLP应用

词向量层

单词->实数向量

  • 降低输入维度(one-hot输入维度与词汇表大小同)

  • 增加语义信息(稠密向量),在自然语言学习的词向量会将含义相似的词赋予值相近的词向量值

    # 为源语言和目标语言分别定义词向量。self.src_embedding = tf.get_variable("src_emb", [SRC_VOCAB_SIZE, HIDDEN_SIZE])self.trg_embedding = tf.get_variable("trg_emb", [TRG_VOCAB_SIZE, HIDDEN_SIZE])
    # 将输入和输出单词编号转为词向量。src_emb = tf.nn.embedding_lookup(self.src_embedding, src_input)trg_emb = tf.nn.embedding_lookup(self.trg_embedding, trg_input)

softmax层

将循环神经网络输出转化为一个单词表中每个单词的输出概率

            # 线性映射,将循环网络输出映射成一个维度与词汇表大小相同的向量# softmax->logoits为加和为1的概率logits = (tf.matmul(output, self.softmax_weight) + self.softmax_bias)# print(logits.shape)# 选出最可能的单词编号next_id = tf.argmax(logits, axis=1, output_type=tf.int32)

Encoder-Decoder框架

处理输入输出长短不一的多对多文本预测问题

Decoder(解码器)

从上下文的文本信息获取特征,然后预测文本。输入为单词的词向量,输出为softmax层产生单词的概率

        # 这里没有指定init_state,也就是没有使用编码器的输出来初始化输入,而完全依赖# 注意力作为信息来源。dec_outputs, _ = tf.nn.dynamic_rnn(attention_cell, trg_emb, trg_size, dtype=tf.float32)

Encoder(编码器)

对输入文本信息进行提取,尽量准确高效地表征文本的特征信息。词向量层与LSTM与解码器一样,由于编码阶段未输出,不需要softmax层。

        # 双向循环网络,顶层输出enc_outputs(seq2seq用不到),代表两个LSTM在每一步的输出。enc_outputs, enc_state = tf.nn.bidirectional_dynamic_rnn(self.enc_cell_fw, self.enc_cell_bw, src_emb, src_size, dtype=tf.float32)# 将两个LSTM的输出拼接为一个张量。enc_outputs = tf.concat([enc_outputs[0], enc_outputs[1]], -1)

注意力机制

句子较长时,中间向量难以储存足够的信息。注意力机制允许解码器查阅输入句子的单词或片段,所以不需要在中间向量中储存所有信息

左边encoder输入转换为Word embedding,进入LSTM,每个节点上输出hidden state。然后进入右侧LSTM,输出hidden state,两边hidden state作为输入放入attention中计算context vector。

前面的context vector可作为输入和目标的单词串起来作为LSTM输入,又回到一个hidden state,如此往复。

另一方面,context vector和decoder的hidden state合起来,通过非线性转换及softmax最后计算出概率

attention_mechanism = tf.contrib.seq2seq.BahdanauAttention(HIDDEN_SIZE, enc_outputs, memory_sequence_length=src_size)
# 将解码器的循环神经网络self.dec_cell和注意力一起封装成更高层的循环神经网络。attention_cell = tf.contrib.seq2seq.AttentionWrapper(self.dec_cell, attention_mechanism, attention_layer_size=HIDDEN_SIZE)

项目结构

Samples_15w:进行训练数据的预处理和存放

**pretreat_0.py:对数据集原始格式清洗****choose_some_qa.py:选择一定数量的数据**

Train_15w:存放训练的模型

Tools.py:自行编写的分词等工具,方便调用

To_word_list.py:词汇表产生

To_word_train.py:按照词汇表,将单词对应为编号

Attention_train.py:模型的训练

Attention_test.py:模型的测试

App_test.py:对聊天效果进一步封装

places.py:地名处理

数据集预处理

小黄鸡五十万对语料集

  1. pretreat_0.py对问答格式进行处理

  2. 选择一定数量问答对并分词

  3. 按照单词词频排序,构建固定大小的词汇表,加入eos, sos, unk

  4. 按词汇表对将单词映射到编号

注意点一:Padding & Batching

样本中,每个句子对通常作为独立数据训练。由于每个句子长短不一,因此放入同一个batch时,需将最短句子补齐至该batch内最长句子相同长度。(tf.data.Dataset的padded_batch函数)

LSTM读取数据时会读取填充位置纳入计算,因此:

读取填充时,跳过这一位置。(tf.nn.dynamic_rnn,读取内容和输入数据长度)使用dynamic_rnn时,每个batch最大长度不需要相同

设计损失函数时需将填充位置损失的权重设为0,,不影响梯度计算。

测试时相似,输入一个句子,但dynamic_rnn要求batch,所以输入句子整理为大小为1的batch,使用dynamic_rnn构造编码器与训练同。

# 删除内容为空(只包含<EOS>)的句子和长度过长的句子。
def FilterLength(src_tuple, trg_tuple):((src_input, src_len), (trg_label, trg_len)) = (src_tuple, trg_tuple)src_len_ok = tf.logical_and(tf.greater(src_len, 1), tf.less_equal(src_len, MAX_LEN))trg_len_ok = tf.logical_and(tf.greater(trg_len, 1), tf.less_equal(trg_len, MAX_LEN))return tf.logical_and(src_len_ok, trg_len_ok)
dataset = dataset.filter(FilterLength)
# 解码器输入trg_input,形式如同<sos> X Y Z
# 解码器输出trg_label,形式如同X Y Z <eos>
# 上面从文件中读到的目标句子是X Y Z <eos>的形式,我们需要从中生成<sos> X Y Z
# 形式并加入到Dataset中。
def MakeTrgInput(src_tuple, trg_tuple):((src_input, src_len), (trg_label, trg_len)) = (src_tuple, trg_tuple)trg_input = tf.concat([[SOS_ID], trg_label[:-1]], axis=0)return ((src_input, src_len), (trg_input, trg_label, trg_len))
dataset = dataset.map(MakeTrgInput)# 随机打乱训练数据。
dataset = dataset.shuffle(10000)# 规定填充后输出的数据维度。
padded_shapes = ((tf.TensorShape([None]),      # 源句子是长度未知的向量tf.TensorShape([])),         # 源句子长度是单个数字(tf.TensorShape([None]),      # 目标句子(解码器输入)是长度未知的向量tf.TensorShape([None]),      # 目标句子(解码器目标输出)是长度未知的向量tf.TensorShape([])))         # 目标句子长度是单个数字
# 调用padded_batch方法进行batching操作。
batched_dataset = dataset.padded_batch(batch_size, padded_shapes)
return batched_dataset

注意点二:解码的循环结构

训练时解码器可以从输入中读取完整的训练句子,所以可以用dynamic_rnn展开。但在测试解码中,只能看到输入句子,看不到目标句子。

解码器读入,预测第一个单词,再将预测的单词输入到第二步,再预测第二个……所以使用循环结构。

Tf.while_loop实现, 循环继续的条件、循环体、初始

天气查询(意图识别)

当用户输入“明天天气如何?、明天是晴天还是雨天?明天需要抹防晒霜吗?”聊天机器人只需要理解用户是想查询天气

意图识别方法:

(1)规则模板:

通过专家手工编写规则模板来识别意图。比如:买 .* 《地名》 .* 《地名》.* 机票 =》 买机票。缺点是人工编写工作量大,易冲突;规则模板覆盖面较小;适用于垂直领域,在通用领域则无法推广

(2)基于统计:

使用意图词典做词频统计,取词频最大的就是对应的意图。覆盖面比规则模板广,但容易误识别

(3)基于语法:

先对句子做语法分析,找到中心动词及名词,再根据意图词典即可识别出意图来。使用语法分析使得准确度更高了,但增加了语法识别的难度。

(4)基于机器学习和深度学习:

把意图识别看成是文本分类任务。进行语料标注,分词,和模型的搭建

天气查询(基于规则)

过程

检测对话中是否含有关于天气查询的关键词,若包含:

​ 检测对话中是否含有具体的地点,若包含:

 调用青云天气API,提纯后返回天气信息否则:询问地点若检索对话得到地点:返回天气信息没有地点:放弃,并将人类对话进行预测输出

否则:

继续对话

地名处理

搜狗词库,提取每个地名的关键词,方便后续匹配

预处理(分词or分字)

分词:jieba中文分词

分字:自己编写,中文按字切分,英文、数字、表情按词(空格)切分

效果:两种分词效果区分不大

词汇表:以15w对问答为例,分词词汇表60000+,分字词汇表13000

单个字的语义信息不明确,用字建模使捕捉字与字之间依赖关系成本提高。但单个字的词汇表大小远远小于按词切分,对于训练成本有益

Chatbot评价问题

难以实现自动化测评,主要的原因就是聊天场景的语义、语言的多样性,大部分都是靠人工评测,但是人工评测最大的问题是人工评测没办法同一批人工去评测,因此造成模型之间其实很难做完全客观的评测

一个也许可行的直接的思路:我们能不能多给一些ground truth的Response如果足够多,那么如果生成的回复能跟其中某一个有一定程度的匹配,那么这个回复就可以认为与该response再讲同一个回复的方向,因此可以用传统的metric进行度量

最终效果

部分参数设置

训练数据集大小 15w****对 Batch大小 200
词汇表大小 13000 句子最大单词数 30
LSTM隐藏层规模 1024 节点不被dropout 0.8
LSTM层数 2 切分方式 按字
Softmax层与词向量层共享参数 True 解码最大步数 100

最终效果



由于训练集的大小和整体风格限制,所以很多日常对话无法完美应对,并且回复中略显色情或暴力

代码fork

由《TensorFlow实战Google深度学习框架》翻译代码改写
GitHub: GitHub

聊天机器人chatbot搭建及思考(TensorFlow)(附代码)相关推荐

  1. chatbot聊天机器人环境搭建以及项目运行指南

    项目地址 网传有一位程序员因忙于工作,无暇陪伴女友,便做了个聊天机器人的软件来陪女友聊天,然后自己就安心工作去了.等到程序员下班时一看,机器人已经和女友聊到了二胎的娃叫啥名了.博主不明觉厉,便去拷贝一 ...

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

    最近在学习研发QA系统,本人单纯想记录一下.项目源码和思路主要参考知乎专栏: PyTorch搭建聊天机器人(一)词表与数据加载器 - 知乎 PyTorch搭建聊天机器人(二)定义seq2seq网络前向 ...

  3. 我开发了一个温柔的智能客服聊天机器人ChatBot,并回答为什么不是ChatGPT(附思路和代码)

    前言 若问2023年科技领域什么最火,那当然是ChatGPT了,这么智能的对话机器人,给人带来无限的想象,围绕着ChatpGPT的各种热点和创意层出不穷.作为一个多年从事编程开发的程序员,我对于这么大 ...

  4. 如何用tf2.0训练中文聊天机器人chatbot

    向AI转型的程序员都关注了这个号???????????? 机器学习AI算法工程   公众号:datayx 一个可以自己进行训练的中文聊天机器人, 根据自己的语料训练出自己想要的聊天机器人,可以用于智能 ...

  5. 独家 | 聊天机器人开发中的机器学习(附链接)

    作者:Omkar Prabhune 翻译:方星轩校对:王雨桐本文约2800字,建议阅读5分钟 本文作者从聊天机器人的种类.用途以及架构等角度介绍目前的聊天机器人技术,并在文末分享了一些聊天机器人行业的 ...

  6. 部署一个基于ChatGPT的微信聊天机器人以及产生的思考

    文章目录 前言 功能 反响 思考 这篇文章主要展示了基于ChatGPT的微信聊天机器人的效果,以及在部署过程中我产生的一些思考.部署一个这样的机器人的具体方法我过两天会单独写一篇文章. 前言 最近几个 ...

  7. 微信 开发 聊天机器人设计方案 java语言 程序和数据库代码

    转自:http://www.tuicool.com/articles/RBJfqyM 使用 Liferay 和 Lucene 实现企业门户智能帮助机器人 时间 2015-04-30 12:00:00  ...

  8. Netty中实现多客户端连接与通信-以实现聊天室群聊功能为例(附代码下载)

    场景 Netty的Socket编程详解-搭建服务端与客户端并进行数据传输: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1086 ...

  9. 给女朋友做个聊天机器人,这样就能安心写代码了

    这是第 404 次女友因为我没有及时回微信而和我生气了 惹祸的是我,受伤的确是钱包-- 但是,我并不后悔 那一局王者荣耀,因为没有回微信,我完成了五杀 carry 全场 那一局刺激战场,因为没有回微信 ...

最新文章

  1. 保护模式下GDTR,LDTR,全局描述符表,局部描述符表和选择器的关系
  2. Multipart/form-data POST文件上传详解
  3. uboot启动第二阶段——start_armboot
  4. 计算机窗口设计java实验,Java银行取款异常处理计算器设计图形用户界面设计实验报告.doc...
  5. Jenkins系列之二——centos 6.9 + JenKins 安装
  6. “引才入湘”大行动正式启动,CSDN携手万兴科技助力长沙打造人才品牌
  7. 谷歌 Daydream VR 开发工具
  8. springboot之idea无法添加包
  9. FreeRTOS学习-day01
  10. 洛谷 P1359 租用游艇(Floyd, Dijkstra,SPFA)
  11. 置信区间的临界值_在进行区间估计时,若要求置信水平为95%,则相应的临界值为...
  12. 修改linux域名解析失败,kali 更新域名解析失败问题解决办法
  13. 泛型转换https://www.cnblogs.com/eason-chan/p/3633210.html
  14. 新房装修步骤有哪些工序? 新房装修步骤要注意哪些问题?
  15. 正电子计算机全身显像(pet ct),正电子发射型计算机断层显像CT (PET-CT)避 免漏诊眼睑恶性肿瘤伴全身转移一例...
  16. 发生系统错误1067
  17. 夫妻驾驶途中打瞌睡 车辆定速巡航120迈飞下四米高速路
  18. 齿轮振动信号的数字滤波处理-含Matlab代码
  19. 谈一下我是如何从使用json-lib到投入fastjson的怀抱....
  20. 2020南京理工大学计算机考研经验

热门文章

  1. python操作手机app超详细步骤
  2. 每日一课 | 如何用Python编写一个Lisp解释器
  3. mysql的COALESCE函数、NULLIF函数、IFNULL函数
  4. js 中 java 代码_在js中嵌套java代码
  5. STM32学习笔记(三)——外部中断的使用
  6. 服务器2012还原系统,Windows Server 2012如何进行系统映像还原
  7. Python 数据结构 之 线性表 的链式存储结构
  8. Unity3d Camera FOV
  9. 实战案例 :电信客户流失分析与预测
  10. button渐变色 ios_ios开发