共计 5729 个字符,预计需要花费 15 分钟才能阅读完成。
原文地址:http://www.leiphone.com/news/201702/4OZau7OfcNO0v1u5.html
第一篇传送门:聊天机器人的发展状况与分类
第二篇传送门:基于规则和检索的聊天机器人引擎
本篇文章以这个 开源项目 为主线进行。
数据预处理
模型能聊的内容也取决于选取的语料。如果已经具备了原始聊天数据,可以用 SQL 通过关键字查询一些对话,也就是从大库里选取出一个小库来训练。从一些论文上,很多 算法 都是在数据预处理层面的,比如 Mechanism-Aware Neural Machine for Dialogue Response Generation 就介绍了,从大库中抽取小库,然后再进行融合,训练出有特色的对话来。
【图 3-1】语料预处理, Ref. #7
对于英语,需要了解NLTK,NLTK 提供了加载语料,语料标准化,语料分类,PoS 词性标注,语意抽取等功能。
另一个功能强大的工具库是CoreNLP,作为 Stanford 开源出来的工具,特色是实体标注,语意抽取,支持多种语言。
下面主要介绍两个内容:
中文分词
现在有很多 中文分词的 SDK,分词的算法也比较多,也有很多文章对不同 SDK 的性能做比较。做中文分词的示例代码如下。
# coding:utf8
”’
Segmenter with Chinese
”’import jieba
import langiddef segment_chinese_sentence(sentence):
”’
Return segmented sentence.
”’
seg_list = jieba.cut(sentence, cut_all=False)
seg_sentence = u” “.join(seg_list)
return seg_sentence.strip().encode(‘utf8′)def process_sentence(sentence):
”’
Only process Chinese Sentence.
”’
if langid.classify(sentence)[0] == ‘zh’:
return segment_chinese_sentence(sentence)
return sentenceif __name__ == “__main__”:
print(process_sentence(‘ 飞雪连天射白鹿 ’))
print(process_sentence(‘I have a pen.’))
以上使用了 langid 先判断语句是否是中文,然后使用 jieba 进行分词。
在功能上,jieba 分词支持全切分模式,精确模式和搜索引擎模式。
全切分:输出所有分词。
精确:概率上的最佳分词。
所有引擎模式:对精确切分后的长句再进行分词。
jieba 分词的实现
主要是分成下面三步:
1、加载字典,在内存中建立字典空间。
字典的构造是每行 一个词,空格,词频,空格,词性。
上诉书 3 n
上诉人 3 n
上诉期 3 b
上诉状 4 n
上课 650 v
建立字典空间的是使用 Python 的 dict,采用前缀数组的方式。
使用前缀数组的原因是树结构只有一层 – word:freq,效率高,节省空间。比如单词 ”dog”, 字典中将这样存储:
{
“d”: 0,
“do”: 0,
“dog”: 1 # value 为词频
}
字典空间的主要用途是对输入句子建立有向无环图,然后根据算法进行切分。算法的取舍主要是根据模式 – 全切,精确还是搜索。
2、对输入的语句分词,首先是建立一个有向无环图。
有向无环图, Directed acyclic graph (音 /ˈdæɡ/)。
【图 3-2】DAG
DAG 对于后面计算最大概率路径和使用 HNN 模型识别新词有直接关系。
3、按照模式,对有向无环图进行遍历,比如,在精确模式下,便利就是求最大权重和的路径,权重来自于在字典中定义的词频。对于没有出现在词典中的词,连续的单个字符也许会构成新词。然后用 HMM 模型和 Viterbi 算法识别新词。
精确模型切词:使用 动态规划 对最大概率路径进行求解。
最大概率路径:求 route = (w1, w2, w3 ,.., wn),使得 Σweight(wi)最大。Wi 为该词的词频。
更多的细节还需要读一下 jieba 的 源码。
自定义字典
jieba 分词默认的字典是:1998 人民日报的切分语料还有一个 msr 的切分语料和一些 txt 小说。开发者可以自行添加字典,只要符合字典构建的格式就行。
jieba 分词同时提供接口添加词汇。
Word embedding
使用 机器学习 训练的语言模型,网络算法是使用数字进行计算,在输入进行编码,在输出进行解码。word embedding 就是编解码的手段。
【图 3-3】word embedding, Ref. #7
word embedding 是文本的数值化表示方法。表示法包括 one-hot,bag of words,N-gram,分布式表示,共现矩阵等。
Word2vec
近年来,word2vec被广泛采用。Word2vec 输入文章或者其他语料,输出语料中词汇建设的词向量空间。详细可参考word2vec 数学原理解析。
- 使用 word2vec
安装 完成后,得到 word2vec 命令行工具。
word2vec -train “data/review.txt”
-output “data/review.model”
-cbow 1
-size 100
-window 8
-negative 25
-hs 0
-sample 1e-4
-threads 20
-binary 1
-iter 15
-train “data/review.txt” 表示在指定的语料库上训练模型
-cbow 1 表示用 cbow 模型,设成 0 表示用 skip-gram 模型
-size 100 词向量的维度为 100
-window 8 训练窗口的大小为 8 即考虑一个单词的前八个和后八个单词
-negative 25 -hs 0 是使用 negative sample 还是 HS 算法
-sample 1e-4 采用阈值
-threads 20 线程数
-binary 1 输出 model 保存成 2 进制
-iter 15 迭代次数
在训练完成后,就得到一个 model,用该 model 可以查询每个词的词向量,在词和词之间求距离,将不同词放在数学公式中计算输出相关性的词。比如:
vector(“ 法国 ”) – vector(“ 巴黎) + vector(“ 英国 ”) = vector(“ 伦敦 ”)”
对于训练不同的语料库,可以单独的训练词向量模型,可以利用已经训练好的模型。
其它训练词向量空间工具推荐:Glove。
Seq2Seq
2014 年,Sequence to Sequence Learning with Neural Networks提出了使用深度学习技术,基于 RNN 和 LSTM 网络训练翻译系统,取得了突破,这一方法便应用在更广泛的领域,比如问答系统,图像字幕,语音识别,撰写诗词等。Seq2Seq 完成了【encoder + decoder -> target】的映射,在上面的论文中,清晰的介绍了实现方式。
【图 3-4】Seq2Seq, Ref. #1
也有很多文章解读它的原理。在使用 Seq2Seq 的过程中,虽然也研究了它的结构,但我还不认为能理解和解释它。下面谈两点感受:
a. RNN 保存了语言顺序的特点,这和 CNN 在处理带有形状的模型时如出一辙,就是数学模型的设计符合物理模型。
【图 3-5】RNN, Ref. #6
b. LSTM Cell 的复杂度对应了自然语言处理的复杂度。
【图 3-6】LSTM, Ref. #6
理由是,有人将 LSTM Cell 尝试了多种其它方案传递状态,结果也很好。
【图 3-7】GRU, Ref. #6
LSTM 的一个替代方案:GRU。只要 RNN 的 Cell 足够复杂,它就能工作的很好。
使用 DeepQA2 训练语言模型
准备工作,下载项目:
Git clone https://github.com/Samurais/DeepQA2.git
cd DeepQA2
open README.md # 根据 README.md 安装依赖包
DeepQA2 将工作分成三个过程:
- 数据预处理:从语料库到数据字典。
- 训练模型:从数据字典到语言模型。
- 提供服务:从语言模型到 RESt API。
预处理
DeepQA2 使用 Cornell Movie Dialogs Corpus 作为 demo 语料库。
原始数据就是movie_lines.txt 和movie_conversations.txt。这两个文件的组织形式参考README.txt
deepqa2/dataset/preprocesser.py是将这两个文件处理成数据字典的模块。
train_max_length_enco 就是问题的长度,train_max_length_deco 就是答案的长度。在语料库中,大于该长度的部分会被截断。
程序运行后,会生成 dataset-cornell-20.pkl 文件,它加载到 python 中是一个字典:
word2id 存储了{word: id},其中 word 是一个单词,id 是 int 数字,代表这个单词的 id。
id2word 存储了{id: word}。
trainingSamples 存储了问答的对话对。
比如 [[[1,2,3],[4,5,6]], [[7,8,9], [10, 11, 12]]]
1,2,3 … 12 都是 word id。
[1,2,3] 和 [4,5,6] 构成一个问答。[7,8,9] 和 [10, 11, 12] 构成一个问答。
开始训练
cp config.sample.ini config.ini # modify keys
python deepqa2/train.py
config.ini 是配置文件, 根据 config.sample.ini 进行修改。训练的时间由 epoch,learning rate, maxlength 和对话对的数量而定。
deepqa2/train.py 大约 100 行,完成数据字典加载、初始化 tensorflow 的 session,saver,writer、初始化神经元模型、根据 epoch 进行迭代,保存模型到磁盘。
session 是网络图,由 placeholder, variable, cell, layer, output 组成。
saver 是保存 model 的,也可以用来恢复 model。model 就是实例化 variable 的 session。
writer 是查看 loss fn 或者其他开发者感兴趣的数据的收集器。writer 的结果会被 saver 保存,然后使用 tensorboard 查看。
【图 3-8】TensorBoard
Model
Model 的构建要考虑输入,状态,softmax,输出。
定义损耗函数,使用 AdamOptimizer 进行迭代。
最后,参考一下训练的 loop 部分。
每次训练,model 会被存储在 save 路径下,文件夹的命名根据机器的 hostname,时间戳生成。
提供服务
在 TensorFlow 中,提供了标准的 serving 模块 – tensorflow serving。但研究了很久,还专门看了一遍《C++ Essentials》,还没有将它搞定,社区也普遍抱怨 tensorflow serving 不好学,不好用。训练结束后,使用下面的脚本启动服务,DeepQA2 的 serve 部分还是调用 TensorFlow 的 python api。
cd DeepQA2/save/deeplearning.cobra.vulcan.20170127.175256/deepqa2/serve
cp db.sample.sqlite3 db.sqlite3
python manage.py runserver 0.0.0.0:8000
测试
POST /api/v1/question HTTP/1.1
Host: 127.0.0.1:8000
Content-Type: application/json
Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=
Cache-Control: no-cache{“message”: “good to know”}
response
{
“rc”: 0,
“msg”: “hello”
}
serve 的核心代码在 serve/api/chatbotmanager.py 中。
使用脚本
scripts/start_training.sh 启动训练
scripts/start_tensorboard.sh 启动 Tensorboard
对模型的评价
目前代码具有很高的维护性,这也是从 DeepQA 项目进行重构的原因,更清晰的数据预处理、训练和服务。有新的变更可以添加到 deepqa2/models 中,然后在 train.py 和 chatbotmanager.py 变更一下。
有待改进的地方
a. 新建 models/rnn2.py, 使用 dropout。目前 DeepQA 中已经使用了 Drop.
b. tensorflow rc0.12.x 中已经提供了 seq2seq network,可以更新成 tf 版本.
c. 融合训练,目前 model 只有一个库,应该是设计一个新的模型,支持一个大库和小库,不同权重进行,就如 Mechanism-Aware Neural Machine for Dialogue Response Generation 的介绍。
d. 代码支持多机多 GPU 运行。
e. 目前训练的结果都是 QA 对,对于一个问题,可以有多个答案。
f. 目前没有一个方法进行 accuracy 测试,一个思路是在训练中就提供干扰项,因为当前只有正确的答案,如果提供错误的答案(而且越多越好),就可以使用 recall_at_k 方法进行测试。
最后
欢迎联系我,尤其是业内人士,给予指正,一起优化。
本系列完结。
References
1. A Neural Conversational Model
2. Sequence to Sequence Learning with Neural Networks
4. Efficient Estimation of Word Representations in Vector Space
5. jieba 分词分析
6. Tensorflow and deep learning – without a PhD by Martin Görner