下面使用了双向LSTM和注意力机制

一.数据集准备

我用的是 小黄鸡问答语料库,分为分词前,分词后,我用的是分词后

二.数据预处理

1.生成词汇表(这里选取的前2500个常用词)

import collections
import codecs
from operator import itemgetter
counter=collections.Counter()
with codecs.open('C://RNN//Chat//小黄鸡.conv',encoding='utf-8') as f:for line in f:for word in line.strip().split():for w in word:if w!='M' and w!='E':counter[w]+=1sorted_word_to_cnt=sorted(counter.items(),key=itemgetter(1),reverse=True)sorted_words=[x[0] for x in sorted_word_to_cnt]
sorted_words=["<unk>","<sos>","<eos>"]+sorted_wordssorted_words=sorted_words[:2500]with codecs.open('C://RNN//Chat//vocab.txt','w',encoding='utf-8') as f:for word in sorted_words:f.write(word+"\n")

2.把语料库里的问题与回答分开

这里可以看出,从零开始计数的话,偶数的M 后面跟的是问题,奇数M后面跟的是回答,所以按照如下分开

import codecs
import numpy as np
que=[]
ans=[]
index=0
with codecs.open('C://RNN//Chat//train.txt','r','utf-8') as f:for line in f.readlines():if line[0]=='M':if index % 2 == 0:que.append(line[2:])index += 1elif index %2==1:index+=1ans.append(line[2:])
np.save('C://RNN//Chat//question.npy',que)
np.save('C://RNN//Chat//answer.npy',ans)

3.把问题与答案转化为数字(回答 同下)

ques=np.load("C://RNN//Chat//question.npy")
convert_qs=[]
for line in ques:for word in line:convert_qs.append(get_id(word))convert_qs.append('\n')
np.savetxt('convert_qs.txt',convert_qs,fmt ='%s')

4.接下来还是数据的处理(这里处理后每一个batch的每一个例子是

((src_input,src_len),(trg_input,trg_label,trg_len))
解码器需要两种格式的目标句子:
#   1.解码器的输入(trg_input),形式如同"<sos> X Y Z"
#   2.解码器的目标输出(trg_label),形式如同"X Y Z <eos>"
# 上面从文件中读到的目标句子是"X Y Z <eos>"的形式,我们需要从中生成"<sos> X Y Z"
# 形式并加入到Dataset中。
import tensorflow as tfquestion_path='C://RNN//Chat//convert_qs.txt'
answer_path='C://RNN//Chat//convert_as.txt'MAX_LEN=30
SOS_ID=1
HIDDEN_SIZE=1024
NUM_LAYERS=2
VOCAB_SIZE=2500
SHARE_EMB_AND_SOFTMAX=True
KEEP_PROB=0.8
MAX_GRAD_NORM=5
LR=1
CHECKPOINT_PATH='C://RNN//Chat//save'
BATCH_SIZE=64
NUM_EPOCH=20
def MakeDataset(file_path):dataset=tf.data.TextLineDataset(file_path)dataset=dataset.map(lambda string:tf.string_split([string]).values)dataset=dataset.map(lambda string:tf.string_to_number(string,tf.int32))dataset=dataset.map(lambda x:(x,tf.size(x)))return datasetdef MakeSrcTrgDataset(src_path,trg_path,batch_size):src_data=MakeDataset(src_path)trg_data=MakeDataset(trg_path)dataset=tf.data.Dataset.zip((src_data,trg_data))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)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)padded_shapes=((tf.TensorShape([None]),tf.TensorShape([])),(tf.TensorShape([None]),tf.TensorShape([None]),tf.TensorShape([])))batched_dataset=dataset.padded_batch(batch_size,padded_shapes)return batched_dataset

5.搭建模型

