2021SC@SDUSC
目录
1,测试精确分词
#encoding=utf-8
import sys
sys.path.append("../")
import jieba
def cuttest(test_sent):
result = jieba.cut(test_sent)
print(" / ".join(result))
if __name__ == "__main__":
cuttest("隐马尔可夫")
cuttest("“Microsoft”一词由“MICROcomputer(微型计算机)”和“SOFTware(软件)”两部分组成")
cuttest("PS: 我觉得开源有一个好处,就是能够敦促自己不断改进,避免敞帚自珍")
cuttest("湖北省石首市")
cuttest("做好了这件事情就一了百了了")
cuttest("孙君意")
cuttest("你好人们审美的观点是不同的")
cuttest("买水果然后来世博园")
cuttest("买水果然后去世博园")
cuttest("的的的的的在的的的的就以和和和")
cuttest("他说的确实在理")
cuttest("长春市长春节讲话")
cuttest('C++和c#是什么关系?11+122=133,是吗?PI=3.14159')
cuttest('看上去iphone8手机样式很赞,售价699美元,销量涨了5%么?')
jieba.del_word('很赞')
cuttest('看上去iphone8手机样式很赞,售价699美元,销量涨了5%么?')
运行结果:
不难看出这些句子都被分成了一些有意义的词组。即使他们有些有歧义,也可以通过增加/删除词典词组来修正最后的结果,例如最后一句,通过删除词典中的“很赞”,导致最后的结果中“很赞”无法再组成一个词组,所以只能被迫拆分成两个词“很”+“赞”
2,测试全模式分词
只需要修改上面代码的cuttest(),参数cut_all设置为True即可
def cuttest(test_sent):
result = jieba.cut(test_sent,cut_all=True)
print(" / ".join(result))
运行结果:
全模式可以将所有可以组成有意义词组的词组列出来,如上图所示
3,不使用HMM模型测试
只需要修改上面代码的cuttest(),参数HMM设置为False即可
def cuttest(test_sent):
result = jieba.cut(test_sent,HMM = False)
print(" / ".join(result))v
运行结果:
可以看出,不使用HMM新词发现,有些词(特殊的名字、特殊含义的成语等)被切分开了;例如敝帚自珍的切分,使用HMM模型可以切分为敝帚/自珍,不使用则切分为敝/帚/自珍;还有孙君意,不使用HMM模型将人名拆分为了三个离散的字。
以下列出测试过程中使用/不使用HMM模型出现结果差异的例子:
结果分为上下两行,第一行使用HMM模型,后者不使用,可以看到一些词不使用HMM模型会被切分为单个字,特别是名字。
4,使用paddle模式的分词测试
我也没太理解paddle深度学习模型可以给cut带来什么,希望读者自行研读paddle源码和GNU相关文档,在这里我只列出一些测试结果(use_paddle=True和use_paddle=False的差异)
首行为True,次行为False
测试范例74条,产生差异31条。其中有些表现良好,有些表现比较差。
5,cut_for_search()测试
cut_for_search(sentence,HMM=True)
与cut()方法相比,cut_for_search()方法只接受两个参数,待分词字符串和是否使用HMM模型,cut()方法接受四个参数:待分词字符串、HMM=True、cut_all=False和use_paddle=False。
cut_for_search()方法可以将待分词字符串切割成便于搜索引擎搜索的词组,测试范例:
def cuttest(test_sent):
result = jieba.cut(test_sent)
# print(" / ".join(result))
return " / ".join(result)
def cuttest_opposite(test_sent):
result = jieba.cut_for_search(test_sent)
# print(" / ".join(result))
return " / ".join(result)
def contrast(test_sent):
test1 = ""
test1 = cuttest(test_sent)
test2 = " "
test2 = cuttest_opposite(test_sent)
if test1!=test2:
print(test1)
print(test2)
运行结果:
可以看到,cut_for_search()方法是对cut()后的结果超过2个字符长度的再次进行分词(并且保留原词),看上去很像cut_all是不是,我们再添加cut_all做对比。
以上为部分结果。
可以看到,第二行cut_for_search()和第三行cut(cut_all =True)的区别。cut_for_search()是对精准分词后的结果长度超过三个的结果再次进行分词,而cut_all模式则是对整个句子进行切分,整合出所有能成词的结果,作为一个可迭代对象返回。
从新词发现角度来讲,cut_all模式就没有新词发现功能,如下例:
它可以识别张三丰却无法识别张三风,其余两种模式均可识别。
接下来我们看它们的源码:
def cut(self, sentence, cut_all=False, HMM=True, use_paddle=False):
"""
The main function that segments an entire sentence that contains
Chinese characters into separated words.
Parameter:
- sentence: The str(unicode) to be segmented.
- cut_all: Model type. True for full pattern, False for accurate pattern.
- HMM: Whether to use the Hidden Markov Model.
"""
is_paddle_installed = check_paddle_install['is_paddle_installed']
sentence = strdecode(sentence)
if use_paddle and is_paddle_installed:
# if sentence is null, it will raise core exception in paddle.
if sentence is None or len(sentence) == 0:
return
import jieba.lac_small.predict as predict
results = predict.get_sent(sentence)
for sent in results:
if sent is None:
continue
yield sent
return
re_han = re_han_default
re_skip = re_skip_default
if cut_all:
cut_block = self.__cut_all
elif HMM:
cut_block = self.__cut_DAG
else:
cut_block = self.__cut_DAG_NO_HMM
blocks = re_han.split(sentence)
for blk in blocks:
if not blk:
continue
if re_han.match(blk):
for word in cut_block(blk):
yield word
else:
tmp = re_skip.split(blk)
for x in tmp:
if re_skip.match(x):
yield x
elif not cut_all:
for xx in x:
yield xx
else:
yield x
可以看到,cut()首先判断use_paddle参数(如果paddle模块已经安装),如果它是True,那么使用paddle模式进行分词,否则考虑cut_all模式,HMM次之,最后不使用HMM的精确模式。
def cut_for_search(self, sentence, HMM=True):
"""
Finer segmentation for search engines.
"""
words = self.cut(sentence, HMM=HMM)
for w in words:
if len(w) > 2:
for i in xrange(len(w) - 1):
gram2 = w[i:i + 2]
if self.FREQ.get(gram2):
yield gram2
if len(w) > 3:
for i in xrange(len(w) - 2):
gram3 = w[i:i + 3]
if self.FREQ.get(gram3):
yield gram3
yield w
搜索引擎模式,首先调用cut()方法,得到切分后的结果,然后对length大于二和大于三的子结果进行遍历,检测是否有二字成词(对于长度大于二的结果)和三字成词(对于长度大于三的结果),如果有,先于结果加入迭代器返回。
6,自定义分词器
使用 jieba.Tokenizer(dictionary=DEFAULT_DICT) 返回自定义分词器。
默认示例:
自定义分词器:
import jieba
dt = jieba.Tokenizer(dictionary="../extra_dict/dict.txt.big")
def cuttest(test_sent):
result = dt.cut(test_sent,HMM=False)
print(" / ".join(result))
加载结果:
这样就加载成功了!