分词模型通常有三种: 基于词典的匹配(trie树,最大匹配法),HMM,CRF
查字典的办法最早被提出,就是:把句子从左向右扫描一遍,遇到词典(
trie树形式存储)里有的词就标识出来,遇到复合词就找最长的词匹配,遇到不认识的词就分割成单字词。
下面使用的是python结巴分词:
结巴分词:
https://github.com/zhangweijiqn/jieba (分词模型HMM)
README.md中很详细:
结巴分词中的实例程序已经展示了比较全的功能:
https://github.com/fxsjy/jieba/blob/master/test/demo.py
导入自定义词典(sougou):
结巴分词自己带的词库并不好用,需要我们自己导入词典。下面的方法用来导入搜狗词典:
(1)进入搜狗官网:
http://pinyin.sogou.com/dict/
下载标准词典(
http://pinyin.sogou.com/dict/detail/index/11640 ),下载后文件名为"搜狗标准词库.scel"。
(2)将scel格式文件转为txt格式
执行如下命令:
python getSougouCiDian.py ~/下载/搜狗标准词库.scel sougou.txt
转换后的文件保存在sougou.txt文件中,该文件中存储格式如下:
啊啊啊 1
x:1
阿埃二氏病变 1
x:1
阿埃二氏手术 1
x:1
(3)从txt文件中导出结巴分词格式的文件。
结巴分词要求的格式(在readme.md文件中搜索“词典”,找到“
添加自定义词典”)为:
创新办 3 i云计算 5凱特琳 nz台中
词典格式和
dict.txt
一样,一个词占一行;每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。
转换只需执行一下linux命令:
awk 'FNR%2==1{print $1}' sougou.txt > dict.list
至此就可以得到dict.list的词库(需要注意的是如果是多个词典合并的,可能没有去重)。
(4)向结巴中添加字典:
用法: jieba.load_userdict(file_name) # file_name 为文件类对象或自定义词典的路径。
只需执行如下代码即可:
jieba.load_userdict(
"dict.list"
)
分词的效果和词典有很大关系:
#测试自定义词典
jieba.load_userdict(
"dict.txt"
)
#字典中同时含有 病毒,性,感冒,病毒性感冒 四个词
seg_list = jieba.cut(
"病毒性感冒"
, cut_all=False)
print
(
"Default Mode: "
+
"/ "
.join(seg_list))
# Default Mode: 病毒性感冒
#在default mode下,进行的是最大匹配
分词词性标记:
汉语文本词性标注标记集参考:
http://fhqllt.iteye.com/blog/947917
-------------------------------------------------------------------------------
a: 形容词
b: 区别词
c: 连词
d: 副词
e: 叹词
g: 语素字
h: 前接成分
i: 习用语
j: 简称
k: 后接成分
m: 数词
n: 普通名词
nd: 方位名词
nh: 人名
ni: 机构名
nl: 处所名词
ns: 地名
nt: 时间词
nz: 其他专名
o: 拟声词
p: 介词
q: 量词
r: 代词
u: 助词
v: 动词
wp: 标点符号
ws: 字符串
x: 非语素字
结巴分词原理
基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG)
采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法
基于词典的匹配
“大学生活动中心落成了”
最大长度匹配(jieba默认模式)
{大学生,活动中心,落成,了}
所有切分(全模式)
{大,大学,大学生,生活,活动,中,中心,心}
存储格式 Trie树
Trie树 (前缀树,字典树)
基本思想(以字母树为例):
1、插入过程对于一个单词,从根开始,沿着单词的各个字母所对应的树中的节点分支向下走,直到单词遍历完,将最后的节点标记为红色,表示该单词已插入Trie树。
2、查询过程同样的,从根开始按照单词的字母顺序向下遍历trie树,一旦发现某个节点标记不存在或者单词遍历完成而最后的节点未标记为红色,则表示该单词不存在,若最后的节点标记为红色,表示该单词存在。
Trie树特性:
1)根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3)每个节点的所有子节点包含的字符都不相同。
4)如果字符的种数为n,则每个结点的出度为n,这也是空间换时间的体现,浪费了很多的空间。5)插入查找的复杂度为O(n),n为字符串长度。
给出字符串"abc","ab","bd","dda",根据该字符串序列构建一棵Trie树。
DAG切分词图
为了消除分词中的歧异,提高切分准确度,需要找出一句话所有可能的词,生成全切分词图。
在"有意见分歧"的切分词图中:"有"这条边的起点是0,终点是1;"有意"这条边的起点是0,终点是2,以此类推。切分方案就是从源点0到终点5之间的路径,共存在两条切分路径。
路径1:0-1-3-5 对应切分方案S1:有/ 意见/ 分歧/
路径2:0-2-3-5 对应切分方案S2:有意/ 见/ 分歧/
动态规划查找最大概率路径
字典在生成trie树的同时, 也把每个词的出现次数转换为了频率. 关于频率和概率,动态规划中, 先查找待分词句子中已经切分好的词语, 对该词语查找该词语出现的频率(次数/总数),如果没有该词, 就把词典中出现频率最小的那个词语的频率作为该词的频率。
最大匹配法
正向最大长度匹配
每次从词典中找和待匹配串前缀最长匹配的词,如果找到该匹配词,则把这个词作为切分词,待匹配串减去该词,如果词典中没有词匹配上,则按单字切分。
“大学生/活动/中心”
逆向长度最大匹配
从输入串的最后一个字往前匹配词典使用的是后缀树(suffix tree),最后一个字符放在第一层(倒挂)。
HMM-处理未登录字符串