class NMTModel(object):# 在模型的初始化函数中定义模型要用到的变量。def __init__(self):# 定义编码器和解码器所使用的LSTM结构。self.dec_cell = tf.nn.rnn_cell.MultiRNNCell([tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE)for _ in range(NUM_LAYERS)])self.enc_cell_fw=tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE)self.enc_cell_bw=tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE)# 为源语言和目标语言分别定义词向量。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])# 定义softmax层的变量if SHARE_EMB_AND_SOFTMAX:self.softmax_weight = tf.transpose(self.trg_embedding)else:self.softmax_weight = tf.get_variable("weight", [HIDDEN_SIZE, TRG_VOCAB_SIZE])self.softmax_bias = tf.get_variable("softmax_bias", [TRG_VOCAB_SIZE])# 在forward函数中定义模型的前向计算图。# src_input, src_size, trg_input, trg_label, trg_size分别是上面# MakeSrcTrgDataset函数产生的五种张量。def forward(self, src_input, src_size, trg_input, trg_label, trg_size):batch_size = tf.shape(src_input)[0]# 将输入和输出单词编号转为词向量。src_emb = tf.nn.embedding_lookup(self.src_embedding, src_input)trg_emb = tf.nn.embedding_lookup(self.trg_embedding, trg_input)# 在词向量上进行dropout。src_emb = tf.nn.dropout(src_emb, KEEP_PROB)trg_emb = tf.nn.dropout(trg_emb, KEEP_PROB)# 使用dynamic_rnn构造编码器。# 编码器读取源句子每个位置的词向量,输出最后一步的隐藏状态enc_state。# 因为编码器是一个双层LSTM,因此enc_state是一个包含两个LSTMStateTuple类# 张量的tuple,每个LSTMStateTuple对应编码器中的一层。# enc_outputs是顶层LSTM在每一步的输出,它的维度是[batch_size,# max_time, HIDDEN_SIZE]。Seq2Seq模型中不需要用到enc_outputs,而# 后面介绍的attention模型会用到它。#outputs是最后一层每个step的输出,它的结构是[batch_size,step,HIDDEN_SIZE] =# states是每一层的最后那个step的输出with tf.variable_scope("encoder"):#构造编码器时,bidirectional_dynamic_rnn构造双向循环网络。#双向循环网络的顶层输出enc_outputs是一个包含两个张量的元祖,每个张量的#维度都是[batch_size,max_time,HIDDEN_SIZE],代表两个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)enc_outputs=tf.concat([enc_outputs[0],enc_outputs[1]],-1)# 使用dyanmic_rnn构造解码器。# 解码器读取目标句子每个位置的词向量,输出的dec_outputs为每一步# 顶层LSTM的输出。dec_outputs的维度是 [batch_size, max_time,HIDDEN_SIZE]。# initial_state=enc_state表示用编码器的输出来初始化第一步的隐藏状态。with tf.variable_scope("decoder"):#选择注意力模型权重的计算模型。BahdanauAttention是使用一个隐藏层的前馈神经网络。#memory_sequence_length是一个维度为[batch_size]的张量,代表batch中每个句子的长度,# Attention需要根据这个信息把填充位置的权重设置为0attention_mechanism=tf.contrib.seq2seq.BahdanauAttention(HIDDEN_SIZE,enc_outputs,memory_sequence_length=src_size)attention_cell=tf.contrib.seq2seq.AttentionWrapper(self.dec_cell,attention_mechanism,attention_layer_size=HIDDEN_SIZE)dec_outputs,_=tf.nn.dynamic_rnn(attention_cell,trg_emb,trg_size,dtype=tf.float32)# 计算解码器每一步的log perplexity。这一步与语言模型代码相同。output = tf.reshape(dec_outputs,[-1,HIDDEN_SIZE])logits = tf.matmul(output, self.softmax_weight)+self.softmax_biasloss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=tf.reshape(trg_label, [-1]), logits=logits)# 在计算平均损失时,需要将填充位置的权重设置为0,以避免无效位置的预测干扰# 模型的训练。label_weights = tf.sequence_mask(trg_size, maxlen=tf.shape(trg_label)[1], dtype=tf.float32)label_weights = tf.reshape(label_weights, [-1])cost = tf.reduce_sum(loss * label_weights)cost_per_token = cost / tf.reduce_sum(label_weights)# 定义反向传播操作。反向操作的实现与语言模型代码相同。trainable_variables = tf.trainable_variables()# 控制梯度大小,定义优化方法和训练步骤。grads = tf.gradients(cost / tf.to_float(batch_size),trainable_variables)grads, _ = tf.clip_by_global_norm(grads, MAX_GRAD_NORM)optimizer = tf.train.GradientDescentOptimizer(learning_rate=1.0)train_op = optimizer.apply_gradients(zip(grads, trainable_variables))return cost_per_token, train_op

