jieba
Python 中文分词库:
github: https://github.com/fxsjy/jieba
特点
- 支持三种分词模式:
– 精确模式,试图将句子最精确地切开,适合文本分析;
– 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
– 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
- 支持繁体分词
- 支持并行分词。基于 python 自带的 multiprocessing 模块,目前暂不支持 Windows;并行分词仅支持默认分词器。
- 支持自定义词典
- MIT 授权协议
算法
- 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)
- 基于 TF-IDF 算法的关键词抽取
- 基于 TextRank 算法的关键词抽取
- 对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法
- 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
jieba分词流程图
Trie 树
Trie 字典树/前缀树。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
典型应用是用于统计、排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
借图理解Trie树结构:
例如:词典中有“am”, “bad”,“be”,“so”,加入Trie树后节点情况如下(当然Trie树也可用中文节点)
建立 DAG 词图
Null
分词 DAG 代码实现
参考jieba源码
# -*- coding:utf-8 -*-
class Trie:
"""
Trie 字典树/前缀树
它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
典型应用是用于统计、排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
"""
def __init__(self):
self.root = {}
self.word_end = -1
def insert(self,word):
curNode = self.root
for c in word:
if not c in curNode:
curNode[c] = {}
curNode = curNode[c]
curNode[self.word_end] = True
def search(self, word):
curNode = self.root
for c in word:
if not c in curNode:
return False
curNode = curNode[c]
if self.word_end not in curNode:
return False
return True
def startsWith(self, prefix):
curNode = self.root
for c in prefix:
if not c in curNode:
return False
curNode = curNode[c]
return True
t = Trie()
t.insert("你好")
t.insert("世界")
t.insert("世界之窗")
t.insert("北京")
t.insert("北京大学")
t.insert("大学生")
t.insert("学生")
t.insert("活动")
t.insert("中心")
print (t.root)
def get_DAG(sentence):
DAG = {} #DAG空字典,用来构建DAG有向无环图
N = len(sentence) #赋值N词的长度
for k in range(N): #创建N词长度的列表,进行遍历
tmplist = [] #从字开始能在TrieNode中的匹配到的词末尾位置所在的list
i = k
frag = sentence[k] #取传入词中的值,例如k=0,frag=我
#print("Debug 0 frag= %s" % frag)
while i < N and t.startsWith(frag): #当传入的词,在Trie中时,就给tmplist赋值,构建字开始可能去往的所有的路径列表
#print("Debug: 1 frag = %s" % frag)
tmplist.append(i) #每个词,在Trie中查找,查到,则将下标传入templist中
i += 1 #例如查找“北”,后继续查找“我北京”是否也在语料库中,直到查不到推出循环
frag = sentence[k: i + 1] #截取传入值得词语,i=1,时截取 我,i=2时截取我们
if not tmplist: #当传入值,在语料库中查询不到时
tmplist.append(k)
DAG[k] = tmplist #赋值DAG 词典
return DAG
print (get_DAG("北京大学生活动中心"))
#print (get_DAG("你好,欢迎来到世界之窗"))
print (t.root)
print log:
> {0: [0, 1, 2, 3], 1: [1], 2: [2, 3, 4], 3: [3, 4], 4: [4], 5: [5, 6], 6: [6], 7: [7, 8], 8: [8]}
> {'北': {'京': {-1: True, '大': {'学': {-1: True}}}}, '大': {'学': {'生': {-1: True}}}, '学': {'生': {-1: True}}, '活': {'动': {-1: True}}, '中': {'心': {-1: True}}}
计算全局概率Route ,基于词频最大切分组合
Null
隐马尔可夫HMM 算法
与HMM模型相关的算法主要分三类,分别解决三种问题:
- 已知:隐含状态序列,转换概率,可见状态链
求解:隐含状态链
解法:Viterbi算法
应用:输入法 / 语音识别
- 已知:隐含状态序列,转换概率,可见状态链
求解:输出概率(发射概率)
解法:前/后向算法
应用:反欺诈
- 已知:可见状态链(观测状态序列)
求解:建立包括 转换概率 隐含状态序列 观测状态序列 输出概率 的模型
解法:Baum -Welch 算法 (ME无监督训练学习)
应用:~
jieba采用Viterbi算法动态规划得到分词和标注:
引用小白教程帮助理解Viterbi算法:
引用
本文所有引用及参考如下,感谢原作者的分享?