更多代码阅读及测试(分词)

2021SC@SDUSC


目录

1,测试精确分词

2,测试全模式分词

3,不使用HMM模型测试

4,使用paddle模式的分词测试

5,cut_for_search()测试

6,自定义分词器



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))

加载结果:

 这样就加载成功了!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值