前言
从规则模板到统计方法,再到机器学习方法,最后到深度学习算法,一起回顾NLP之意图识别的历程。
作用
1、在搜索中会用到意图
比如在baidu中搜索“怎么做龙虾馅饺子”,意图是“做饺子”,而不是“做龙虾”,搜索时以饺子为核心。
2、在问答系统中会用到意图
比如用户问“我要买从深圳到上海的机票”,意图是“买机票”,然后再在“买机票”这个领域继续去做语义识别。
进化史
一、规则模板方法
通过专家手工编写规则模板来识别意图。
比如:
买 .* 《地名》 .* 《地名》.* 机票 =》 买机票
模板构成: 字符串、词性、正则表达式
通过匹配上述模板,即可识别出对应的意图
- 缺点:
1、人工编写工作量大,易冲突
2、规则模板覆盖面较小,使用通配符可以解决一部分问题,但带来了匹配优先级的问题
3、适用于垂直领域,在通用领域则无法推广
二、基于统计的方法
使用意图词典做词频统计,取词频最大的就是对应的意图
- 缺点
1、覆盖面比规则模板广,但容易误识别
三、基于语法的方法
先对句子做语法分析,找到中心动词及名词,再根据意图词典即可识别出意图来。
如:
我要买从深圳到上海的机票
1、语法分析结果(调用哈工大的ltp:http://ltp.ai/demo.html):
2、再根据意图词典即可识别出“买机票”意图
- 缺点:
1、使用语法分析使得准确度更高了,但增加了语法识别的难点,日常口语的语法识别不是那么高,比如: - 我要买个去从深圳到上海的机票 语法分析结果:
- 显然不是我们需要的
四、基于机器学习的方法
- 核心步骤
- 1、数据标注
如:
我要买个去从深圳到上海的机票 => 买机票
我要买从深圳到上海的机票 => 买机票 - 2、数据预处理
1)对数据进行分词,推荐使用jieba分词工具
2)去停用词,如:“的”、“个”。。。
3)增加同义词词条,如:“机票”=“飞机票”、“买”=“购买”。。。 - 3、训练集拆分
通常取90%作为训练数据,10%作为测试数据 - 4、特征提取
用卡方检验提取每个词的特征,从而得到每一个词与当前意图类别的相关程度
核心代码(python3):
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
'''
输入语料格式:
我要买去从深圳到上海的机票 0
我要买从深圳到上海的机票 0
我要去上海旅游 1
上海是个旅游的地方,我准备去 1
'''
#数据分词及去停用词之后,得到如下(padding后的结果):
data = [
['要', '买', '去', '从', '深圳', '到', '上海', '机票'],
['要', '买', '从', '深圳', '到', '上海', '机票', ''],
['要', '去', '上海', '旅游', '', '', '', ''],
['上海', '是', '旅游', '地方', '准备', '去', '', '']
]
#生成word2index(过程略)
word2index = {'要':1, '买':2, '去':3, '从':4, '深圳':5, '到':6, '上海':7, '机票':8, '旅游':9, '是':10, '地方':11, '准备':12, '':0}
#word转为index表示
data = [
[1, 2, 3, 4, 5, 6, 7, 8],
[1, 2, 4, 5, 6, 7, 8, 0],
[1, 3, 7, 9, 0, 0, 0, 0],
[7, 10, 9, 11, 12, 3, 0, 0]
]
lable_list = [0 , 0, 1, 1]
#使用卡方检验来选择特征
model = SelectKBest(chi2, k=5)#选择5个最佳特征
featrue = model.fit_transform(data, lable_list)
print(featrue)#最佳特征
print(model.scores_)
print(model.pvalues_)
- 运行输出结果:
[[ 2 4 6 7 8]
[ 2 5 7 8 0]
[ 3 9 0 0 0]
[10 11 3 0 0]]
[ 3.6 4.76470588 3.52173913 4.17241379 0.04347826 6.25 15. 8. ]
[5.77795711e-02 2.90490222e-02 6.05688602e-02 4.10872245e-02 8.34827329e-01 1.24193307e-02 1.07511177e-04 4.67773498e-03]
- 5、特征向量化
在上述代码中一共有12个词,故特征维度设置为12.
对应的特征转向量示例:
featur_array = [ 2 4 6 7 8]
=》
featur_vector = [0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0]
说明:featur_array中对应的数值n就是表示featur_vector[n-1]为1,其他的值为0 - 6 使用支持向量机svm训练模型
核心代码:
#####################svm
import sys
from sklearn import svm
#通过步骤5转换得到的特征向量
featur_vector = [
[0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0]
]
# SVM分类
clf = svm.SVC(C=2.0, probability=True)
clf.fit(featur_vector, lable_list)
print('Test Accuracy is: %.2f' % clf.score(featur_vector, lable_list))
可以看到输出结果是:Test Accuracy is: 1.00
- 特别说明:
在步骤4中,可以加一些人工特征,比如把地点都使用词性ns表示,同义词使用相同的index表示等
五、基于深度学习方法
- 核心思想
把意图识别看成是文本分类任务。 - 核心步骤
- 1、预料标注
同上 - 2、分词
同上 - 3、搭建模型
- 使用 word2vec + TextCNN 搭建网络
可以参考这篇文章实现:https://github.com/norybaby/sentiment_analysis_textcnn - 使用Bert + ABSA 搭建网络
可以参考这篇文章实现:https://github.com/songyouwei/ABSA-PyTorch - 使用XLNet + TextCNN 搭建网络
待研究
- 优点:
1、数据标注比较容易
2、在有充足的数据下,模型的准确率最高,无需人工特征