资讯专栏INFORMATION COLUMN

jieba分词学习笔记(二)

fxp / 2850人阅读

分词模式

jieba分词有多种模式可供选择。可选的模式包括:

全切分模式

精确模式

搜索引擎模式

同时也提供了HMM模型的开关。

其中全切分模式就是输出一个字串的所有分词,

精确模式是对句子的一个概率最佳分词,

而搜索引擎模式提供了精确模式的再分词,将长词再次拆分为短词。

效果大抵如下:

# encoding=utf-8
import jieba

seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式

seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精确模式

seg_list = jieba.cut("他来到了网易杭研大厦")  # 默认是精确模式
print(", ".join(seg_list))

seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造")  # 搜索引擎模式
print(", ".join(seg_list))

的结果为

【全模式】: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学

【精确模式】: 我/ 来到/ 北京/ 清华大学

【新词识别】:他, 来到, 了, 网易, 杭研, 大厦    (此处,“杭研”并没有在词典中,但是也被Viterbi算法识别出来了)

【搜索引擎模式】: 小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造

其中,新词识别即用HMM模型的Viterbi算法进行识别新词的结果。

值得详细研究的模式是精确模式,以及其用于识别新词的HMM模型和Viterbi算法。

jieba.cut()

在载入词典之后,jieba分词要进行分词操作,在代码中就是核心函数jieba.cut(),代码如下:

 def cut(self, sentence, cut_all=False, HMM=True):
        """
        The main function that segments an entire sentence that contains
        Chinese characters into seperated 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.
        """
        sentence = strdecode(sentence)

        if cut_all:
            re_han = re_han_cut_all
            re_skip = re_skip_cut_all
        else:
            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

其中,

docstr中给出了默认的模式,精确分词 + HMM模型开启。

第12-23行进行了变量配置。

第24行做的事情是对句子进行中文的切分,把句子切分成一些只包含能处理的字符的块(block),丢弃掉特殊字符,因为一些词典中不包含的字符可能对分词产生影响。

24行中re_han默认值为re_han_default,是一个正则表达式,定义如下:

# u4E00-u9FD5a-zA-Z0-9+#&._ : All non-space characters. Will be handled with re_han
re_han_default = re.compile("([u4E00-u9FD5a-zA-Z0-9+#&._]+)", re.U)

可以看到诸如空格、制表符、换行符之类的特殊字符在这个正则表达式被过滤掉。

25-40行使用yield实现了返回结果是一个迭代器,即文档中所说:

jieba.cut 以及 jieba.cut_for_search 返回的结构都是一个可迭代的 generator,可以使用 for 循环来获得分词后得到的每一个词语(unicode)

其中,31-40行,如果遇到block是非常规字符,就正则验证一下直接输出这个块作为这个块的分词结果。如标点符号等等,在分词结果中都是多带带一个词的形式出现的,就是这十行代码进行的。

关键在28-30行,如果是可分词的block,那么就调用函数cut_block,默认是cut_block = self.__cut_DAG,进行分词

jieba.__cut_DAG()

__cut_DAG的作用是按照DAG,即有向无环图进行切分单词。其代码如下:

def __cut_DAG(self, sentence):
        DAG = self.get_DAG(sentence)
        route = {}
        self.calc(sentence, DAG, route)
        x = 0
        buf = ""
        N = len(sentence)
        while x < N:
            y = route[x][1] + 1
            l_word = sentence[x:y]
            if y - x == 1:
                buf += l_word
            else:
                if buf:
                    if len(buf) == 1:
                        yield buf
                        buf = ""
                    else:
                        if not self.FREQ.get(buf):
                            recognized = finalseg.cut(buf)
                            for t in recognized:
                                yield t
                        else:
                            for elem in buf:
                                yield elem
                        buf = ""
                yield l_word
            x = y

        if buf:
            if len(buf) == 1:
                yield buf
            elif not self.FREQ.get(buf):
                recognized = finalseg.cut(buf)
                for t in recognized:
                    yield t
            else:
                for elem in buf:
                    yield elem

对于一个sentence,首先 获取到其有向无环图DAG,然后利用dp对该有向无环图进行最大概率路径的计算。
计算出最大概率路径后迭代,如果是登录词,则输出,如果是单字,将其中连在一起的单字找出来,这些可能是未登录词,使用HMM模型进行分词,分词结束之后输出。

至此,分词结束。

其中,值得跟进研究的是第2行获取DAG第4行计算最大概率路径第20和34行的使用HMM模型进行未登录词的分词,在后面的文章中会进行解读。

DAG = self.get_DAG(sentence)

    ...

self.calc(sentence, DAG, route)

    ...

recognized = finalseg.cut(buf)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37653.html

相关文章

  • jieba分词学习笔记(三)

    摘要:由此得到了,下一步就是使用动态规划对最大概率路径进行求解。最大概率路径值得注意的是,的每个结点,都是带权的,对于在词典里面的词语,其权重为其词频,即。动态规划求解法满足的条件有两个重复子问题最优子结构我们来分析最大概率路径问题。 DAG(有向无环图) 有向无环图,directed acyclic graphs,简称DAG,是一种图的数据结构,其实很naive,就是没有环的有向图_(:...

    nevermind 评论0 收藏0
  • 分词,难在哪里?科普+解决方案!

    摘要:分词的算法中文分词有难度,不过也有成熟的解决方案。例如通过人民日报训练的分词系统,在网络玄幻小说上,分词的效果就不会好。三的优点是开源的,号称是中,最好的中文分词组件。 showImg(https://segmentfault.com/img/remote/1460000016359704?w=1350&h=900); 题图:by Lucas Davies 一、前言 分词,我想是大多数...

    Steven 评论0 收藏0
  • Python第三方库jieba库与中文分词全面详解

      Python在工作中的应用还是比较的广泛的,市场上面对于这类人才开出的薪资还是比较的高的。那么,如何使用第三方库jieba库与中文分词进行一个分解呢?下面小编就给大家详细的做出一个解答。  一、什么是jieba库  jieba是优秀的中文分词第三方库,由于中文文本之间每个汉字都是连续书写的,我们需要通过特定的手段来获得其中的每个词组,这种手段叫做分词,我们可以通过jieba库来完成这个过程。 ...

    89542767 评论0 收藏0
  • Python如何生成词云(详解)

    摘要:前言今天教大家用模块来生成词云,我读取了一篇小说并生成了词云,先看一下效果图效果图一效果图二根据效果图分析的还是比较准确的,小说中的主人公就是程理,所以出现次数最多。 前言 今天教大家用wrodcloud模块来生成词云,我读取了一篇小说并生成了词云,先看一下效果图: 效果图一: showImg(https://segmentfault.com/img/remote/1460000015...

    Juven 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<