6.训练函数

# 使用给定的模型model上训练一个epoch,并返回全局步数。
# 每训练200步便保存一个checkpoint。
def run_epoch(session, cost_op, train_op, saver, step):# 训练一个epoch。# 重复训练步骤直至遍历完Dataset中所有数据。while True:try:# 运行train_op并计算损失值。训练数据在main()函数中以Dataset方式提供。cost, _ = session.run([cost_op, train_op])if step % 10 == 0:print("After %d steps, per token cost is %.3f" % (step, cost))# 每200步保存一个checkpoint。if step % 200 == 0:saver.save(session, CHECKPOINT_PATH, global_step=step)step += 1except tf.errors.OutOfRangeError:breakreturn stepdef main():# 定义初始化函数。initializer = tf.random_uniform_initializer(-0.05, 0.05)# 定义训练用的循环神经网络模型。with tf.variable_scope("nmt_model", reuse=None,initializer=initializer):train_model = NMTModel()# 定义输入数据。data = MakeSrcTrgDataset(SRC_TRAIN_DATA, TRG_TRAIN_DATA, BATCH_SIZE)iterator = data.make_initializable_iterator()(src, src_size), (trg_input, trg_label, trg_size) = iterator.get_next()# 定义前向计算图。输入数据以张量形式提供给forward函数。cost_op, train_op = train_model.forward(src, src_size, trg_input,trg_label, trg_size)# 训练模型。saver = tf.train.Saver()step = 0with tf.Session() as sess:tf.global_variables_initializer().run()for i in range(NUM_EPOCH):print("In iteration: %d" % (i + 1))sess.run(iterator.initializer)step = run_epoch(sess, cost_op, train_op, saver, step)
if __name__ == "__main__":main()

7.上面的代码只能来训练,接下来是测试

