结巴中文分词原理分析4
结果分析:首先默认模式就是精确模式,即cut_all=False。这里很好的将“白宁超”划分为一个词。与全模式分词是有区别的。精确模式适合文本分析。
(3)默认精确模式分词
>>> seg_list = jieba.cut(
"他来到了网易杭研大厦"
) # 默认是精确模式
>>> print(
"【新词发现】\t"
+
", "
.
join
(seg_list))
【新词发现】 他, 来到, 了, 网易, 杭研, 大厦
结果分析: 此处杭研并没有在词典中,但是也被Viterbi算法识别出来了。实际上是基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法可以发现新词。也可以在自定义字典去收集新词。
(4)搜索引擎模式分词
>>> seg_list = jieba.cut_for_search(
"小明硕士毕业于中国科学院计算所,后在日本京都大学深造"
) # 搜索引擎模式
>>> print(
"搜索引擎模式:\t"
+
", "
.
join
(seg_list))
搜索引擎模式:小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, ,, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造
结果分析:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
(5)繁体分词
>>> str=
''
'此開卷第一回也.作者自云:因曾歷過一番夢幻之后,故將真事隱去,
而借
"通靈"
之說,撰此《石頭記》一書也.故曰
"甄士隱"
云云.但書中所記
何事何人?自又云:“今風塵碌碌,一事無成,忽念及當日所有之女子,一
一細考較去,覺其行止見識,皆出于我之上.何我堂堂須眉,誠不若彼裙釵
哉?實愧則有余,悔又無益之大無可如何之日也!
''
'
>>> str=jieba.cut(str)
>>> print(
'/ '
.
join
(str))
此開卷/ 第一回/ 也/ ./ 作者/ 自云/ :/ 因曾/ 歷過/ 一番/ 夢/ 幻之后/ ,/ 故將/ 真事/ 隱去/ ,/
/ 而/ 借/
"/ 通靈/ "
/ 之/ 說/ ,/ 撰此/ 《/ 石頭記/ 》/ 一書/ 也/ ./ 故/ 曰/
"/ 甄士/ 隱/ "
/ 云云/ ./ 但書中/ 所記/
/ 何事何/ 人/ ?/ 自又云/ :/ “/ 今風/ 塵碌碌/ ,/ 一事/ 無成/ ,/ 忽念及/ 當日/ 所/ 有/ 之/ 女子/ ,/ 一/
/ 一細/ 考較/ 去/ ,/ 覺其/ 行止/ 見識/ ,/ 皆/ 出于/ 我/ 之/ 上/ ./ 何/ 我堂/ 堂須/ 眉/ ,/ 誠不若/ 彼/ 裙釵/
/ 哉/ ?/ 實愧則/ 有/ 余/ ,/ 悔/ 又/ 無益/ 之/ 大/ 無/ 可/ 如何/ 之/ 日/ 也/ !
>>>
(6) jieba.lcut 全模式、精准模式、搜索引擎模式
>>> seg_list=jieba.lcut(str,cut_all=True,HMM=True)
>>> type(seg_list)
<
class
'list'
>
>>> seg_list
[
'我'
,
'是'
,
'白'
,
'宁'
,
'超'
,
'来自'
,
'博客'
,
'博客园'
]
>>> print(
"Full Mode: "
+
"/ "
.
join
(seg_list)) # 全模式隐马
Full Mode: 我/ 是/ 白/ 宁/ 超/ 来自/ 博客/ 博客园
>>> type(
"/ "
.
join
(seg_list))
<
class
'str'
>
结果分析:显然调用jieba.lcut返回list类型,”/ “.join(seg_list)是将list转化为string类型。
(7)自定义分词器
#encoding=utf-8
from
__future__ import print_function, unicode_literals
import sys
sys.path.append(
"../"
)
import jieba
jieba.load_userdict(
"userdict.txt"
)
import jieba.posseg
as
pseg
jieba.add_word(
'凱特琳'
)
jieba.del_word(
'自定义词'
)
test_sent = (
"李小福和李铁军是创新办主任也是云计算方面的专家; 什么是八一双鹿\n"
"例如我输入一个带“韩玉赏鉴”的标题,在自定义词库中也增加了此词为N类\n"
"「台中」正確應該不會被切開。mac上可分出「石墨烯」;此時又可以分出來凱特琳了。"
)
words = jieba.cut(test_sent)
print(
'/'
.
join
(words))
print(
"="
*40)
result = pseg.cut(test_sent)
for
w
in
result:
print(w.word,
"/"
, w.flag,
", "
, end=
' '
)
print(
"\n"
+
"="
*40)
terms = jieba.cut(
'easy_install is great'
)
print(
'/'
.
join
(terms))
terms = jieba.cut(
'python 的正则表达式是好用的'
)
print(
'/'
.
join
(terms))
print(
"="
*40)
# test frequency tune
testlist = [
(
'今天天气不错'
, (
'今天'
,
'天气'
)),
(
'如果放到post中将出错。'
, (
'中'
,
'将'
)),
(
'我们中出了一个叛徒'
, (
'中'
,
'出'
)),
]
for
sent, seg
in
testlist:
print(
'/'
.
join
(jieba.cut(sent, HMM=False)))
word =
''
.
join
(seg)
print(
'%s Before: %s, After: %s'
% (word, jieba.get_FREQ(word), jieba.suggest_freq(seg, True)))
print(
'/'
.
join
(jieba.cut(sent, HMM=False)))
print(
"-"
*40
结果分析:
首先对一段话分词处理:
test_sent = (
"李小福和李铁军是创新办主任也是云计算方面的专家; 什么是八一双鹿\n"
"例如我输入一个带“韩玉赏鉴”的标题,在自定义词库中也增加了此词为N类\n"
"「台中」正確應該不會被切開。mac上可分出「石墨烯」;此時又可以分出來凱特琳了。"
)
words = jieba.cut(test_sent)
print(
'/'
.
join
(words))
李小福/和/李铁/军是/创新办/主任/也/是/云计算/方面/的/专家/;/ /什么/是/八一双鹿/
/例如/我/输入/一个/带/“/韩玉赏鉴/”/的/标题/,/在/自定义词/库中/也/增加/了/此/词为/N/类/
/「/台中/」/正確/應該/不會/被/切開/。/mac/上/可/分出/「/石墨/烯/」/;/此時/又/可以/分出/來/凱特琳/了/
此处“李小福“和“李铁军”都是人名,结果却分词“李小福”和“李铁”,而“军是”当做一个词处理,显然不对。我们可以将“李铁军”当着一个词加入自定义文本中:
import sys
sys.path.append(
"../"
)
import jieba
jieba.load_userdict(
"userdict.txt"
)
jieba.add_word(
'李铁军'
)
test_sent = (
"李小福和李铁军是创新办主任也是云计算方面的专家; 什么是八一双鹿\n"
"例如我输入一个带“韩玉赏鉴”的标题,在自定义词库中也增加了此词为N类\n"
"「台中」正確應該不會被切開。mac上可分出「石墨烯」;此時又可以分出來凱特琳了。"
)
words = jieba.cut(test_sent)
print(
'/'
.
join
(words))
李小福/和/李铁军/是/创新办/主任/也/是/云计算/方面/的/专家/;/ /什么/是/八一双鹿/
/例如/我/输入/一个/带/“/韩玉赏鉴/”/的/标题/,/在/自定义词/库中/也/增加/了/此/词为/N/类/
/「/台中/」/正確/應該/不會/被/切開/。/mac/上/可/分出/「/石墨/烯/」/;/此時/又/可以/分出/來/凱特琳/了/。
结果显然经过自定义分词有所好转。而石墨/烯分词错误。
李小福/和/李铁军/是/创新办/主任/也/是/云计算/方面/的/专家/;/ /什么/是/八一双鹿/
/例如/我/输入/一个/带/“/韩玉赏鉴/”/的/标题/,/在/自定义词/库中/也/增加/了/此/词为/N/类/
/「/台中/」/正確/應該/不會/被/切開/。/mac/上/可/分出/「/石墨烯/」/;/此時/又/可以/分出/來/凱特琳/了/。
(8) 词性标注
print(
"="
*40)
result = pseg.cut(test_sent)
for
w
in
result:
print(w.word,
"/"
, w.flag,
", "
, end=
' '
)
print(
"\n"
+
"="
*40)
terms = jieba.cut(
'easy_install is great'
)
print(
'/'
.
join
(terms))
terms = jieba.cut(
'python 的正则表达式是好用的'
)
print(
'/'
.
join
(terms))
print(
"="
*40)
# 结果
========================================
李小福 / nr , 和 / c , 李铁军 / x , 是 / v , 创新办 / i , 主任 / b , 也 / d , 是 / v , 云计算 / x , 方面 / n , 的 / uj , 专家 / n , ; / x , / x , 什么 / r , 是 / v , 八一双鹿 / nz ,
/ x , 例如 / v , 我 / r , 输入 / v , 一个 / m , 带 / v , “ / x , 韩玉赏鉴 / nz , ” / x , 的 / uj , 标题 / n , , / x , 在 / p , 自定义词 / n , 库中 / nrt , 也 / d , 增加 / v , 了 / ul , 此 / r , 词 / n , 为 / p , N / eng , 类 / q ,
/ x , 「 / x , 台中 / s , 」 / x , 正確 / ad , 應該 / v , 不 / d , 會 / v , 被 / p , 切開 / ad , 。/ x , mac / eng , 上 / f , 可 / v , 分出 / v , 「 / x , 石墨烯 / x , 」 / x , ;/ x , 此時 / c , 又 / d , 可以 / c , 分出 / v , 來 / zg , 凱特琳 / x , 了 / ul , 。/ x ,
========================================
easy_install/ /is/ /great
python/ /的/正则表达式/是/好用/的
========================================
结果分析:李小福 / nr , 李铁军 / x 都是名字,属于名词,而李铁军 / x显然词性不对,这是由于刚刚jieba.add_word(‘李铁军’)时候,没有进行词性参数输入,我们看看jieba.add_word(‘李铁军’)源码:
def add_word(self, word, freq=None, tag=None)
jieba.add_word('李铁军',tag='nr')修改后结果
运行结果:
========================================
李小福 / nr , 和 / c , 李铁军 / nr , 是 / v , 创新办 / i , 主任 / b , 也 / d , 是 / v , 云计算 / x , 方面 / n , 的 / uj , 专家 / n , ; / x , / x , 什么 / r , 是 / v , 八一双鹿 / nz ,
/ x , 例如 / v , 我 / r , 输入 / v , 一个 / m , 带 / v , “ / x , 韩玉赏鉴 / nz , ” / x , 的 / uj , 标题 / n , , / x , 在 / p , 自定义词 / n , 库中 / nrt , 也 / d , 增加 / v , 了 / ul , 此 / r , 词 / n , 为 / p , N / eng , 类 / q ,
/ x , 「 / x , 台中 / s , 」 / x , 正確 / ad , 應該 / v , 不 / d , 會 / v , 被 / p , 切開 / ad , 。/ x , mac / eng , 上 / f , 可 / v , 分出 / v , 「 / x , 石墨烯 / x , 」 / x , ;/ x , 此時 / c , 又 / d , 可以 / c , 分出 / v , 來 / zg , 凱特琳 / x , 了 / ul , 。/ x ,
========================================
(9) 自定义调整词典
# test frequency tune
testlist = [
(
'今天天气不错'
, (
'今天'
,
'天气'
)),
(
'如果放到post中将出错。'
, (
'中'
,
'将'
)),
(
'我们中出了一个叛徒'
, (
'一'
,
'个'
)),
]
for
sent, seg
in
testlist:
print(
'/'
.
join
(jieba.cut(sent, HMM=False)))
word =
''
.
join
(seg)
print(
'%s Before: %s, After: %s'
% (word, jieba.get_FREQ(word), jieba.suggest_freq(seg, True)))
print(
'/'
.
join
(jieba.cut(sent, HMM=False)))
print(
"-"
*40)
结果:
========================================
今天天气/不错
今天天气 Before: 3, After: 0
今天天气/不错
----------------------------------------
如果/放到/post/中将/出错/。
中将 Before: 763, After: 494
如果/放到/post/中/将/出错/。
----------------------------------------
我们/中/出/了/一个/叛徒
一个 Before: 142747, After: 454
我们/中/出/了/一/个/叛徒
----------------------------------------
结果分析:列表中的每一条数据如(‘今天天气不错’, (‘今天’, ‘天气’)),其中(‘今天’, ‘天气’)调整分词颗粒精度的。如第三句正常分词:我们/中/出/了/一个/叛徒。我们假设某些情况下一和个分别分词,可以做如上处理。
-
使用 add_word(word, freq=None, tag=None) 和 del_word(word) 可在程序中动态修改词典。
-
使用 suggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。
注意:自动计算的词频在使用 HMM 新词发现功能时可能无效。
(10) 自定义调节词典解决歧义分词问题
>>> import jieba
>>> print(
'/'
.
join
(jieba.cut(
'如果放到post中将出错。'
, HMM=False)))
Building prefix dict
from
the
default
dictionary ...
Loading model
from
cache C:\Users\cuitbnc\AppData\Local\Temp\jieba.cache
Loading model cost 1.069 seconds.
Prefix dict has been built succesfully.
如果/放到/post/中将/出错/。
>>> jieba.suggest_freq((
'中'
,
'将'
), True)
494
>>> print(
'/'
.
join
(jieba.cut(
'如果放到post中将出错。'
, HMM=False)))
如果/放到/post/中/将/出错/。
>>> print(
'/'
.
join
(jieba.cut(
'「台中」正确应该不会被切开'
, HMM=False)))
「/台/中/」/正确/应该/不会/被/切开
>>> jieba.suggest_freq(
'台中'
, True)
69
>>> print(
'/'
.
join
(jieba.cut(
'「台中」正确应该不会被切开'
, HMM=False)))
「/台中/」/正确/应该/不会/被/切开
>>
总结:jieba.cut 方法接受三个输入参数: 需要分词的字符串;cut_all 参数用来控制是否采用全模式;HMM 参数用来控制是否使用 HMM 模型。jieba.cut 以及 jieba.cut_for_search 返回的结构都是一个可迭代的 generator,可以使用 for 循环来获得分词后得到的每一个词语(unicode)。