如何进行意图分析
之前开始做语义理解的时候,笔者采用的是比较粗暴的方法进行匹配。随着语料的积累,语料库的规模变得越来越大,匹配的效率也随着越来越低,对语料进行意图分类的想法也就随着产生。
当用户输入之后,系统首先对输入进行意图分类,然后对分类下的语料进行匹配,从而减轻计算量,提高系统的匹配效率。
本文只是简单的阐述一下意图分析的典型思路和方法,并实现一个基本的意图分类器,而无意系统的探究意图分类。更详细的探讨后文再进行。
本文按照如下流程进行叙述:
假设有3个场景:吃饭、打招呼、再见。那么三个场景下会有什么样的对话呢? 比如:
很明显,人眼一看就能看出对应的句子应该是哪个类别了:
到这里,我们模型需要的数据就有了。可以很清晰的写出下面的代码:
list_sen=['今天这个菜真好吃!','嗨!今天天气不错!','今天很开心,明天见!']
需要的数据就有了,下一步是提取特征。
特征的提取是为了方便进行分类计算,每一个特征都具备一定的权重,表明它的权值。通过特征的权值,就能够确定句子属于哪一个类别。这里我们将每一个字作为一个特征,1/(字出现的总次数)作为权值。 首先构造一个字典,key为字,value为频率:
dict_voc=dict()
for s in list_sen:
for w in s:
if w in dict_voc.keys():
dict_voc[w]+=1
else:
dict_voc[w]=1
输出为:
{'这': 1.0, '嗨': 1.0, '好': 1.0, '气': 1.0, '真': 1.0, '错': 1.0, '不': 1.0, '个': 1.0, '心': 1.0, '天': 0.2, '菜': 1.0, '今': 0.3333333333333333, ',': 1.0, '!': 0.25, '吃': 1.0, '明': 1.0, '见': 1.0, '很': 1.0, '开': 1.0}
到这里字典构造完毕,下一步就是构造类别的特征了。 前面说了,我们把每一个类别下的每一个字作为特征,代码也就可以写出来了。
features_one=dict()#吃饭 {字:频率}
features_two=dict()#打招呼
features_three=dict()#再见
for w in list_sen[0]:
if w in features_one.keys():
features_one[w]+=1
else:
features_one[w]=1
for w in list_sen[1]:
if w in features_two.keys():
features_two[w]+=1
else:
features_two[w]=1
for w in list_sen[2]:
if w in features_three.keys():
features_three[w]+=1
else:
features_three[w]=1
print(features_one)
print(features_two)
print(features_three)
#{'好': 1, '天': 1, '真': 1, '吃': 1, '!': 1, '菜': 1, '今': 1, '个': 1, '这': 1}
#{'不': 1, '!': 2, '气': 1, '嗨': 1, '错': 1, '今': 1, '天': 2}
#{'明': 1, '心': 1, '开': 1, '见': 1, ',': 1, '很': 1, '今': 1, '天': 2, '!': 1}
到这里特征的提取已经完成
模型准备需要的是建立分类模型。这里我们通过给每一个特征赋予一个得分,然后将句子中每一个字的特征得分进行相加,然后就可以得到句子在某一个类别下特征的总得分,从而能够对句子进行分类。
比方说:今天的工作就到这里吧,大家早点回去,明天再继续吧。 这句话在每一个类别下的得分为:
特征命中:今、天、这、天
类别:吃饭
得分:4
特征命中:今、天、天
类别:打招呼
得分:3
特征命中:今、天、明、天、,、,
类别:再见
得分:6
这里,我们假设每一个字的权重为1,。显然,得分6最高,所属的类别应该是:再见。 到这里,我们所需要的模型就已经建立起来了。
上一节有一个问题,比如今天在所有的类别都出现了,拜拜只出现在了再见类别,菜也只出现在了吃饭类别。这是不是意味这每一个特征应该具备不同的权重呢?或者说有些字的辨识度应该更高,有些字的辨识度应该更低呢?
是的,我们在这里通过1/(字出现的总次数)来对字的特征得分进行加权。
特征命中:今(0.3)、天(0.2)、这(1)、天(0.2)
类别:吃饭
得分:1.73
特征命中:今(0.3)、天(0.2)、天(0.2)
类别:打招呼
得分:1.13
特征命中:今(0.3)、天(0.2)、明(1.0)、天(0.2)、,(1.0)、,(1.0)
类别:再见
得分:4.13
结果还是属于类别再见。
有了前面的叙述,可以很方便的进行编码实现:
sen='今天的工作就到这里吧,大家早点回去,明天再继续吧。'
score1=0.0
score2=0.0
score3=0.0
print('class1:')
for w in sen:
if w in features_one:
print('word:',w,features_one[w],dict_voc[w])
score1+=features_one[w]*dict_voc[w]
print('score1:',score1)
print('---------------------')
print('class2:')
for w in sen:
if w in features_two:
print('word', w,features_two[w],dict_voc[w])
score2+=features_two[w]*dict_voc[w]
print('score2:',score2)
print('---------------------')
print('class3:')
for w in sen:
if w in features_three:
print('word', w,features_three[w],dict_voc[w])
score3+=features_three[w]*dict_voc[w]
print('score3:',score3)
print('---------------------')
输出如下:
class1:
word: 今 1 0.3333333333333333
word: 天 1 0.2
word: 这 1 1.0
word: 天 1 0.2
score1: 1.7333333333333332
---------------------
class2:
word 今 1 0.3333333333333333
word 天 2 0.2
word 天 2 0.2
score2: 1.1333333333333333
---------------------
class3:
word 今 1 0.3333333333333333
word 天 2 0.2
word , 1 1.0
word , 1 1.0
word 明 1 1.0
word 天 2 0.2
score3: 4.133333333333334
---------------------
以上就完成了意图分类模型的建立。本文只是对意图分类进行了简单的探讨,实际上的意图分类并不是这么简单,当然,这就是后话了。