import tensorflow as tf
import codecs
import argparseCHECKPOINT_PATH='C://RNN//Chat//./save'HIDDEN_SIZE=1024
NUM_LAYERS=2
VOCAB_SIZE=2500
SHARE_EMB_AND_SOFTMAX=True
SOS_ID=1
EOS_ID=2class NMTModel(object):def __init__(self):self.enc_cell_fw=tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE)self.enc_cell_bw=tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE)# self.enc_cell=tf.nn.rnn_cell.MultiRNNCell(#     [tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE)#      for _ in range(NUM_LAYERS)])self.dec_cell=tf.nn.rnn_cell.MultiRNNCell([tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE)for _ in range(NUM_LAYERS)])self.src_embedding=tf.get_variable('src_emb',[VOCAB_SIZE,HIDDEN_SIZE])self.trg_embedding=tf.get_variable('trg_emb',[VOCAB_SIZE,HIDDEN_SIZE])if SHARE_EMB_AND_SOFTMAX:self.softmax_weight=tf.transpose(self.trg_embedding)else:self.softmax_weight=tf.get_variable('weight',[HIDDEN_SIZE,VOCAB_SIZE])self.softmax_bias=tf.get_variable('softmax_bias',[VOCAB_SIZE])def inference(self,src_input):src_size=tf.convert_to_tensor([len(src_input)],dtype=tf.int32)src_input=tf.convert_to_tensor([src_input],dtype=tf.int32)src_emb=tf.nn.embedding_lookup(self.src_embedding,src_input)with tf.variable_scope('encoder'):# enc_outputs,enc_state=tf.nn.dynamic_rnn(#     self.enc_cell,src_emb,src_size,dtype=tf.float32)enc_outputs, enc_state = tf.nn.bidirectional_dynamic_rnn(self.enc_cell_fw, self.enc_cell_bw, src_emb, src_size, dtype=tf.float32)enc_outputs = tf.concat([enc_outputs[0], enc_outputs[1]], -1)with tf.variable_scope('decoder'):attention_mechanism=tf.contrib.seq2seq.BahdanauAttention(HIDDEN_SIZE,enc_outputs,memory_sequence_length=src_size)attention_cell=tf.contrib.seq2seq.AttentionWrapper(self.dec_cell,attention_mechanism,attention_layer_size=HIDDEN_SIZE)MAX_DEC_LEN=100with tf.variable_scope('decoder/rnn/attention_wrapper'):init_array=tf.TensorArray(dtype=tf.int32,size=0,dynamic_size=True,clear_after_read=False)init_array=init_array.write(0,SOS_ID)init_loop_var=(attention_cell.zero_state(batch_size=1,dtype=tf.float32),init_array,0)def continue_loop_condition(state,trg_ids,step):return tf.reduce_all(tf.logical_and(tf.not_equal(trg_ids.read(step),EOS_ID),tf.less(step,MAX_DEC_LEN-1)))def loop_body(state,trg_ids,step):trg_input=[trg_ids.read(step)]trg_emb=tf.nn.embedding_lookup(self.trg_embedding,trg_input)dec_outputs,next_state=attention_cell.call(state=state,inputs=trg_emb)output=tf.reshape(dec_outputs,[-1,HIDDEN_SIZE])logits=(tf.matmul(output,self.softmax_weight)+self.softmax_bias)next_id=tf.argmax(logits,axis=1,output_type=tf.int32)trg_ids=trg_ids.write(step+1,next_id[0])return next_state,trg_ids,step+1state,trg_ids,step=tf.while_loop(continue_loop_condition,loop_body,init_loop_var)return trg_ids.stack()
def content(words,word_to_id):test_sentence = wordstest_sentence = [word_to_id[x] for x in test_sentence]test_sentence.append(word_to_id['<eos>'])return test_sentencedef main():with codecs.open('C://RNN//Chat//vocab.txt', 'r', encoding='utf-8') as f:vocab = [w.strip() for w in f.readlines()]word_to_id = {k: v for (k, v) in zip(vocab, range(len(vocab)))}id_to_word = {k: v for (k, v) in enumerate(vocab)}with tf.Session() as sess:with tf.variable_scope("nmt_model", reuse=None):model = NMTModel()words = input()test_sentence = content(words, word_to_id)output_op = model.inference(test_sentence)saver=tf.train.Saver()saver.restore(sess,CHECKPOINT_PATH)output = sess.run(output_op)output = ''.join([id_to_word[x] for x in output])print(output[5:-5])if __name__=='__main__':main()

最后有个说大也大说小也小的缺陷,就是不能连续输入。。。。我开始在test里加了while True  但一直会报错。。。(ˉ▽ˉ;)...

