nlp文本处理开源工具,及聊天机器人实现

2,636次阅读
没有评论

共计 5729 个字符,预计需要花费 15 分钟才能阅读完成。

原文地址:http://www.leiphone.com/news/201702/4OZau7OfcNO0v1u5.html

第一篇传送门:聊天机器人的发展状况与分类

第二篇传送门:基于规则和检索的聊天机器人引擎

本篇文章以这个 开源项目 为主线进行。

数据预处理

模型能聊的内容也取决于选取的语料。如果已经具备了原始聊天数据,可以用 SQL 通过关键字查询一些对话,也就是从大库里选取出一个小库来训练。从一些论文上,很多 算法 都是在数据预处理层面的,比如 Mechanism-Aware Neural Machine for Dialogue Response Generation 就介绍了,从大库中抽取小库,然后再进行融合,训练出有特色的对话来。

nlp 文本处理开源工具,及聊天机器人实现

【图 3-1】语料预处理, Ref. #7

对于英语,需要了解NLTK,NLTK 提供了加载语料,语料标准化,语料分类,PoS 词性标注,语意抽取等功能。

另一个功能强大的工具库是CoreNLP,作为 Stanford 开源出来的工具,特色是实体标注,语意抽取,支持多种语言。

下面主要介绍两个内容:

中文分词

现在有很多 中文分词的 SDK,分词的算法也比较多,也有很多文章对不同 SDK 的性能做比较。做中文分词的示例代码如下。

# coding:utf8
”’
Segmenter with Chinese
”’

import jieba
import langid

def 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 sentence

if __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æɡ/)。

nlp 文本处理开源工具,及聊天机器人实现

【图 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 就是编解码的手段。

nlp 文本处理开源工具,及聊天机器人实现

【图 3-3】word embedding, Ref. #7

word embedding 是文本的数值化表示方法。表示法包括 one-hot,bag of words,N-gram,分布式表示,共现矩阵等。

Word2vec

nlp 文本处理开源工具,及聊天机器人实现

近年来,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】的映射,在上面的论文中,清晰的介绍了实现方式。

nlp 文本处理开源工具,及聊天机器人实现

【图 3-4】Seq2Seq, Ref. #1

也有很多文章解读它的原理。在使用 Seq2Seq 的过程中,虽然也研究了它的结构,但我还不认为能理解和解释它。下面谈两点感受:

a. RNN 保存了语言顺序的特点,这和 CNN 在处理带有形状的模型时如出一辙,就是数学模型的设计符合物理模型。

nlp 文本处理开源工具,及聊天机器人实现

【图 3-5】RNN, Ref. #6

b. LSTM Cell 的复杂度对应了自然语言处理的复杂度。

nlp 文本处理开源工具,及聊天机器人实现

【图 3-6】LSTM, Ref. #6

理由是,有人将 LSTM Cell 尝试了多种其它方案传递状态,结果也很好。

nlp 文本处理开源工具,及聊天机器人实现

【图 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是将这两个文件处理成数据字典的模块。

nlp 文本处理开源工具,及聊天机器人实现

train_max_length_enco 就是问题的长度,train_max_length_deco 就是答案的长度。在语料库中,大于该长度的部分会被截断。

程序运行后,会生成 dataset-cornell-20.pkl 文件,它加载到 python 中是一个字典:

nlp 文本处理开源工具,及聊天机器人实现

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 查看。

nlp 文本处理开源工具,及聊天机器人实现

【图 3-8】TensorBoard

Model

Model 的构建要考虑输入,状态,softmax,输出。

nlp 文本处理开源工具,及聊天机器人实现

定义损耗函数,使用 AdamOptimizer 进行迭代。

nlp 文本处理开源工具,及聊天机器人实现

最后,参考一下训练的 loop 部分。

nlp 文本处理开源工具,及聊天机器人实现

每次训练,model 会被存储在 save 路径下,文件夹的命名根据机器的 hostname,时间戳生成。

nlp 文本处理开源工具,及聊天机器人实现

提供服务

在 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

scripts/start_serving.sh 启动服务

对模型的评价

目前代码具有很高的维护性,这也是从 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

3. DeepQA Project

4. Efficient Estimation of Word Representations in Vector Space

5. jieba 分词分析

6. Tensorflow and deep learning – without a PhD by Martin Görner

7. Pragmatic NLP by Matt Fortier

正文完
 0
评论(没有评论)