中文分词
今天想记录一下有关中文分词的部分。
分词粒度:粗粒度、细粒度
推荐场景:粗粒度
搜索场景:细粒度——召回
- 那么怎样理解中文分词呢
一段文字不仅在于字面上是什么,还在于怎么切分和理解
eg:
--李家面馆
--李家/面馆 李/家/面馆
和英文不同,中文词之家没有空格
如果没有中文分词会出现
--我们搜索“达内”,会出现“齐达内”相关的信息
- 因此必要的中文分词是必须的
0 有 1 意 2 见 3 分 4 歧 5
切开的开始位置对应1,否则对应0,来表示有/意见/分歧 的bit内容是:11010(1表示从此处切开,0表示到此处结束)
还可以用一个分词节点序列来表示切分方案,则序列为{0,1,3,5}
- 最常见的切分方案是基于词典匹配
--最大长度查找(前向、后向查找)
- 数据结构
– 为了提高查找效率,不要逐个匹配词典中的词
– 查找词典所占的时间可能占总的分词时间的1/3左右,为了保证切分速度,需要选择一个好 的查找词典方法
– Trie树常用于加速分词查找词典问题
例如:大学生活动中心
正向:大学生/活动/中心
反向:大学生/活动/中心
一般来说,应用反向比较合适,因为在一些场景中使用正向得到的分词和我们希望的并不一样。
- 接下来是DAG图
关于有向无环图(DAG)举一个例子:广州本田雅阁汽车
其中每一个字可以自己切分,在加上(广州,广州本田,本田,雅阁,本田雅阁,汽车)
形成这样的DAG:{0:【0,1,3】,1:【1】,2:【2,3,5】,3:【3】,4:【5】,5:【5】,6:【7】,7:【7】}
此时我们通过朴素贝叶斯公式来进行查找最大可能词序列的概率
例如:南京市长江大桥
--南京市/长江/大桥
--南京/市长/江大桥
• 这两种切分方法分别叫做S1和S2。计算条件概率P(S1|C)和P(S2|C),然后根据 P(S1|C)和P(S2|C)的值来决定选择S1还是S2。 • P(C)是字串在语料库中出现的概率。比如说语料库中有1万个句子,其中有一句 是 “南京市长江大桥”那么P(C)=P(“南京市长江大桥”)=万分之一。
• 因为P(C∩S) = P(S|C)*P(C) = P(C|S)*P(S),所以P(S|C) = P(C|S)*P(S)/P(C)
因为P(C)只是一个用来归一化的固定数值,可以忽略不计
另外:从词串恢复到汉字串的概率只有唯一的一种方式,所以P(C|S)=1
所以:比较P(S1|C)和P(S2|C)的大小变成比较P(S1)和P(S2) 的大小
P(S1|C)/P(S2|C)=P(S1)/P(S2)
因为P(S1)=P(南京市,长江,大桥)=P(南京市)*P(长江)*P(大桥) > P(S2)=P(南京,市 长,江大桥),所以选择切分方案S1
最后我们对得到的结果取log,目的:
1、取log后概率从乘法变为加法,
2、防止越界溢出
- 最后看一下模型
1、一元模型
对于不同的S,m的值是不一样的,一般来说m越大,P(S)会越小。也就是说, 分出的词越多,概率越小。
P(Wi)=Wi在语料库中的出现次数n/语料库中的总次数N
因此: logP(Wi)=log(FREQw)-logN 这个P(S)的计算公式也叫做基于一元模型的计算公式,它综合考虑了切分出的词 数和词频。
如果简化成一个词的出现仅依赖于它前面出现的一个词,那么就称为二元模型为(Bigram)
如果简化成一个词的出现仅依赖于它前面出现的两个词,就称之三元模型(Trigram)
如果一个词的出现不依赖于它前面出现的词,叫做一元模型(Unigram)
实践
分词工具我们选用的是jieba分词
源码下载的地址:https://github.com/fxsjy/jieba
支持三种分词模式
– 精确模式:将句子最精确的分开,适合文本分析
– 全模式:句子中所有可以成词的词语都扫描出来,速度快,不能解决歧义
– 搜索引擎模式:在精确模式基础上,对长词再次切分,提高召回
• 支持繁体分词
• 支持自定义字典
jieba分词的细节
最后用代码完成。