tensorflow seq2seq 聊天机器人相关推荐

  1. 基于tensorflow的聊天机器人

    ** 基于tensorflow的聊天机器人 ** 基于Tensorflow的聊天机器人,主要基于机器深度学习,采用seq2seq+Attention模型,先由jieba中文分词框架对汉字文本语句分词再 ...

  2. 如何用TensorFlow训练聊天机器人(附github)

    前言 实际工程中很少有直接用深度学习实现端对端的聊天机器人,但这里我们来看看怎么用深度学习的seq2seq模型来实现一个简易的聊天机器人.这篇文章将尝试使用TensorFlow来训练一个基于seq2s ...

  3. 利用seq2seq 聊天机器人做出鲁迅体

    背景 利用 luojiangtao 这位大神https://github.com/luojiangtao/ChatBot_web 的代码,灵感来源http://www.shareditor.com/b ...

  4. 11步,教你创建深度学习聊天机器人

    全文共4687字,预计学习时长9分钟 创建一款聊天机器人时,目标应该是令其仅需最少的人类干预甚至无需人类干预.这一目标可通过两种方法实现. 第一种方法是,客服团队接收来自人工智能的建议,以改进客户服务 ...

  5. 自动聊天机器人项目班

    打造传统NLP聊天机器人 第1课 聊天机器人的基础模型与综述 知识点1:行业与业界综述 实战项目:最简单的Rule-Base聊天机器人 第2课 NLP基础及扫盲 知识点1:NLP基本算法 实战项目:经 ...

  6. 目前最新《自动聊天机器人项目班 [一门课搞定聊天机器人]》

    .打造传统NLP聊天机器人 第1课 聊天机器人的基础模型与综述 知识点1:行业与业界综述 实战项目:最简单的Rule-Base聊天机器人 第2课 NLP基础及扫盲 知识点1:NLP基本算法 实战项目: ...

  7. RNN聊天机器人与Beam Search [Tensorflow Seq2Seq]

    本博客分析了一个Tensorflow实现的开源聊天机器人项目deepQA,首先从数据集上和一些重要代码上进行了说明和阐述,最后针对于测试的情况,在deepQA项目上实现了Beam Search的方法, ...

  8. Tensorflow搞一个聊天机器人

     Tensorflow搞一个聊天机器人 catalogue 0. 前言 1. 训练语料库 2. 数据预处理 3. 词汇转向量 4. 训练 5. 聊天机器人 - 验证效果 0. 前言 不是搞机器学习 ...

  9. 我用 tensorflow 实现的“一个神经聊天模型”:一个基于深度学习的聊天机器人

    我用 tensorflow 实现的"一个神经聊天模型":一个基于深度学习的聊天机器人 个工作尝试重现这个论文的结果A Neural Conversational Model(aka ...

最新文章

  1. gt,gte,lt,lte缩写的含义
  2. PHP类的静态(static)方法和静态(static)变量使用介绍
  3. 20165301 预备作业二:学习基础和C语言基础调查
  4. 轻松与外来客户进行REST通信
  5. python中cookies怎么用_Cookie在python爬虫中怎么用?Cookielib又是什么?
  6. 同一工作组无法访问_工作组、AD、域、DC...
  7. 把Python函数转换成能在SQL语句中调用的函数
  8. xlrd读取所有sheet名_如何在Python对Excel进行读取
  9. Delphi XE开发 Android 开机自动启动
  10. 11.Linux/Unix 系统编程手册(上) -- 系统限制和选项
  11. Date 当前程序日期格式 参数设置 DecimalSeparator
  12. leetcode[81]Search in Rotated Sorted Array II
  13. 股票做手回忆录中的精华
  14. 华为HCNA独家视频课程
  15. Programming Ruby读书笔记
  16. OKRs-E,转变只追求结果的旧观念
  17. Scrapy之10行代码爬下电影天堂全站
  18. C语言程序设计---读书笔记汇总(整理中)
  19. u盘怎么制作linux系统盘,如何制作LinuxU盘安装盘
  20. 数学软件四大家族——Maple、MATLAB、MathCAD和Mathematica优缺点比较

热门文章

  1. 林业及其他专业 arcgis小班编号问题
  2. 蒟蒻の小窝(快速幂)
  3. Dell服务器 iDRAC(IPMI) 连接管理服务器
  4. 金三银四想拿到20K的高薪offer,到底是不是痴人说梦
  5. 微语录(2010-12-31—2011-0108)
  6. html5绘制八卦图,用cad画八卦图的方法步骤详解
  7. nn.Sequential nn.ModuleList
  8. matlab卷积码记忆长度,用matlab中simulink仿真卷积码参数设置
  9. 编程入门注重实践还是注重理论?气宗剑宗之争的观点汇总。
  10. Calendar:日历图