分词_分词器 - CSDN
分词 订阅
分词就是具有动词及形容词二者特征的词,尤指以-ing或-ed,-d,-t,-en或-n结尾的英语动词性形容词,具有形容词功能,同时又表现各种动词性特点,如时态、语态、带状语性修饰语的性能及带宾词的性能。分词分为现在分词和过去分词两种,是一种非谓语动词形式。现在分词和过去分词主要差别在于:现在分词表示“主动和进行”,过去分词表示“被动和完成”(不及物动词的过去分词不表示被动,只表示完成)。分词可以有自己的状语、宾语或逻辑主语等。 展开全文
分词就是具有动词及形容词二者特征的词,尤指以-ing或-ed,-d,-t,-en或-n结尾的英语动词性形容词,具有形容词功能,同时又表现各种动词性特点,如时态、语态、带状语性修饰语的性能及带宾词的性能。分词分为现在分词和过去分词两种,是一种非谓语动词形式。现在分词和过去分词主要差别在于:现在分词表示“主动和进行”,过去分词表示“被动和完成”(不及物动词的过去分词不表示被动,只表示完成)。分词可以有自己的状语、宾语或逻辑主语等。
信息
结    构
现在分词doing,过去分词done
外文名
participle
语    法
非谓语动词形式
中文名
分词
特    征
具有动词及形容词二者特征
表    示
进行,完成,被动
分词分词的类型
一般式doing一般被动式 done完成式having done完成被动式having been done所有否定式都是在-ing前面加not,过去分词done
收起全文
精华内容
参与话题
  • 数据挖掘基础-2.中文分词

    千次阅读 2018-09-27 21:56:07
    一、中文分词 分词是文本相似度的基础,不同于英文分词,中文没有空格,所以在进行自然语言处理处理前,需要先进行中文分词。 1.常用方法-基于词典匹配 即有个用于匹配的词典,一般采用最大长度查找法,可以分为...

    一、中文分词

    分词是文本相似度的基础,不同于英文分词,中文没有空格,所以在进行自然语言处理处理前,需要先进行中文分词。

    1.常用方法-基于词典匹配

    即有个用于匹配的词典,一般采用最大长度查找法,可以分为前向查找,后向查找。

    前向查找:待切分的句子从前往后切分,如果有存在一个最大长度的词在词典中,就在这切分。后向查找:句子从后往前切分,原理和前向相同。一般来说后向切分效果会好一点,因为中文重心一般位于句子后面。

    举例:有带切分的句子“北京大学生活动中心”。通过前向查找,发现“北”、“北京”、“北京大”、“北京大学”都在词典中,但是没有“北京大学生”,因此判断可切分的最大长度就是“北京大学”,因此就在这里切分,依次类推可以切分出“生活“、”动”、“中心”,这结果显然不是很合理。如果通过后向查找:将会先切分出“中心”、接下来依次是“生活”、“大学生”、“北京”,切分的效果会比前向的好。由于中文的重心一般位于句子后面,所以后向查找的效果总体效果会比前向查找好。

    2.概率语言模型

    自然语言处理可以分为两个阶段:基于规则和基于统计。基于规则即基于语言的语法来分析句子,基于统计则是根据统计来得出处理结果。后来语义分析渐入瓶颈,而基于统计逐渐大放光彩,成为现在的绝对主流。有兴趣的可以阅读吴军的《数学之美》,讲的非常有意思。

    从统计思想的角度来看,分词问题的输入是一个字串C=c1,c2……cn ,输出是一个词串S=w1,w2……wm ,其中m<=n。对于一个特定的字符串C,会有多个切分方案S对应,假设这两种切分方法分别叫做S1和S2。计算条件概率P(S1|C)和P(S2|C),然后根据P(S1|C)和P(S2|C)的值大小来决定选择S1还是S2。通过贝叶斯公式可以将P(S|C)的计算转换成如下形式。

    • P(S|C)是由字符串C产生切分S的概率,也就是对输入字符串切分出最有可能的词序列概率值。

    • P(C)只是一个用来归一化的固定值,即这个句子在语料库中占的比例。从词串恢复到汉字串的概率只有一种可能,所以P(C|S)=1。比较P(S1|C)和P(S2|C)的大小变成比较P(S1)和P(S2) 的大小。

    p(S1|C)/p(S2|C) = p(S1)/p(S2)

    例如:对于输入字符串C“南京市长江大桥”,有下面两种切分可能:

    – S1:南京市 / 长江 / 大桥

    – S2:南京 / 市长 / 江大桥

    假设语料库中有1万个句子,其中有一句是 “南京市长江大桥”, 那么P(C)=P(“南京市长江大桥” )=万分之一。

    假设每个词出现的概率互相独立,因为P(S1)=P(南京市,长江,大桥)=P(南京市)*P(长江)*P(大桥)> P(S2)=P(南京,市长,江大桥),所以选择切分方案S1。

    3.一元模型

    假设每个词出现的概率独立的,即上下文无关。对于不同的S(切分方案),m(分词的数量)的值是不一样的,一般来说m越大,P(S)会越小,也就是说,分出的词越多,概率越小(但是也不一定,只是有这个倾向)。词出现的概率计算公式 如下:

    由于这个值可能会很小,所以采用log进行计算,防止值向下溢出,即logP(wi ) = log(Freq w ) - logN。

    因此基于一元模型的计算公式如下:

    P(S) = P(w1,w 2,...,wm ) P(w1)×P(w 2 )×...×P(wm )logP(w1) +logP(w 2 ) +...+ logP(wm )

    其中,P(w) 就是这个词出现在语料库中的概率。 ∝是正比符号,因为词的概率小于1,所以取log后是负数。

    4.N元模型

    一元模型假设词的出现是独立,但是实际上词与词之间出现经常是上下文相关的,为了切分更准确,要考虑词所处的上下文。N元模型使用n个单词组成的序列来衡量切分方案的合理性,所以这里就需要使用条件概率。单词w1后出现w2的概率,根据条件概率的定义:

    可以得到:P(w1,w2)= P(w1)P(w2|w1),同理:P(w1,w2,w3)= P(w1,w2)P(w3|w1,w2)

    所以有:P(w1,w2,w3)= P(w1)P(w2|w1)P(w3|w1,w2),更加一般的形式如下:

    P(S)=P(w1,w2,...,wn)= P(w1)P(w2|w1)P(w3|w1,w2)…P(wn|w1w2…wn-1),这叫做概率的链规则。

    • 如果一个词的出现不依赖于它前面出现的词,叫做一元模型(Unigram)。如果简化成一个词的出现仅依赖于它前面出现的一个词,那么就称为二元模型(Bigram)。公式如下:

    P(S)=P(w1,w2,...,wn)=P(w1) P(w2|w1) P(w3|w1,w2)…P(wn|w1w2…wn-1)≈P(w1) P(w2|w1) P(w3|w2)…P(wn|wn-1)

    • 如果简化成一个词的出现仅依赖于它前面出现的两个词,就称之为三元模型(Trigram)。一般使用较多的就是这几种模型,更高阶的模型使用较少。

    二、Jieba分词

    1.概述

    源码下载地址:http://github.com/fxsjy/jieba

    jieba分词主要是基于统计词典,构造一个前缀词典;然后利用前缀词典对输入句子进行切分,得到所有的切分可能,根据切分位置,构造一个有向无环图;通过动态规划算法,计算得到最大概率路径,也就得到了最终的切分形式。下文会结合例子具体讲解。

    • 支持三种分词模式

    – 精确模式:将句子最精确的分开,适合文本分析

    – 全模式:句子中所有可以成词的词语都扫描出来,速度快,不能解决歧义

    – 搜索引擎模式:在精确模式基础上,对长词再次切分,提高召回

    • 支持繁体分词、支持自定义字典

    2.jieba分词思路

    下面的内容参考:https://segmentfault.com/a/1190000004061791http://www.cnblogs.com/zhbzz2007的学习笔记。

    jieba分词对已收录词和未收录词都有相应的算法进行处理,其处理的思路很简单,当然,过于简单的算法也是制约其召回率的原因之一。其主要的处理思路如下:

    1)加载词典dict.txt,形成前缀词典

    2)根据内存的前缀词典,构建该句子的DAG(有向无环图)

    3)对于词典中未收录词,使用HMM模型的viterbi算法尝试分词处理

    4)已收录词和未收录词全部分词完毕后,使用dp寻找DAG的最大概率路径

    5)输出分词结果

    3.Jieba分词详解

    jieba.__init__.py中实现了jieba分词接口函数cut(self, sentence, cut_all=False, HMM=True)。

    jieba分词接口主入口函数,会首先将输入文本解码为Unicode编码,然后根据入参,选择不同的切分方式,本文主要以精确模式进行讲解,因此cut_all和HMM这两个入参均为默认值;

    切分方式选择,

    re_han = re_han_default
    re_skip = re_skip_default

    块切分方式选择,

    cut_block = self.__cut_DAG

    函数__cut_DAG(self, sentence)首先构建前缀词典,其次构建有向无环图,然后计算最大概率路径,最后基于最大概率路径进行分词,如果遇到未登录词,则调用HMM模型进行切分。

    1)词典加载

    jieba分词默认的模型使用了一些语料来做训练集,来源主要有两个,一个是网上能下载到的1998人民日报的切分语料,还有一个msr的切分语料。另一个是作者收集的一些txt小说,用ictclas把他们切分(可能有一定误差)。 然后用python脚本统计词频。

    语料库中所有的词语被用来做两件事情:对词语的频率进行统计,作为登录词使用;对单字在词语中的出现位置进行统计,使用BMES模型进行统计,供HMM模型Viterbi算法使用。统计后的结果保存在dict.txt中,摘录其部分结构如下:

    上访 212 v
    上访事件 3 n
    上访信 3 nt
    上访户 3 n
    上访者 5 n
    上证 120 j
    上证所 8 nt

    其中,第一列是中文词语,第二列是词频,第三列是词性,jieba分词现在的版本除了分词也提供词性标注等其他功能,这个不在本文讨论范围内,可以先忽略第三列。接下来需要将词典加载到内存。

    jieba分词为了快速地索引词典以加快分词性能,使用了前缀词典。在旧版本的jieba分词中,jieba采用trie树的数据结构来存储,其实对于python来说,使用trie树显得非常多余,下面将对新老版本的字典加载分别进行分析。

    2)trie树

    trie树又叫字典树,是一种常见的数据结构,用于在一个字符串列表中进行快速的字符串匹配。其核心思想是将拥有公共前缀的单词归一到一棵树下以减少查询的时间复杂度,其主要缺点是占用内存太大了。

    trie树按如下方法构造:trie树的根节点是空,不代表任何含义;其他每个节点只有一个字符,词典中所有词的第一个字的集合作为第一层叶子节点,以字符α开头的单词挂在以α为根节点的子树下,所有以α开头的单词的第二个字的集合作为α子树下的第一层叶子节点,以此类推;从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。一个以and at as cn com构造的trie树如下图:

    查找过程如下:

    从根结点开始一次搜索;

    取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;

    在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。

    迭代过程……

    在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。其他操作类似处理。

    如查询at,可以找到路径root-a-t的路径,对于单词av,从root找到a后,在a的叶子节点下面不能找到v结点,则查找失败。

    trie树的查找时间复杂度为O(k),k = len(s),s为目标串。二叉查找树的查找时间复杂度为O(lgn),比起二叉查找树,trie树的查找和结点数量无关,因此更加适合词汇量大的情况。但是trie树对空间的消耗是很大的,是一个典型的空间换时间的数据结构。

    3)前缀词典

    在2014年的某次PR中(https://github.com/fxsjy/jieba/pull/187 ),提交者将trie树改成前缀词典,大大地减少了内存的使用,加快了查找的速度。现在jieba分词对于词典的操作,改为了一层word:freq的结构,存于lfreq中,其具体操作如下:

    1.对于每个收录词,直接放入lfreq词典中,并且将词频加到ltotal中。

    2.对该收录词的所有前缀,如单词'北京大学',则前缀为“北”、“北京”、“北京大”,判断这些词是否已经在lfreq词典中了,如果在不做处理,如果不在就加入到lfreq词典中,并且词频记为0。

    # f是离线统计的词典文件句柄
    def gen_pfdict(self, f):
        # 初始化前缀词典
        lfreq = {}
        ltotal = 0
        f_name = resolve_filename(f)
        for lineno, line in enumerate(f, 1):
            try:
                # 解析离线词典文本文件,离线词典文件格式如第2章中所示
                line = line.strip().decode('utf-8')
                # 词和对应的词频
                word, freq = line.split(' ')[:2]
                freq = int(freq)
                lfreq[word] = freq
                ltotal += freq
                # 获取该词所有的前缀词
                for ch in xrange(len(word)):
                    wfrag = word[:ch + 1]
                    # 如果某前缀词不在前缀词典中,则将对应词频设置为0,
                    if wfrag not in lfreq:
                        lfreq[wfrag] = 0
            except ValueError:
                raise ValueError(
                    'invalid dictionary entry in %s at Line %s: %s' % (f_name, lineno, line))
        f.close()
        return lfreq, ltotal

    现在就完成了jieba的词典加载。现在来了句子,就可以采取不同的分词模式,对句子进行切分。

    4)分词模式

    jieba分词有多种模式可供选择。

    # 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算法。

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

    默认的模式,精确分词 + 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,进行分词。

    6)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模型进行未登录词的分词。

    4.有向无环图:(DAG)

    有向无环图,directed acyclic graphs,简称DAG,是一种图的数据结构,顾名思义,就是没有环的有向图。DAG在分词中的应用很广,无论是最大概率路径,还是其它做法,DAG都广泛存在于分词中。因为DAG本身也是有向图,所以用邻接矩阵来表示是可行的,但是jieba采用了Python的dict结构,可以更方便的表示DAG。最终的DAG是以{k : [k , j , ..] , m : [m , p , q] , ...}的字典结构存储,其中k和m为词在文本sentence中的位置,k对应的列表存放的是文本中以k开始且词sentence[k: j + 1]在前缀词典中的 以k开始j结尾的词的列表,即列表存放的是sentence中以k开始的可能的词语的结束位置,这样通过查找前缀词典就可以得到词。

    get_DAG(self, sentence)函数进行对系统初始化完毕后,会根据输入的句子构建有向无环图。

    从前往后依次遍历句子的每个位置,对于位置k,首先形成一个片段,这个片段只包含位置k的字,然后就判断该片段是否在前缀词典中。

    如果这个片段在前缀词典中,

       1.1 如果词频大于0,就将这个位置i追加到以k为key的一个列表中;

       1.2 如果词频等于0,则表明前缀词典存在这个前缀,但是统计词典并没有这个词,继续循环;

    如果这个片段不在前缀词典中,则表明这个片段已经超出统计词典中该词的范围,则终止循环;

    然后该位置加1,然后就形成一个新的片段,该片段在句子的索引为[k:i+1],继续判断这个片段是否在前缀词典中。

    get_DAG()函数代码如下:

    # 有向无环图构建主函数
    def get_DAG(self, sentence):
        # 检查系统是否已经初始化
        self.check_initialized()
        # DAG存储向无环图的数据,数据结构是dict
        DAG = {}
        N = len(sentence)
        # 依次遍历文本中的每个位置
        for k in xrange(N):
            tmplist = []
            i = k
            # 位置k形成的片段
            frag = sentence[k]
            # 判断片段是否在前缀词典中
            # 如果片段不在前缀词典中,则跳出本循环
            # 也即该片段已经超出统计词典中该词的长度
            while i < N and frag in self.FREQ:
                # 如果该片段的词频大于0
                # 将该片段加入到有向无环图中
                # 否则,继续循环
                if self.FREQ[frag]:
                    tmplist.append(i)
                # 片段末尾位置加1
                i += 1
                # 新的片段较旧的片段右边新增一个字
                frag = sentence[k:i + 1]
            if not tmplist:
                tmplist.append(k)
            DAG[k] = tmplist
        return DAG

    frag即fragment,可以看到代码循环切片句子,FREQ即是前缀词典。因为在载入词典的时候已经将word和word的所有前缀加入了词典,所以一旦frag not in FREQ,即可以断定frag和以frag为前缀的词不在词典里,可以跳出循环。由此得到了DAG,下一步就是使用dp动态规划对最大概率路径进行求解。

    5.动态规划——最大概率路径计算

    有向无环图DAG的每个节点,都是带权的,对于在前缀词典里面的词语,其权重就是它的词频;我们想要求得route = (w1,w2,w3,...,wn),使得 ∑weight(wi) 最大。如果需要使用动态规划求解,需要满足两个条件,重复子问题、最优子结构。

    重复子问题:

    对于节点wi和其可能存在的多个后继节点Wj和Wk:

    任意通过Wi到达Wj的路径的权重 = 该路径通过Wi的路径权重 + Wj的权重,也即{Ri -> j} = {Ri + weight(j)}
    任意通过Wi到达Wk的路径的权重 = 该路径通过Wi的路径权重 + Wk的权重,也即{Ri -> k} = {Ri + weight(k)}

    即对于拥有公共前驱节点Wi的节点Wj和Wk,需要重复计算达到Wi的路径的概率。

    最优子结构:

    对于整个句子的最优路径Rmax和一个末端节点Wx,对于其可能存在的多个前驱Wi,Wj,Wk...,设到达Wi,Wj,Wk的最大路径分别是Rmaxi,Rmaxj,Rmaxk,有:

    Rmax = max(Rmaxi,Rmaxj,Rmaxk,...) + weight(Wx)

    于是,问题转化为,求解Rmaxi,Rmaxj,Rmaxk,...等,组成了最优子结构,子结构里面的最优解是全局的最优解的一部分。状态转移方程为:

    Rmax = max{(Rmaxi,Rmaxj,Rmaxk,...) + weight(Wx)}

    jieba分词中计算最大概率路径的主函数是calc(self, sentence, DAG, route),函数根据已经构建好的有向无环图计算最大概率路径。函数是一个自底向上的动态规划问题,它从sentence的最后一个字(N-1)开始倒序遍历sentence的每个字(idx)的方式,计算子句sentence[idx ~ N-1]的概率对数得分。然后将概率对数得分最高的情况以(概率对数,词语最后一个位置)这样的元组保存在route中。函数中,logtotal为构建前缀词频时所有的词频之和的对数值,这里的计算都是使用概率对数值,可以有效防止下溢问题。

    jieba分词中calc函数实现如下

    def calc(self, sentence, DAG, route):
        N = len(sentence)
        # 初始化末尾为0
        route[N] = (0, 0)
        logtotal = log(self.total)
        # 从后到前计算
        for idx in xrange(N - 1, -1, -1):#遍历0-N-1,-1代表递减的方式
            route[idx] = max((log(self.FREQ.get(sentence[idx:x + 1]) or 1) -
                              logtotal + route[x + 1][0], x) for x in DAG[idx])
            print "root:",route #这里是自己加的,为了看到每次输出的route,在实际代码中没有

    例如:DAG :{0: [0, 1], 1: [1], 2: [2, 3, 5], 3: [3], 4: [4, 5], 5: [5], 6: [6, 7], 7: [7]}

    计算过程:

    root: {8: (0, 0), 7: (-8.702713881905304, 7)}
    root: {8: (0, 0), 6: (-8.682096638586806, 7), 7: (-8.702713881905304, 7)}
    root: {8: (0, 0), 5: (-18.81251125649701, 5), 6: (-8.682096638586806, 7), 7: (-8.702713881905304, 7)}
    root: {8: (0, 0), 4: (-25.495037477673915, 5), 5: (-18.81251125649701, 5), 6: (-8.682096638586806, 7), 7: (-8.702713881905304, 7)}
    root: {3: (-34.70541057789988, 3), 4: (-25.495037477673915, 5), 5: (-18.81251125649701, 5), 6: (-8.682096638586806, 7), 7: (-8.702713881905304, 7), 8: (0, 0)}
    root: {2: (-25.495037477673915, 5), 3: (-34.70541057789988, 3), 4: (-25.495037477673915, 5), 5: (-18.81251125649701, 5), 6: (-8.682096638586806, 7), 7: (-8.702713881905304, 7), 8: (0, 0)}
    root: {1: (-33.72931380325669, 1), 2: (-25.495037477673915, 5), 3: (-34.70541057789988, 3), 4: (-25.495037477673915, 5), 5: (-18.81251125649701, 5), 6: (-8.682096638586806, 7), 7: (-8.702713881905304, 7), 8: (0, 0)}
    root: {0: (-34.76895126093703, 1), 1: (-33.72931380325669, 1), 2: (-25.495037477673915, 5), 3: (-34.70541057789988, 3), 4: (-25.495037477673915, 5), 5: (-18.81251125649701, 5), 6: (-8.682096638586806, 7), 7: (-8.702713881905304, 7), 8: (0, 0)}

    三、马尔科夫模型

    对于未登录词,需要使用隐马尔可夫模型进行分词。这里先介绍马尔科夫模型。

    1.马尔科夫模型

    • 每个状态只依赖之前有限个状态,对于N阶马尔科夫,依赖之前n个状态。1阶马尔科夫仅仅依赖前一个状态,即2元模型。

    p(w1,w2,w3,w4…wn) = p(w1)p(w2|w1)p(w3|w1,w2)……p(wn|w1,w2,……,wn-1) =p(w1) p(w2|w1) p(w3|w2)……p(wn|wn-1)

    • 参数

      – 状态,由数字表示,假设共有M个(有多少字就有多少个状态)

      – 初始概率,由πk表示

                       

      – 状态转移概率,由表示ak,l表示,词k变换到词l的概率

                    

    这些参数值用统计的方法来获得,即最大似然估计法。

    2.最大似然法

    最大似然估计,就是利用已知的样本结果,反推最有可能(最大概率)导致这样结果的参数值,在这里就是根据样本的情况,近似地得到概率值,所以下面的等号严格来说是约等号。

    – 状态转移概率ak,l,P(St+1=l|St=k)=l紧跟k出现的次数/k出现的总次数

    – 初始概率πk,P(S1=k)=k作为序列开始的次数/观测序列总数

    马尔科夫模型是对一个序列数据建模,但有时需要对两个序列数据建模,所以需要隐马尔可夫模型。例如如下几个场景:

    • 机器翻译:源语言序列 <-> 目标语言序列

    • 语音识别:语音信号序列 <-> 文字序列

    • 词性标注:文字序列 <-> 词性序列

           – 写/一个/程序

          – Verb/Num/Noun

    3.隐马尔科夫模型HMM

    1)观察序列和隐藏序列

    通常其中一个序列是观察到的,背后隐藏的序列是要寻找的,把观察到的序列表示为O,隐藏的序列表示为S。观察序列O中的数据通常是由对应的隐藏序列数据决定的。隐藏序列数据间相互依赖,通常构成了马尔科夫序列。例如,语音识别中声波信号每段信号都是相互独立的,由对应的文字决定,对应的文字序列中相邻的字相互依赖,构成Markov链。观察和隐藏序列共同构成隐马模型。

    • O(o1o2 … oT):观测序列,ot只依赖于st

    • S(s1s2 … sT):状态序列(隐藏序列),S是Markov序列,假设1阶Markov序列,则st+1只依赖于st

    2)HMM参数

    – 状态s,由数字表示,假设共有M个

    – 观测o,由数字表示,假设共有N个

    – 初始概率,由πk表示

    – 状态转移概率,由ak,l表示

    – 发射概率,由bk(u) 表示

     

    3)HMM生成过程

    生成第一个状态,然后依次由当前状态生成下一个状态,最后每个状态发射出一个观察值。

    四、jieba中的HMM详解

    基于前缀词典和动态规划方法可以实现分词,但是如果没有前缀词典或者有些词不在前缀词典中,jieba分词一样可以分词,基于汉字成词能力的HMM模型识别未登录词。利用HMM模型进行分词,主要是将分词问题视为一个序列标注(sequence labeling)问题,其中,句子为观测序列,分词结果为状态序列。首先通过语料训练出HMM相关的模型,然后利用Viterbi算法进行求解,最终得到最优的状态序列,然后再根据状态序列,输出分词结果。

    1.序列标注

    序列标注,就是将输入句子和分词结果当作两个序列,句子为观测序列,分词结果为状态序列,当完成状态序列的标注,也就得到了分词结果。

    以“去北京大学玩”为例,“去北京大学玩”的分词结果是“去 / 北京大学 / 玩”。对于分词状态,由于jieba分词中使用的是4-tag,因此我们以4-tag进行计算。4-tag,也就是每个字处在词语中的4种可能状态,B、M、E、S,分别表示Begin(这个字处于词的开始位置)、Middle(这个字处于词的中间位置)、End(这个字处于词的结束位置)、Single(这个字是单字成词)。具体如下图所示,“去”和“玩”都是单字成词,因此状态就是S,“北京大学”是多字组合成的词,因此“北”、“京”、“大”、“学”分别位于“北京大学”中的B、M、M、E。

    https://images2015.cnblogs.com/blog/668850/201611/668850-20161118123105545-1599810853.png

    2.HMM模型作的两个基本假设

    1.齐次马尔科夫性假设,即假设隐藏的马尔科夫链在任意时刻t的状态只依赖于其前一时刻的状态,与其它时刻的状态及观测无关,也与时刻t无关;

    P(states[t] | states[t-1],observed[t-1],...,states[1],observed[1]) = P(states[t] | states[t-1]) t = 1,2,...,T

    2.观测独立性假设,即假设任意时刻的观测只依赖于该时刻的马尔科夫链的状态,与其它观测和状态无关;

    P(observed[t] | states[T],observed[T],...,states[1],observed[1]) = P(observed[t] | states[t]) t = 1,2,...,T

    3.HMM模型三个基本问题

    1.概率计算问题,给定模型 λ=(A,B,π)和观测序列 O=(o1,o2,...,oT),怎样计算在模型λ下观测序列O出现的概率 P(O|λ),也就是前向(Forward-backward)算法;

    2.学习问题,已知观测序列 O=(o1,o2,...,oT)O=(o1,o2,...,oT) ,估计模型 λ=(A,B,π)λ=(A,B,π) ,使得在该模型下观测序列的概率 P(O|λ)P(O|λ) 尽可能的大,即用极大似然估计的方法估计参数;

    3.预测问题,也称为解码问题,已知模型 λ=(A,B,π)和观测序列 O=(o1,o2,...,oT),求对给定观测序列条件概率 P(S|O)P(S|O) 最大的状态序列 I=(s1,s2,...,sT),即给定观测序列,求最有可能的对应的状态序列;

    其中,jieba分词主要涉及第三个问题,也即预测问题。

    这里仍然以“去北京大学玩”为例,那么“去北京大学玩”就是观测序列。而“去北京大学玩”对应的“SBMMES”则是隐藏状态序列,我们将会注意到B后面只能接(M或者E),不可能接(B或者S);而M后面也只能接(M或者E),不可能接(B或者S)。

    状态初始概率表示,每个词初始状态的概率;jieba分词训练出的状态初始概率模型如下所示。

    P={'B': -0.26268660809250016,
     'E': -3.14e+100,
     'M': -3.14e+100,
     'S': -1.4652633398537678}

    其中的概率值都是取对数之后的结果(可以让概率相乘转变为概率相加),其中-3.14e+100代表负无穷,对应的概率值就是0。这个概率表说明一个词中的第一个字属于{B、M、E、S}这四种状态的概率,如下可以看出,E和M的概率都是0,这也和实际相符合:开头的第一个字只可能是每个词的首字(B),或者单字成词(S)。这部分对应jieba/finaseg/ prob_start.py,具体可以进入源码查看。

    状态转移概率是马尔科夫链中很重要的一个知识点,一阶的马尔科夫链最大的特点就是当前时刻T = i的状态states(i),只和T = i时刻之前的n个状态有关,即{states(i-1),states(i-2),...,states(i-n)}。再看jieba中的状态转移概率,其实就是一个嵌套的词典,数值是概率值求对数后的值,如下所示,

    P={'B': {'E': -0.510825623765990, 'M': -0.916290731874155},
     'E': {'B': -0.5897149736854513, 'S': -0.8085250474669937},
     'M': {'E': -0.33344856811948514, 'M': -1.2603623820268226},
     'S': {'B': -0.7211965654669841, 'S': -0.6658631448798212}}

    P['B']['E']代表的含义就是从状态B转移到状态E的概率,由P['B']['E'] = -0.58971497368-54513,表示当前状态是B,下一个状态是E的概率对数是-0.5897149736854513,对应的概率值是0.6,相应的,当前状态是B,下一个状态是M的概率是0.4,说明当我们处于一个词的开头时,下一个字是结尾的概率要远高于下一个字是中间字的概率,符合我们的直觉,因为二个字的词比多个字的词更常见。这部分对应jieba/finaseg/prob_trans.py,具体可以查看源码。

    状态发射概率,根据HMM模型中观测独立性假设,发射概率,即观测值只取决于当前状态值,也就如下所示,

    P(observed[i],states[j]) = P(states[j]) * P(observed[i] | states[j])

    其中,P(observed[i] | states[j])就是从状态发射概率中获得的。

    P={'B': {'一': -3.6544978750449433,
           '丁': -8.125041941842026,
           '七': -7.817392401429855,
    ...
    'S': {':': -15.828865681131282,
      '一': -4.92368982120877,
      '丁': -9.024528361347633,
    ...

    P['B']['一']代表的含义就是状态处于'B',而观测的字是‘一’的概率对数值为P['B']['一'] = -3.6544978750449433。这部分对应jieba/finaseg/prob_emit.py,具体可以查看源码。

    有了初始概率、发射概率和转移概率后,HMM的模型也就准备完毕,现在就需要根据输入的句子,计算出背后的隐藏序列,并选取出概率最大的隐藏序列作为分词的结果。(词性一旦标注完,就知道BMES的具体位置,只要在S和E的位置进行切分就可以得到切分结果,这很容易理解)假设输入13个汉字,每个汉字背后有10个不同的状态,为了得到最大概率的序列,朴素的做法就是进行10的13次方计算,从中选出概率最大的那个。这个计算量是非常巨大的,因此jieba使用维特比算法来求解概率最大的路径。

    五、viterbi算法

    Viterbi算法实际上是用动态规划求解HMM模型预测问题,即用动态规划求概率路径最大(最优路径)。一条路径对应着一个状态序列。如图所示,x代表着状态序列。

    viterbi算法的核心思想是:

    1.如果概率最大的路径P经过某个点,假设是X22,那么这条路径上从起始点S到X22的这段子路径Q,一定是S到X22之间最短的路径。否则,用另外一条路径R代替Q,就构成了另外一条比P概率更大的路径,这是矛盾的。(即最大最是最大,没有其他更大的,听起来感觉没什么用的样子)

    2.从S到E的路径必定经过第i时刻的某个状态,假定第i时刻有k个状态,那么如果记录了从S到第i个状态的所有k个节点的最短路径,最终的最短路径必经过其中的一条。这样,在任何时刻,只要考虑非常有限条最短路径即可。

    3.综合上面两点,假定从状态i到状态i+1,从S到状态i上各个节点的最短路径已经找到,并且记录在节点上,那么计算从起点S到第i+1状态的某个节点Xi+1的最短路径时,只要考虑S到前一个状态i所有的k个节点的最短路径,以及从这个k个节点到Xi+1的距离即可。

    这样时间复杂度不超过:O(N*D^2),N代表总共几个字,D代表状态最多的那个字的状态数目。

    jieba分词会首先调用函数cut(sentence),cut函数会先将输入句子进行解码,然后调用__cut函数进行处理。__cut函数就是jieba分词中实现HMM模型分词的主函数。__cut函数会首先调用viterbi算法,求出输入句子的隐藏状态,然后基于隐藏状态进行分词。

    def __cut(sentence):
        global emit_P
        # 通过viterbi算法求出隐藏状态序列
        prob, pos_list = viterbi(sentence, 'BMES', start_P, trans_P, emit_P)
        begin, nexti = 0, 0
        # print pos_list, sentence
        # 基于隐藏状态序列进行分词
        for i, char in enumerate(sentence):
            pos = pos_list[i]
            # 字所处的位置是开始位置
            if pos == 'B':
                begin = i
            # 字所处的位置是结束位置
            elif pos == 'E':
                # 这个子序列就是一个分词
                yield sentence[begin:i + 1]
                nexti = i + 1
            # 单独成字
            elif pos == 'S':
                yield char
                nexti = i + 1
        # 剩余的直接作为一个分词,返回
        if nexti < len(sentence):
            yield sentence[nexti:]

    jieba分词实现Viterbi算法是在viterbi(obs, states, start_p, trans_p, emit_p)函数中实现。viterbi函数会先计算各个初始状态的对数概率值,然后递推计算,每时刻某状态的对数概率值取决于上一时刻的对数概率值、上一时刻的状态到这一时刻的状态的转移概率、这一时刻状态转移到当前的字的发射概率三部分组成。

    def viterbi(obs, states, start_p, trans_p, emit_p):
        V = [{}]  # tabular
        path = {}
        # 时刻t = 0,初始状态
        for y in states:  # init
            V[0][y] = start_p[y] + emit_p[y].get(obs[0], MIN_FLOAT)
            path[y] = [y]
        # 时刻t = 1,...,len(obs) - 1
        for t in xrange(1, len(obs)):
            V.append({})
            newpath = {}
            # 当前时刻所处的各种可能的状态
            for y in states:
                # 获取发射概率对数
                em_p = emit_p[y].get(obs[t], MIN_FLOAT)
                # 分别获取上一时刻的状态的概率对数,该状态到本时刻的状态的转移概率对数,本时刻的状态的发射概率对数
                # 其中,PrevStatus[y]是当前时刻的状态所对应上一时刻可能的状态
                (prob, state) = max(
                    [(V[t - 1][y0] + trans_p[y0].get(y, MIN_FLOAT) + em_p, y0) for y0 in PrevStatus[y]])
                V[t][y] = prob
                # 将上一时刻最优的状态 + 这一时刻的状态
                newpath[y] = path[state] + [y]
            path = newpath
        # 最后一个时刻
        (prob, state) = max((V[len(obs) - 1][y], y) for y in 'ES')
        # 返回最大概率对数和最优路径
        return (prob, path[state])

    输出分词结果

    Viterbi算法得到状态序列,根据状态序列得到分词结果。其中状态以B开头,离它最近的以E结尾的一个子状态序列或者单独为S的子状态序列,就是一个分词。以去北京大学玩的隐藏状态序列”SBMMES“为例,则分词为”S / BMME / S“,对应观测序列,也就是 / 北京大学 /

    六、实践

    1.中文分词和webserver

    下载jieba和web模块。模拟用户在浏览器输入中文句子,浏览器返回一个切分结果。

    #encoding=utf-8
    import web
    import sys
    sys.path.append("./")//这里需要把jieba里面的jieba模块加载进去,所以要注意路径问题。
    import jieba
    import jieba.posseg
    import jieba.analyse
    
    urls = (
        '/', 'index',默认的方式
        '/test', 'test',
    )
    
    app = web.application(urls, globals())
    class index:
        def GET(self):
            params = web.input()
            context = params.get('context', '')//自定义输入http://192.168.101.10:9999/? context=语句
    
            seg_list = jieba.cut(context)
            result = ", ".join(seg_list)
            print("=====>", result)打印结果
            return result
    
    class test: //只是用来测试用的,http://192.168.101.10:9999/test返回都是222
        def GET(self):
            print web.input()
            return '222'
    if __name__ == "__main__":
        app.run()

    [root@master segment]# python web_seg.py 9999

    http://192.168.101.10:9998/?context=加入购物车,结果为乱码,需要在浏览器修改编码方式,在选项卡里面工具,修改为自动检测或者utf-8等。

    结果:加入, 购物车

    2.jieba和mapreduce结合

    如果输入的句子非常庞大,就需要将jieba分词和MapReduce相结合起来,否则很难在一台机子上搞定。现在假设有如下的数据,其中第一列代表该句子的id,第二列代表句子。我们的目的是将句子进行切分,当用户的输入一旦包含切分的词,就会返回对应的id值,即查询到该条记录。

    8920791333    天路MV-韩红

    8920845333    初音未来PV【世界第一公主殿下】

    8920849333    曼莉(dj电音舞曲)

    8920888333    《我是歌手》第四场无歌单惊呆众歌手!

    以最后一条为例,加入切分成:我、是、歌手、第四场、无歌单、惊呆、众歌手,当用户输入“歌手”,就返回8920888333记录进行展示。

    1)run.sh

    这里使用到hadoop-streaming,可以参考大数据基础学习-2.Hadoop1.0、MapReduce中的内容进行学习。

    #HADOOP_CMD="/usr/local/src/hadoop-1.2.1/bin/hadoop"
    #STREAM_JAR_PATH="/usr/local/src/hadoop-1.2.1/contrib/streaming/hadoop-streaming-1.2.1.jar"
    
    HADOOP_CMD="/usr/local/src/hadoop-2.6.0-cdh5.7.0/bin/hadoop"
    STREAM_JAR_PATH="/usr/local/src/hadoop-2.6.0-cdh5.7.0/share/hadoop/tools/lib/hadoop-streaming-2.6.0-cdh5.7.0.jar"
    
    INPUT_FILE_PATH_1="/music_meta.txt.small"
    OUTPUT_Z_PATH="/output_z_fenci"
    OUTPUT_D_PATH="/output_d_fenci"
    
    $HADOOP_CMD fs -rmr $OUTPUT_Z_PATH
    $HADOOP_CMD fs -rmr $OUTPUT_D_PATH
    
    # Step 1.
    $HADOOP_CMD jar $STREAM_JAR_PATH \
        -input $INPUT_FILE_PATH_1 \
        -output $OUTPUT_Z_PATH \
        -mapper "python map.py mapper_func" \
        -jobconf "mapred.reduce.tasks=0" \
        -jobconf  "mapred.job.name=jieba_fenci_demo" \
        -file "./jieba.tar.gz" \
        -file "./map.py"
    
    # Step 2.
    $HADOOP_CMD jar $STREAM_JAR_PATH \
        -input $OUTPUT_Z_PATH \
        -output $OUTPUT_D_PATH \
        -mapper "python map_inverted.py mapper_func" \
        -reducer "python red_inverted.py reducer_func" \
        -jobconf "mapred.reduce.tasks=2" \
        -jobconf  "mapred.job.name=jieba_fenci" \
        -file "./map_inverted.py" \
        -file "./red_inverted.py"

    2)map.py

    #!/usr/bin/python
    import os
    import sys
    os.system('tar xvzf jieba.tar.gz > /dev/null')//先把jieba中的jieba模块的压缩包进行解压
    reload(sys)
    sys.setdefaultencoding('utf-8')
    sys.path.append("./")//将jieba模块加载进来
    
    import jieba
    import jieba.posseg
    import jieba.analyse
    
    def mapper_func():
        for line in sys.stdin: //music_meta.txt.small读进来
            ss = line.strip().split('\t')
            if len(ss) != 2:
                continue
            music_id = ss[0].strip()
            music_name = ss[1].strip()
    
            tmp_list = []
            for x, w in jieba.analyse.extract_tags(music_name, withWeight=True): //x为词,w为词的if-idf值
                tmp_list.append((x, float(w))) //单词和权重
            final_token_score_list = sorted(tmp_list, key=lambda x: x[1], reverse=True) //倒序排序, 结尾再添加[:3]可取出前top3个
            print '\t'.join([music_id, music_name, '^A'.join(['^B'.join([t_w[0], str(t_w[1])]) for t_w in final_token_score_list])])
    
    
    if __name__ == "__main__":
        module = sys.modules[__name__]
        func = getattr(module, sys.argv[1])
        args = None
        if len(sys.argv) > 1:
            args = sys.argv[2:]
        func(*args)

    结果如下,形成了一个正排表:

    9056597333	哈利波特电影主题曲 - 钢琴版	哈利波2.98869187572主题曲2.95530902757钢琴2.06380768858电影1.6644699323
    9056759333	李玉刚《日日红上海》	李玉刚3.98492250097日日2.99114132227上海1.52787922045
    9056887333	佛教音乐	佛教3.42225118394音乐3.31483455685
    9057033333	美久广场舞2013_神曲来袭_摇一摇.zero	美久1.70782392899zero1.70782392899摇一摇1.7078239289920131.70782392899神曲1.46615592746来袭1.35454814917广场1.01644142957
    9057091333	爱在女儿乡	女儿6.01572470622

    得到正排表后,就需要将数据进行处理,形成倒排表,这是搜索的基础。

    3)map_inverted.py

    #!/usr/bin/python
    import os
    import sys
    
    def mapper_func():
        for line in sys.stdin:
            ss = line.strip().split('\t')
            if len(ss) != 3:
                continue
            music_id = ss[0].strip()
            music_name = ss[1].strip()
            music_fealist = ss[2].strip()
    
            for fea in music_fealist.split('^A'):
                token, weight = fea.strip().split('^B')
                print '\t'.join([token, music_name, weight])
    
    if __name__ == "__main__":
        module = sys.modules[__name__]
        func = getattr(module, sys.argv[1])
        args = None
        if len(sys.argv) > 1:
            args = sys.argv[2:]
        func(*args)

    4)red_inverted.py

    #!/usr/bin/python
    
    import os
    import sys
    
    def reducer_func():
        cur_token = None
        m_list = []
        for line in sys.stdin:
            ss = line.strip().split('\t')
            if len(ss) != 3:
                continue
            token = ss[0].strip()
            name = ss[1].strip()
            weight = float(ss[2].strip())
    
            if cur_token == None:
                cur_token = token
            if cur_token != token:
                final_list = sorted(m_list, key=lambda x: x[1], reverse=True)
                print '\t'.join([cur_token, '^A'.join(['^B'.join([name_weight[0], str(name_weight[1])]) for name_weight in final_list])])
                cur_token = token
                m_list = []
            m_list.append((name, weight))
        final_list = sorted(m_list, key=lambda x: x[1], reverse=True)
        print '\t'.join([cur_token, '^A'.join(['^B'.join([name_weight[0], str(name_weight[1])]) for name_weight in final_list])])
    
    if __name__ == "__main__":
        module = sys.modules[__name__]
        func = getattr(module, sys.argv[1])
        args = None
        if len(sys.argv) > 1:
            args = sys.argv[2:]
        func(*args)
    9993740333	张宇《不要来找我》 	张宇5.97738375145 不要 2.44647159005
    9993857333	韩磊《爱的箴言》	韩磊 5.97738375145 箴言 5.1871585637
    9993869333	茜拉《If I Ain`t Got You》	Got 5.97738375145 Ain 5.97738375145

     

    展开全文
  • 中文分词原理及分词工具介绍

    万次阅读 2018-07-31 11:00:37
    本文首先介绍下中文分词的基本原理,然后介绍下国内比较流行的中文分词工具,如jieba、SnowNLP、THULAC、NLPIR,上述分词工具都已经在github上开源,后续也会附上github链接,以供参考。 1.中文分词原理介绍 1.1 ...

    转自:https://blog.csdn.net/flysky1991/article/details/73948971

    本文首先介绍下中文分词基本原理,然后介绍下国内比较流行的中文分词工具,如jiebaSnowNLPTHULACNLPIR,上述分词工具都已经在github上开源,后续也会附上github链接,以供参考。

    1.中文分词原理介绍

    1.1 中文分词概述

    中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一个一个单独的词分词就是将连续的字序列按照一定的规范重新组合成词序列的过程

    1.2 中文分词方法介绍

    现有的分词方法可分为三大类:基于字符串匹配的分词方法基于理解的分词方法基于统计的分词方法

    1.2.1 基于字符串匹配的分词方法

    基于字符串匹配的分词方法又称机械分词方法,它是按照一定的策略待分析的汉字串与一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。

    按照扫描方向的不同,字符串匹配分词方法可以分为正向匹配逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配最小(最短)匹配;按照是否与词性标注过程相结合,可以分为单纯分词方法分词与词性标注相结合的一体化方法。常用的字符串匹配方法有如下几种:

    (1)正向最大匹配法(从左到右的方向);

    (2)逆向最大匹配法(从右到左的方向);

    (3)最小切分(每一句中切出的词数最小);

    (4)双向最大匹配(进行从左到右、从右到左两次扫描)

    这类算法的优点是速度快,时间复杂度可以保持在O(n),实现简单,效果尚可;但对歧义未登录词处理效果不佳。

    1.2.2 基于理解的分词方法

    基于理解的分词方法通过让计算机模拟人对句子的理解,达到识别词的效果。其基本思想就是在分词的同时进行句法、语义分析,利用句法信息语义信息处理歧义现象。它通常包括三个部分:分词子系统句法语义子系统总控部分。在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断,即它模拟了人对句子的理解过程。这种分词方法需要使用大量的语言知识和信息。由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式,因此目前基于理解的分词系统还处在试验阶段

    1.2.3 基于统计的分词方法

    基于统计的分词方法是在给定大量已经分词的文本的前提下,利用统计机器学习模型学习词语切分的规律(称为训练),从而实现对未知文本的切分。例如最大概率分词方法最大熵分词方法等。随着大规模语料库的建立,统计机器学习方法的研究和发展,基于统计的中文分词方法渐渐成为了主流方法

    主要的统计模型有:N元文法模型(N-gram),隐马尔可夫模型(Hidden Markov Model ,HMM),最大熵模型(ME),条件随机场模型(Conditional Random Fields,CRF)等。

    在实际的应用中,基于统计的分词系统都需要使用分词词典进行字符串匹配分词,同时使用统计方法识别一些新词,即将字符串频率统计字符串匹配结合起来,既发挥匹配分词切分速度快、效率高的特点,又利用了无词典分词结合上下文识别生词、自动消除歧义的优点

    2.中文分词工具介绍

    2.1 jieba (github star数 9003)

    jieba分词是国内使用人数最多的中文分词工具(github链接:https://github.com/fxsjy/jieba)。jieba分词支持三种模式

    (1)精确模式:试图将句子最精确地切开,适合文本分析

    (2)全模式:把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义

    (3)搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率适合用于搜索引擎分词

    jieba分词过程中主要涉及如下几种算法:

    (1)基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG);

    (2)采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合

    (3)对于未登录词,采用了基于汉字成词能力的 HMM 模型,采用Viterbi 算法进行计算;

    (4)基于Viterbi算法做词性标注

    (5)基于tf-idftextrank模型抽取关键词

    测试代码如下所示:

    # -*- coding: utf-8 -*-
    """
    jieba分词测试
    """
    
    import jieba
    
    
    #全模式
    test1 = jieba.cut("杭州西湖风景很好,是旅游胜地!", cut_all=True)
    print("全模式: " + "| ".join(test1))
    
    #精确模式
    test2 = jieba.cut("杭州西湖风景很好,是旅游胜地!", cut_all=False)
    print("精确模式: " + "| ".join(test2))
    
    #搜索引擎模式
    test3= jieba.cut_for_search("杭州西湖风景很好,是旅游胜地,每年吸引大量前来游玩的游客!")  
    print("搜索引擎模式:" + "| ".join(test3))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    测试结果如下图所示:

    这里写图片描述

    2.2 SnowNLP(github star数 2043)

    SnowNLP是一个python写的类库(https://github.com/isnowfy/snownlp),可以方便的处理中文文本内容,是受到了TextBlob的启发而写的。SnowNLP主要包括如下几个功能:

    (1)中文分词(Character-Based Generative Model);

    (2)词性标注(3-gram HMM);

    (3)情感分析(简单分析,如评价信息);

    (4)文本分类(Naive Bayes)

    (5)转换成拼音(Trie树实现的最大匹配)

    (6)繁简转换(Trie树实现的最大匹配)

    (7)文本关键词文本摘要提取(TextRank算法)

    (8)计算文档词频TF,Term Frequency)和逆向文档频率IDF,Inverse Document Frequency)

    (9)Tokenization(分割成句子)

    (10)文本相似度计算(BM25)

    SnowNLP的最大特点是特别容易上手,用其处理中文文本时能够得到不少有意思的结果,但不少功能比较简单,还有待进一步完善。

    测试代码如下所示:

    # -*- coding: utf-8 -*-
    """
    SnowNLP测试
    """
    
    from snownlp import SnowNLP
    
    s = SnowNLP(u'杭州西湖风景很好,是旅游胜地,每年吸引大量前来游玩的游客!')
    
    #分词
    print(s.words)
    
    
    #情感词性计算
    print("该文本的情感词性为正的概率:" + str(s.sentiments))
    
    text = u'''
    西湖,位于浙江省杭州市西面,是中国大陆首批国家重点风景名胜区和中国十大风景名胜之一。
    它是中国大陆主要的观赏性淡水湖泊之一,也是现今《世界遗产名录》中少数几个和中国唯一一个湖泊类文化遗产。
    西湖三面环山,面积约6.39平方千米,东西宽约2.8千米,南北长约3.2千米,绕湖一周近15千米。
    湖中被孤山、白堤、苏堤、杨公堤分隔,按面积大小分别为外西湖、西里湖、北里湖、小南湖及岳湖等五片水面,
    苏堤、白堤越过湖面,小瀛洲、湖心亭、阮公墩三个小岛鼎立于外西湖湖心,夕照山的雷峰塔与宝石山的保俶塔隔湖相映,
    由此形成了“一山、二塔、三岛、三堤、五湖”的基本格局。
    '''
    
    s2 = SnowNLP(text)
    
    #文本关键词提取
    print(s2.keywords(10))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    测试结果如下图所示:

    这里写图片描述

    2.3 THULAC (github star数 311)

    THULAC(THU Lexical Analyzer for Chinese)由清华大学自然语言处理与社会人文计算实验室研制推出的一套中文词法分析工具包(github链接:https://github.com/thunlp/THULAC-Python),具有中文分词词性标注功能。THULAC具有如下几个特点:

    (1)能力强。利用我们集成的目前世界上规模最大的人工分词和词性标注中文语料库(约含5800万字)训练而成,模型标注能力强大

    (2)准确率高。该工具包在标准数据集Chinese Treebank(CTB5)上分词的F1值可达97.3%,词性标注的F1值可达到92.9%,与该数据集上最好方法效果相当。

    (3)速度较快。同时进行分词和词性标注速度为300KB/s,每秒可处理约15万字。只进行分词速度可达到1.3MB/s。

    THU词性标记集(通用版)如下所示:

    n/名词 np/人名 ns/地名 ni/机构名 nz/其它专名
    m/数词 q/量词 mq/数量词 t/时间词 f/方位词 s/处所词
    v/动词 a/形容词 d/副词 h/前接成分 k/后接成分 i/习语 
    j/简称 r/代词 c/连词 p/介词 u/助词 y/语气助词
    e/叹词 o/拟声词 g/语素 w/标点 x/其它
    • 1
    • 2
    • 3
    • 4
    • 5

    测试代码(python版)如下所示:

    # -*- coding: utf-8 -*-
    """
    THULAC 分词测试
    """
    
    import thulac   
    
    #默认模式,分词的同时进行词性标注
    test1 = thulac.thulac()
    text1 = test1.cut("杭州西湖风景很好,是旅游胜地!")
    print(text1)
    
    
    #只进行分词
    test2 = thulac.thulac(seg_only=True)
    text2 = test2.cut("杭州西湖风景很好,是旅游胜地!")
    print(text2)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试结果如下图所示:

    这里写图片描述

    2.4 NLPIR (github star数 811)

    NLPIR分词系统(前身为2000年发布的ICTCLAS词法分析系统,gtihub链接:https://github.com/NLPIR-team/NLPIR),是由北京理工大学张华平博士研发的中文分词系统,经过十余年的不断完善,拥有丰富的功能和强大的性能。NLPIR是一整套对原始文本集进行处理和加工的软件,提供了中间件处理效果的可视化展示,也可以作为小规模数据的处理加工工具。主要功能包括:中文分词词性标注命名实体识别用户词典新词发现关键词提取等功能。本文测试所采用的是PyNLPIRNLPIRPython版本,github链接:https://github.com/tsroten/pynlpir

    测试代码如下所示:

    # -*- coding: utf-8 -*-
    """
    PYNLPIR 分词测试
    """
    
    import pynlpir
    
    
    #打开分词器
    pynlpir.open()
    
    text1 = "杭州西湖风景很好,是旅游胜地,每年吸引大量前来游玩的游客!" 
    
    #分词,默认打开分词和词性标注功能
    test1 = pynlpir.segment(text1)
    #print(test1)
    print('1.默认分词模式:\n' + str(test1))
    
    #将词性标注语言变更为汉语
    test2 = pynlpir.segment(text1,pos_english=False)
    print('2.汉语标注模式:\n' + str(test2))
    
    
    #关闭词性标注
    test3 = pynlpir.segment(text1,pos_tagging=False)
    print('3.无词性标注模式:\n' + str(test3))
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    测试结果如下图所示:

    这里写图片描述


    展开全文
  • 整理停用词 去空行和两边的空格#encoding=utf-8 filename = "stop_words.txt"f = open(filename,"r",encoding='utf-8') result = list() for line in f.readlines(): line = line.strip() if not len(line): ...

    整理停用词 去空行和两边的空格

    #encoding=utf-8
    filename = "stop_words.txt"
    
    f = open(filename,"r",encoding='utf-8')
    result = list()
    for line in f.readlines():
        line = line.strip()
        if not len(line):
            continue
    
        result.append(line)
    f.close
    with open("stop_words2.txt","w",encoding='utf-8') as fw:
        for sentence in result:
            sentence.encode('utf-8')
            data=sentence.strip()  
            if len(data)!=0:  
                fw.write(data)
                fw.write("\n") 
    print ("end")
    

    分词、停用词过滤(包括标点)

    #encoding=utf-8
    import jieba
    filename = "../data/1000页洗好2.txt"
    stopwords_file = "../data/stop_words2.txt"
    
    stop_f = open(stopwords_file,"r",encoding='utf-8')
    stop_words = list()
    for line in stop_f.readlines():
        line = line.strip()
        if not len(line):
            continue
    
        stop_words.append(line)
    stop_f.close
    
    print(len(stop_words))
    
    f = open(filename,"r",encoding='utf-8')
    result = list()
    for line in f.readlines():
        line = line.strip()
        if not len(line):
            continue
        outstr = '' 
        seg_list = jieba.cut(line,cut_all=False) 
        for word in seg_list:  
            if word not in stop_words:  
                if word != '\t':  
                    outstr += word 
                    outstr += " "  
       # seg_list = " ".join(seg_list)
        result.append(outstr.strip())
    f.close
    
    with open("../data/test2.txt","w",encoding='utf-8') as fw:
        for sentence in result:
            sentence.encode('utf-8')
            data=sentence.strip()  
            if len(data)!=0:  
                fw.write(data)
                fw.write("\n") 
    
    
    print ("end")
    
    
    '''
    seg_list = jieba.cut("工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作",cut_all=False)
    seg_list = "/".join(seg_list)
    print (seg_list)
    '''

    训练词向量(word2vec)

    #encoding=utf-8
    from gensim.models import word2vec
    import sys
    sentences=word2vec.Text8Corpus(u'e:/workspace/Word2Vec/data/test2.txt')
    model=word2vec.Word2Vec(sentences, size=10)
    for i in model.most_similar(u"明凯",topn=20):
        print (i[0],i[1])
    

    tf-idf和textrank获取关键词:

    from jieba import analyse
    # 引入TF-IDF关键词抽取接口
    tfidf = analyse.extract_tags
    textrank = analyse.textrank
    
    filename = "e:/workspace/Word2Vec/data/test2.txt"
    # 基于TF-IDF算法进行关键词抽取
    content = open(filename, 'rb').read()
    #keywords = tfidf(content)
    #print ("keywords by tfidf:")
    # 输出抽取出的关键词
    #for keyword in keywords:
    #    print (keyword + "/")
    
    
    
    
    
    print ("\nkeywords by textrank:")
    # 基于TextRank算法进行关键词抽取
    keywords = textrank(content)
    # 输出抽取出的关键词
    for keyword in keywords:
        print (keyword)    
    print("end")

    词频

    import collections  
    #coding=utf-8
    filename = "e:/workspace/Word2Vec/data/test2.txt"
    with open (filename,'rb') as f:  
        words_box=[]
        words_box2=[]  
        for line in f:   
            line.decode("utf-8")
            words_box.extend(line.strip().split())
        for word in words_box:
            word2 = word.decode("utf-8")
            words_box2.append(word2)
    print("词的总数为:%s"%len(words_box2))
    print("词频结果:%s"%collections.Counter(words_box2))  
    
    

    训练词向量(Word2vec):

    #encoding=utf-8
    from gensim.models import word2vec
    import sys
    sentences=word2vec.Text8Corpus(u'e:/workspace/Word2Vec/data/test2.txt')
    model=word2vec.Word2Vec(sentences, size=10)
    for i in model.most_similar(u"明凯",topn=20):
        print (i[0],i[1])
    

    停用词表(1893个):

    from:http://blog.csdn.net/shijiebei2009/article/details/39696571

    !  
    "  
    #  
    $  
    %  
    &  
    '  
    (  
    )  
    *  
    +  
    ,  
    -  
    --  
    .  
    ..  
    ...  
    ......  
    ...................  
    ./  
    .一  
    .数  
    .日  
    /  
    //  
    0  
    1  
    2  
    3  
    4  
    5  
    6  
    7  
    8  
    9  
    :  
    ://  
    ::  
    ;  
    <  
    =  
    >  
    >>  
    ?  
    @  
    A  
    Lex  
    [  
    \  
    ]  
    ^  
    _  
    `  
    exp  
    sub  
    sup  
    |  
    }  
    ~  
    ~~~~  
    ·  
    ×  
    ×××  
    Δ  
    Ψ  
    γ  
    μ  
    φ  
    φ.  
    В  
    —  
    ——  
    ———  
    ‘  
    ’  
    ’‘  
    “  
    ”  
    ”,  
    …  
    ……  
    …………………………………………………③  
    ′∈  
    ′|  
    ℃  
    Ⅲ  
    ↑  
    →  
    ∈[  
    ∪φ∈  
    ≈  
    ①  
    ②  
    ②c  
    ③  
    ③]  
    ④  
    ⑤  
    ⑥  
    ⑦  
    ⑧  
    ⑨  
    ⑩  
    ──  
    ■  
    ▲  
       
    、  
    。  
    〈  
    〉  
    《  
    》  
    》),  
    」  
    『  
    』  
    【  
    】  
    〔  
    〕  
    〕〔  
    ㈧  
    一  
    一.  
    一一  
    一下  
    一个  
    一些  
    一何  
    一切  
    一则  
    一则通过  
    一天  
    一定  
    一方面  
    一旦  
    一时  
    一来  
    一样  
    一次  
    一片  
    一番  
    一直  
    一致  
    一般  
    一起  
    一转眼  
    一边  
    一面  
    七  
    万一  
    三  
    三天两头  
    三番两次  
    三番五次  
    上  
    上下  
    上升  
    上去  
    上来  
    上述  
    上面  
    下  
    下列  
    下去  
    下来  
    下面  
    不  
    不一  
    不下  
    不久  
    不了  
    不亦乐乎  
    不仅  
    不仅...而且  
    不仅仅  
    不仅仅是  
    不会  
    不但  
    不但...而且  
    不光  
    不免  
    不再  
    不力  
    不单  
    不变  
    不只  
    不可  
    不可开交  
    不可抗拒  
    不同  
    不外  
    不外乎  
    不够  
    不大  
    不如  
    不妨  
    不定  
    不对  
    不少  
    不尽  
    不尽然  
    不巧  
    不已  
    不常  
    不得  
    不得不  
    不得了  
    不得已  
    不必  
    不怎么  
    不怕  
    不惟  
    不成  
    不拘  
    不择手段  
    不敢  
    不料  
    不断  
    不日  
    不时  
    不是  
    不曾  
    不止  
    不止一次  
    不比  
    不消  
    不满  
    不然  
    不然的话  
    不特  
    不独  
    不由得  
    不知不觉  
    不管  
    不管怎样  
    不经意  
    不胜  
    不能  
    不能不  
    不至于  
    不若  
    不要  
    不论  
    不起  
    不足  
    不过  
    不迭  
    不问  
    不限  
    与  
    与其  
    与其说  
    与否  
    与此同时  
    专门  
    且  
    且不说  
    且说  
    两者  
    严格  
    严重  
    个  
    个人  
    个别  
    中小  
    中间  
    丰富  
    串行  
    临  
    临到  
    为  
    为主  
    为了  
    为什么  
    为什麽  
    为何  
    为止  
    为此  
    为着  
    主张  
    主要  
    举凡  
    举行  
    乃  
    乃至  
    乃至于  
    么  
    之  
    之一  
    之前  
    之后  
    之後  
    之所以  
    之类  
    乌乎  
    乎  
    乒  
    乘  
    乘势  
    乘机  
    乘胜  
    乘虚  
    乘隙  
    九  
    也  
    也好  
    也就是说  
    也是  
    也罢  
    了  
    了解  
    争取  
    二  
    二来  
    二话不说  
    二话没说  
    于  
    于是  
    于是乎  
    云云  
    云尔  
    互  
    互相  
    五  
    些  
    交口  
    亦  
    产生  
    亲口  
    亲手  
    亲眼  
    亲自  
    亲身  
    人  
    人人  
    人们  
    人家  
    人民  
    什么  
    什么样  
    什麽  
    仅  
    仅仅  
    今  
    今后  
    今天  
    今年  
    今後  
    介于  
    仍  
    仍旧  
    仍然  
    从  
    从不  
    从严  
    从中  
    从事  
    从今以后  
    从优  
    从古到今  
    从古至今  
    从头  
    从宽  
    从小  
    从新  
    从无到有  
    从早到晚  
    从未  
    从来  
    从此  
    从此以后  
    从而  
    从轻  
    从速  
    从重  
    他  
    他人  
    他们  
    他是  
    他的  
    代替  
    以  
    以上  
    以下  
    以为  
    以便  
    以免  
    以前  
    以及  
    以后  
    以外  
    以後  
    以故  
    以期  
    以来  
    以至  
    以至于  
    以致  
    们  
    任  
    任何  
    任凭  
    任务  
    企图  
    伙同  
    会  
    伟大  
    传  
    传说  
    传闻  
    似乎  
    似的  
    但  
    但凡  
    但愿  
    但是  
    何  
    何乐而不为  
    何以  
    何况  
    何处  
    何妨  
    何尝  
    何必  
    何时  
    何止  
    何苦  
    何须  
    余外  
    作为  
    你  
    你们  
    你是  
    你的  
    使  
    使得  
    使用  
    例如  
    依  
    依据  
    依照  
    依靠  
    便  
    便于  
    促进  
    保持  
    保管  
    保险  
    俺  
    俺们  
    倍加  
    倍感  
    倒不如  
    倒不如说  
    倒是  
    倘  
    倘使  
    倘或  
    倘然  
    倘若  
    借  
    借以  
    借此  
    假使  
    假如  
    假若  
    偏偏  
    做到  
    偶尔  
    偶而  
    傥然  
    像  
    儿  
    允许  
    元/吨  
    充其极  
    充其量  
    充分  
    先不先  
    先后  
    先後  
    先生  
    光  
    光是  
    全体  
    全力  
    全年  
    全然  
    全身心  
    全部  
    全都  
    全面  
    八  
    八成  
    公然  
    六  
    兮  
    共  
    共同  
    共总  
    关于  
    其  
    其一  
    其中  
    其二  
    其他  
    其余  
    其后  
    其它  
    其实  
    其次  
    具体  
    具体地说  
    具体来说  
    具体说来  
    具有  
    兼之  
    内  
    再  
    再其次  
    再则  
    再有  
    再次  
    再者  
    再者说  
    再说  
    冒  
    冲  
    决不  
    决定  
    决非  
    况且  
    准备  
    凑巧  
    凝神  
    几  
    几乎  
    几度  
    几时  
    几番  
    几经  
    凡  
    凡是  
    凭  
    凭借  
    出  
    出于  
    出去  
    出来  
    出现  
    分别  
    分头  
    分期  
    分期分批  
    切  
    切不可  
    切切  
    切勿  
    切莫  
    则  
    则甚  
    刚  
    刚好  
    刚巧  
    刚才  
    初  
    别  
    别人  
    别处  
    别是  
    别的  
    别管  
    别说  
    到  
    到了儿  
    到处  
    到头  
    到头来  
    到底  
    到目前为止  
    前后  
    前此  
    前者  
    前进  
    前面  
    加上  
    加之  
    加以  
    加入  
    加强  
    动不动  
    动辄  
    勃然  
    匆匆  
    十分  
    千  
    千万  
    千万千万  
    半  
    单  
    单单  
    单纯  
    即  
    即令  
    即使  
    即便  
    即刻  
    即如  
    即将  
    即或  
    即是说  
    即若  
    却  
    却不  
    历  
    原来  
    去  
    又  
    又及  
    及  
    及其  
    及时  
    及至  
    双方  
    反之  
    反之亦然  
    反之则  
    反倒  
    反倒是  
    反应  
    反手  
    反映  
    反而  
    反过来  
    反过来说  
    取得  
    取道  
    受到  
    变成  
    古来  
    另  
    另一个  
    另一方面  
    另外  
    另悉  
    另方面  
    另行  
    只  
    只当  
    只怕  
    只是  
    只有  
    只消  
    只要  
    只限  
    叫  
    叫做  
    召开  
    叮咚  
    叮当  
    可  
    可以  
    可好  
    可是  
    可能  
    可见  
    各  
    各个  
    各人  
    各位  
    各地  
    各式  
    各种  
    各级  
    各自  
    合理  
    同  
    同一  
    同时  
    同样  
    后  
    后来  
    后者  
    后面  
    向  
    向使  
    向着  
    吓  
    吗  
    否则  
    吧  
    吧哒  
    吱  
    呀  
    呃  
    呆呆地  
    呐  
    呕  
    呗  
    呜  
    呜呼  
    呢  
    周围  
    呵  
    呵呵  
    呸  
    呼哧  
    呼啦  
    咋  
    和  
    咚  
    咦  
    咧  
    咱  
    咱们  
    咳  
    哇  
    哈  
    哈哈  
    哉  
    哎  
    哎呀  
    哎哟  
    哗  
    哗啦  
    哟  
    哦  
    哩  
    哪  
    哪个  
    哪些  
    哪儿  
    哪天  
    哪年  
    哪怕  
    哪样  
    哪边  
    哪里  
    哼  
    哼唷  
    唉  
    唯有  
    啊  
    啊呀  
    啊哈  
    啊哟  
    啐  
    啥  
    啦  
    啪达  
    啷当  
    喀  
    喂  
    喏  
    喔唷  
    喽  
    嗡  
    嗡嗡  
    嗬  
    嗯  
    嗳  
    嘎  
    嘎嘎  
    嘎登  
    嘘  
    嘛  
    嘻  
    嘿  
    嘿嘿  
    四  
    因  
    因为  
    因了  
    因此  
    因着  
    因而  
    固  
    固然  
    在  
    在下  
    在于  
    地  
    均  
    坚决  
    坚持  
    基于  
    基本  
    基本上  
    处在  
    处处  
    处理  
    复杂  
    多  
    多么  
    多亏  
    多多  
    多多少少  
    多多益善  
    多少  
    多年前  
    多年来  
    多数  
    多次  
    够瞧的  
    大  
    大不了  
    大举  
    大事  
    大体  
    大体上  
    大凡  
    大力  
    大多  
    大多数  
    大大  
    大家  
    大张旗鼓  
    大批  
    大抵  
    大概  
    大略  
    大约  
    大致  
    大都  
    大量  
    大面儿上  
    失去  
    奇  
    奈  
    奋勇  
    她  
    她们  
    她是  
    她的  
    好  
    好在  
    好的  
    好象  
    如  
    如上  
    如上所述  
    如下  
    如今  
    如何  
    如其  
    如前所述  
    如同  
    如常  
    如是  
    如期  
    如果  
    如次  
    如此  
    如此等等  
    如若  
    始而  
    姑且  
    存在  
    存心  
    孰料  
    孰知  
    宁  
    宁可  
    宁愿  
    宁肯  
    它  
    它们  
    它们的  
    它是  
    它的  
    安全  
    完全  
    完成  
    定  
    实现  
    实际  
    宣布  
    容易  
    密切  
    对  
    对于  
    对应  
    对待  
    对方  
    对比  
    将  
    将才  
    将要  
    将近  
    小  
    少数  
    尔  
    尔后  
    尔尔  
    尔等  
    尚且  
    尤其  
    就  
    就地  
    就是  
    就是了  
    就是说  
    就此  
    就算  
    就要  
    尽  
    尽可能  
    尽如人意  
    尽心尽力  
    尽心竭力  
    尽快  
    尽早  
    尽然  
    尽管  
    尽管如此  
    尽量  
    局外  
    居然  
    届时  
    属于  
    屡  
    屡屡  
    屡次  
    屡次三番  
    岂  
    岂但  
    岂止  
    岂非  
    川流不息  
    左右  
    巨大  
    巩固  
    差一点  
    差不多  
    己  
    已  
    已矣  
    已经  
    巴  
    巴巴  
    带  
    帮助  
    常  
    常常  
    常言说  
    常言说得好  
    常言道  
    平素  
    年复一年  
    并  
    并不  
    并不是  
    并且  
    并排  
    并无  
    并没  
    并没有  
    并肩  
    并非  
    广大  
    广泛  
    应当  
    应用  
    应该  
    庶乎  
    庶几  
    开外  
    开始  
    开展  
    引起  
    弗  
    弹指之间  
    强烈  
    强调  
    归  
    归根到底  
    归根结底  
    归齐  
    当  
    当下  
    当中  
    当儿  
    当前  
    当即  
    当口儿  
    当地  
    当场  
    当头  
    当庭  
    当时  
    当然  
    当真  
    当着  
    形成  
    彻夜  
    彻底  
    彼  
    彼时  
    彼此  
    往  
    往往  
    待  
    待到  
    很  
    很多  
    很少  
    後来  
    後面  
    得  
    得了  
    得出  
    得到  
    得天独厚  
    得起  
    心里  
    必  
    必定  
    必将  
    必然  
    必要  
    必须  
    快  
    快要  
    忽地  
    忽然  
    怎  
    怎么  
    怎么办  
    怎么样  
    怎奈  
    怎样  
    怎麽  
    怕  
    急匆匆  
    怪  
    怪不得  
    总之  
    总是  
    总的来看  
    总的来说  
    总的说来  
    总结  
    总而言之  
    恍然  
    恐怕  
    恰似  
    恰好  
    恰如  
    恰巧  
    恰恰  
    恰恰相反  
    恰逢  
    您  
    您们  
    您是  
    惟其  
    惯常  
    意思  
    愤然  
    愿意  
    慢说  
    成为  
    成年  
    成年累月  
    成心  
    我  
    我们  
    我是  
    我的  
    或  
    或则  
    或多或少  
    或是  
    或曰  
    或者  
    或许  
    战斗  
    截然  
    截至  
    所  
    所以  
    所在  
    所幸  
    所有  
    所谓  
    才  
    才能  
    扑通  
    打  
    打从  
    打开天窗说亮话  
    扩大  
    把  
    抑或  
    抽冷子  
    拦腰  
    拿  
    按  
    按时  
    按期  
    按照  
    按理  
    按说  
    挨个  
    挨家挨户  
    挨次  
    挨着  
    挨门挨户  
    挨门逐户  
    换句话说  
    换言之  
    据  
    据实  
    据悉  
    据我所知  
    据此  
    据称  
    据说  
    掌握  
    接下来  
    接着  
    接著  
    接连不断  
    放量  
    故  
    故意  
    故此  
    故而  
    敞开儿  
    敢  
    敢于  
    敢情  
    数/  
    整个  
    断然  
    方  
    方便  
    方才  
    方能  
    方面  
    旁人  
    无  
    无宁  
    无法  
    无论  
    既  
    既...又  
    既往  
    既是  
    既然  
    日复一日  
    日渐  
    日益  
    日臻  
    日见  
    时候  
    昂然  
    明显  
    明确  
    是  
    是不是  
    是以  
    是否  
    是的  
    显然  
    显著  
    普通  
    普遍  
    暗中  
    暗地里  
    暗自  
    更  
    更为  
    更加  
    更进一步  
    曾  
    曾经  
    替  
    替代  
    最  
    最后  
    最大  
    最好  
    最後  
    最近  
    最高  
    有  
    有些  
    有关  
    有利  
    有力  
    有及  
    有所  
    有效  
    有时  
    有点  
    有的  
    有的是  
    有着  
    有著  
    望  
    朝  
    朝着  
    末##末  
    本  
    本人  
    本地  
    本着  
    本身  
    权时  
    来  
    来不及  
    来得及  
    来看  
    来着  
    来自  
    来讲  
    来说  
    极  
    极为  
    极了  
    极其  
    极力  
    极大  
    极度  
    极端  
    构成  
    果然  
    果真  
    某  
    某个  
    某些  
    某某  
    根据  
    根本  
    格外  
    梆  
    概  
    次第  
    欢迎  
    欤  
    正值  
    正在  
    正如  
    正巧  
    正常  
    正是  
    此  
    此中  
    此后  
    此地  
    此处  
    此外  
    此时  
    此次  
    此间  
    殆  
    毋宁  
    每  
    每个  
    每天  
    每年  
    每当  
    每时每刻  
    每每  
    每逢  
    比  
    比及  
    比如  
    比如说  
    比方  
    比照  
    比起  
    比较  
    毕竟  
    毫不  
    毫无  
    毫无例外  
    毫无保留地  
    汝  
    沙沙  
    没  
    没奈何  
    没有  
    沿  
    沿着  
    注意  
    活  
    深入  
    清楚  
    满  
    满足  
    漫说  
    焉  
    然  
    然则  
    然后  
    然後  
    然而  
    照  
    照着  
    牢牢  
    特别是  
    特殊  
    特点  
    犹且  
    犹自  
    独  
    独自  
    猛然  
    猛然间  
    率尔  
    率然  
    现代  
    现在  
    理应  
    理当  
    理该  
    瑟瑟  
    甚且  
    甚么  
    甚或  
    甚而  
    甚至  
    甚至于  
    用  
    用来  
    甫  
    甭  
    由  
    由于  
    由是  
    由此  
    由此可见  
    略  
    略为  
    略加  
    略微  
    白  
    白白  
    的  
    的确  
    的话  
    皆可  
    目前  
    直到  
    直接  
    相似  
    相信  
    相反  
    相同  
    相对  
    相对而言  
    相应  
    相当  
    相等  
    省得  
    看  
    看上去  
    看出  
    看到  
    看来  
    看样子  
    看看  
    看见  
    看起来  
    真是  
    真正  
    眨眼  
    着  
    着呢  
    矣  
    矣乎  
    矣哉  
    知道  
    砰  
    确定  
    碰巧  
    社会主义  
    离  
    种  
    积极  
    移动  
    究竟  
    穷年累月  
    突出  
    突然  
    窃  
    立  
    立刻  
    立即  
    立地  
    立时  
    立马  
    竟  
    竟然  
    竟而  
    第  
    第二  
    等  
    等到  
    等等  
    策略地  
    简直  
    简而言之  
    简言之  
    管  
    类如  
    粗  
    精光  
    紧接着  
    累年  
    累次  
    纯  
    纯粹  
    纵  
    纵令  
    纵使  
    纵然  
    练习  
    组成  
    经  
    经常  
    经过  
    结合  
    结果  
    给  
    绝  
    绝不  
    绝对  
    绝非  
    绝顶  
    继之  
    继后  
    继续  
    继而  
    维持  
    综上所述  
    缕缕  
    罢了  
    老  
    老大  
    老是  
    老老实实  
    考虑  
    者  
    而  
    而且  
    而况  
    而又  
    而后  
    而外  
    而已  
    而是  
    而言  
    而论  
    联系  
    联袂  
    背地里  
    背靠背  
    能  
    能否  
    能够  
    腾  
    自  
    自个儿  
    自从  
    自各儿  
    自后  
    自家  
    自己  
    自打  
    自身  
    臭  
    至  
    至于  
    至今  
    至若  
    致  
    般的  
    良好  
    若  
    若夫  
    若是  
    若果  
    若非  
    范围  
    莫  
    莫不  
    莫不然  
    莫如  
    莫若  
    莫非  
    获得  
    藉以  
    虽  
    虽则  
    虽然  
    虽说  
    蛮  
    行为  
    行动  
    表明  
    表示  
    被  
    要  
    要不  
    要不是  
    要不然  
    要么  
    要是  
    要求  
    见  
    规定  
    觉得  
    譬喻  
    譬如  
    认为  
    认真  
    认识  
    让  
    许多  
    论  
    论说  
    设使  
    设或  
    设若  
    诚如  
    诚然  
    话说  
    该  
    该当  
    说明  
    说来  
    说说  
    请勿  
    诸  
    诸位  
    诸如  
    谁  
    谁人  
    谁料  
    谁知  
    谨  
    豁然  
    贼死  
    赖以  
    赶  
    赶快  
    赶早不赶晚  
    起  
    起先  
    起初  
    起头  
    起来  
    起见  
    起首  
    趁  
    趁便  
    趁势  
    趁早  
    趁机  
    趁热  
    趁着  
    越是  
    距  
    跟  
    路经  
    转动  
    转变  
    转贴  
    轰然  
    较  
    较为  
    较之  
    较比  
    边  
    达到  
    达旦  
    迄  
    迅速  
    过  
    过于  
    过去  
    过来  
    运用  
    近  
    近几年来  
    近年来  
    近来  
    还  
    还是  
    还有  
    还要  
    这  
    这一来  
    这个  
    这么  
    这么些  
    这么样  
    这么点儿  
    这些  
    这会儿  
    这儿  
    这就是说  
    这时  
    这样  
    这次  
    这点  
    这种  
    这般  
    这边  
    这里  
    这麽  
    进入  
    进去  
    进来  
    进步  
    进而  
    进行  
    连  
    连同  
    连声  
    连日  
    连日来  
    连袂  
    连连  
    迟早  
    迫于  
    适应  
    适当  
    适用  
    逐步  
    逐渐  
    通常  
    通过  
    造成  
    逢  
    遇到  
    遭到  
    遵循  
    遵照  
    避免  
    那  
    那个  
    那么  
    那么些  
    那么样  
    那些  
    那会儿  
    那儿  
    那时  
    那末  
    那样  
    那般  
    那边  
    那里  
    那麽  
    部分  
    都  
    鄙人  
    采取  
    里面  
    重大  
    重新  
    重要  
    鉴于  
    针对  
    长期以来  
    长此下去  
    长线  
    长话短说  
    问题  
    间或  
    防止  
    阿  
    附近  
    陈年  
    限制  
    陡然  
    除  
    除了  
    除却  
    除去  
    除外  
    除开  
    除此  
    除此之外  
    除此以外  
    除此而外  
    除非  
    随  
    随后  
    随时  
    随着  
    随著  
    隔夜  
    隔日  
    难得  
    难怪  
    难说  
    难道  
    难道说  
    集中  
    零  
    需要  
    非但  
    非常  
    非徒  
    非得  
    非特  
    非独  
    靠  
    顶多  
    顷  
    顷刻  
    顷刻之间  
    顷刻间  
    顺  
    顺着  
    顿时  
    颇  
    风雨无阻  
    饱  
    首先  
    马上  
    高低  
    高兴  
    默然  
    默默地  
    齐  
    ︿  
    !  
    #  
    $  
    %  
    &  
    '  
    (  
    )  
    )÷(1-  
    )、  
    *  
    +  
    +ξ  
    ++  
    ,  
    ,也  
    -  
    -β  
    --  
    -[*]-  
    .  
    /  
    0  
    0:2  
    1  
    1.  
    12%  
    2  
    2.3%  
    3  
    4  
    5  
    5:0  
    6  
    7  
    8  
    9  
    :  
    ;  
    <  
    <±  
    <Δ  
    <λ  
    <φ  
    <<  
    =  
    =″  
    =☆  
    =(  
    =-  
    =[  
    ={  
    >  
    >λ  
    ?  
    @  
    A  
    LI  
    R.L.  
    ZXFITL  
    [  
    [①①]  
    [①②]  
    [①③]  
    [①④]  
    [①⑤]  
    [①⑥]  
    [①⑦]  
    [①⑧]  
    [①⑨]  
    [①A]  
    [①B]  
    [①C]  
    [①D]  
    [①E]  
    [①]  
    [①a]  
    [①c]  
    [①d]  
    [①e]  
    [①f]  
    [①g]  
    [①h]  
    [①i]  
    [①o]  
    [②  
    [②①]  
    [②②]  
    [②③]  
    [②④  
    [②⑤]  
    [②⑥]  
    [②⑦]  
    [②⑧]  
    [②⑩]  
    [②B]  
    [②G]  
    [②]  
    [②a]  
    [②b]  
    [②c]  
    [②d]  
    [②e]  
    [②f]  
    [②g]  
    [②h]  
    [②i]  
    [②j]  
    [③①]  
    [③⑩]  
    [③F]  
    [③]  
    [③a]  
    [③b]  
    [③c]  
    [③d]  
    [③e]  
    [③g]  
    [③h]  
    [④]  
    [④a]  
    [④b]  
    [④c]  
    [④d]  
    [④e]  
    [⑤]  
    [⑤]]  
    [⑤a]  
    [⑤b]  
    [⑤d]  
    [⑤e]  
    [⑤f]  
    [⑥]  
    [⑦]  
    [⑧]  
    [⑨]  
    [⑩]  
    [*]  
    [-  
    []  
    ]  
    ]∧′=[  
    ][  
    _  
    a]  
    b]  
    c]  
    e]  
    f]  
    ng昉  
    {  
    {-  
    |  
    }  
    }>  
    ~  
    ~±  
    ~+  
    ¥  
    展开全文
  • 干货 | 史上最全中文分词工具整理

    万次阅读 多人点赞 2019-05-22 17:09:04
    作者 |fendouai 一.中文分词 分词服务接口列表 ...二....THULAC:与代表性分词软件的性能对比 ...我们选择LTP-3.2.0、ICTCLAS...我们选择Windows作为测试环境,根据第二届国际汉语分词测评(The SecondInternational ...

    作者 | fendouai

     

    一.中文分词

     分词服务接口列表

     

    二.准确率评测:

    THULAC:与代表性分词软件的性能对比

     

    我们选择LTP-3.2.0 、ICTCLAS(2015版) 、jieba(C++版)等国内具代表性的分词软件与THULAC做性能比较。我们选择Windows作为测试环境,根据第二届国际汉语分词测评(The SecondInternational Chinese Word Segmentation Bakeoff)发布的国际中文分词测评标准,对不同软件进行了速度和准确率测试。

     

    在第二届国际汉语分词测评中,共有四家单位提供的测试语料(Academia Sinica、 City University 、Peking University 、MicrosoftResearch), 在评测提供的资源icwb2-data中包含了来自这四家单位的训练集(training)、测试集(testing), 以及根据各自分词标准而提供的相应测试集的标准答案(icwb2-data/scripts/gold).在icwb2-data/scripts目录下含有对分词进行自动评分的perl脚本score。

     

    我们在统一测试环境下,对上述流行分词软件和THULAC进行了测试,使用的模型为各分词软件自带模型。THULAC使用的是随软件提供的简单模型Model_1。评测环境为 Intel Core i5 2.4 GHz 评测结果如下:

    评测结果1

     

    除了以上在标准测试集上的评测,我们也对各个分词工具在大数据上的速度进行了评测,结果如下:

     

    CNKI_journal.txt(51 MB)

    评测结果2

     

    分词数据准备及评测由BosonNLP完成:11 款开放中文分词引擎大比拼(2015年发布)

     

    分词的客观量化测试离不开标注数据,即人工所准备的分词“标准答案”。在数据源方面,我们将测试分为: 1.新闻数据:140篇,共30517词语; 2.微博数据:200篇,共12962词语; 3.汽车论坛数据(汽车之家)100篇:共27452词语; 4.餐饮点评数据(大众点评):100条,共8295词语。

     

    准确度计算规则:

    将所有标点符号去除,不做比较

    参与测试的部分系统进行了实体识别,可能造成词语认定的不统一。我们将对应位置替换成了人工标注的结果,得到准确率估算的上界。

    经过以上处理,用SIGHAN 分词评分脚本比较得到最终的准确率,召回率和F1值。

    以上所有数据采用北大现代汉语基本加工规范对所有数据进行分词作为标准。具体数据下载地址请参见附录。通过这四类数据综合对比不同分词系统的分词准确度。

    不同分词系统的分词准确度对比

     

    三.付费价格:

    阿里云:

     阿里云付费价格

     

    腾讯云:

    腾讯云付费价格

     

    玻森中文

    免费额度:

     玻森中文免费额度

     

    付费价格:

     玻森中文付费价格

     

    四.官网

    开源工具

    HanLP:

    https://github.com/hankcs/HanLP

    结巴分词:

    https://github.com/fxsjy/jieba

    盘古分词:

    http://pangusegment.codeplex.com/

    庖丁解牛:

    https://code.google.com/p/paoding/

    SCWS中文分词:

    http://www.xunsearch.com/scws/docs.php

     

    高校工具

    FudanNLP:

    https://github.com/FudanNLP/fnlp

    LTP:

    http://www.ltp-cloud.com/document

    THULAC:

    http://thulac.thunlp.org/

    NLPIR:

    http://ictclas.nlpir.org/docs

     

    商业服务

    BosonNLP:

    http://bosonnlp.com/dev/center   

    百度NLP:

    https://cloud.baidu.com/doc/NLP/NLP-API.html

    搜狗分词:

    http://www.sogou.com/labs/webservice/

    腾讯文智:

    https://cloud.tencent.com/document/product/271/2071

    腾讯价格单:

    https://cloud.tencent.com/document/product/271/1140

    阿里云NLP:

    https://data.aliyun.com/product/nlp

    新浪云:

    http://www.sinacloud.com/doc/sae/python/segment.html

     

    测试数据集

    1、SIGHANBakeoff 2005 MSR, 560KB 

    http://sighan.cs.uchicago.edu/bakeoff2005/

    2、SIGHANBakeoff 2005 PKU, 510KB 

    http://sighan.cs.uchicago.edu/bakeoff2005/

    3、人民日报 2014,65MB 

    https://pan.baidu.com/s/1hq3KKXe

     

    前两个数据集是SIGHAN于2005年组织的中文分词比赛所用的数据集,也是学术界测试分词工具的标准数据集,本文用于测试各大分词工具的准确性,而最后一个数据集规模较大,用于测试分词速度。

     

    磐创AI:http://www.panchuangai.com/

    TensorFlowNews:http://www.tensorflownews.com/

    展开全文
  • 中文分词方法

    千次阅读 2019-05-23 11:36:57
    title: “中文分词方法的比较” author: p01son6415 词条化 分词又叫做词条化(tokenlize),指的是将原始的字符流转换成一个一个词条(token)的过程。词条化属于自然语言处理中预处理的一个步骤,它是分析语义的...
  • 分词

    千次阅读 2018-09-07 20:41:14
    对于西方拼音语言来说,从词之间由明确的分界符,而很多亚洲语言(如汉语、日语、韩语、泰语)词之间没有明确的分界符,因此需要先对句子进行分词,才能做进一步的自然语言处理(也适用于英文词组的分割、或者手写...
  • NLP|中文分词技术及应用

    万次阅读 多人点赞 2018-05-25 23:36:00
    摘要:中文分词是中文信息处理的重要基础,本文详细阐述了目前主要的几种中文分词算法的技术原理 、中文分词目前的瓶颈和评价准则,以及中文分词的具体应用。中文分词指将一个汉字序列切分成一个个单独的词。现有的...
  • 常用分词方法总结分析

    万次阅读 2015-01-28 18:29:44
    1.中文分词 中文句子是由字组成的连续字符串。为了理解中文语义,首先需要将句子划分为以词为基本单位的词串,这就是中文分词。词是最小的能够独立活动的有意义的语言成分,英文单词之间是以空格作为自然分界符的,...
  • 上一篇我们讲了N一最短路径方法、基于词的n元文法模型,本节将主要介绍由字构词方法、基于词感知机算法的汉语分词方法、基于字的生成模型和区分式模型相结合的汉语分词方法,下面我们就开始讲解由字构词的方法: ...
  • NLP --- 分词详解(分词的历史)

    千次阅读 2018-12-24 15:10:36
    前面的内容我们以算法为主,主要讲解了HMM和CRF算法,为了解决HMM的问题,使用了EM算法,但是整个HMM算法是产生式模型的,计算量大和复杂,因此为了解决这个问题,我们引入了CRF算法,该算法是借鉴了最大熵模型的...
  • jieba分词详解

    万次阅读 2019-03-02 11:46:22
    语音识别中有一项任务就是训练语言模型,而对于中文的语言模型,需要事先进行分词。而语音识别中的语言模型还有个特殊的要求,就是语言模型中的所有词都必须在发音词典中(也就是说每个词都要有对应的发音)。因此这就...
  • ElasticSearch7.0.0安装IK分词

    万次阅读 2020-03-30 16:42:53
    为什么要在elasticsearch中要使用ik这样的中文分词呢,那是因为es提供的分词是英文分词,对于中文的分词就做的非常不好了,因此我们需要一个中文分词器来用于搜索和使用。就尝试安装下IK分词。 2.去github下载对应...
  • GET /${index}/${type}/${id}/_termvectors?fields=${fields_name}
  • 中文分词词库汇总(一)

    万次阅读 2018-08-09 23:43:11
    最近需要对招投标领域的中文词汇进行统计和分析,首选需要分词分词需要词库。 一、从网上找了不少词库,各有特点,在这里整理一下。词的数量有:4万,5.7万,9.1万,13.3万,15.5万,19.6万,21.3万,21.7万,21....
  • PUT news { "settings": { "index.analysis.analyzer.default.type": "ik_max_word" } }, "mappings": { "_doc": { "properties"...type
  • Python分词:结巴分词的安装使用

    万次阅读 2016-03-15 22:04:26
    结巴分词1. 下载:jieba-0.38 (python2/3)都可用。 https://pypi.python.org/pypi/jieba2. 解压:将其解压到:D:\program\python\jieba-0.38 3. 安装:cmd进入该目录,执行 python setyp.py install 4. 测试...
  • 修改ES默认分词设置

    万次阅读 2018-04-16 10:49:58
    ES的默认分词设置是standard,这个在中文分词时就比较尴尬了,会单字拆分,比如我搜索关键词“清华大学”,这时候会按“清”,“华”,“大”,“学”去分词,然后搜出来的都是些“清清的河水”,“中华儿女”,...
  • 中文分词是中文文本处理的一个基础步骤,也是中文人机自然语言交互的基础模块,在进行中文自然语言处理时,通常需要先进行分词。本文详细介绍现在非常流行的且开源的分词器结巴jieba分词器,并使用python实战介绍。...
  • Elasticsearch- 分词查询

    万次阅读 2014-05-27 18:32:13
    查看分词的命令, ES
  • ElasticSearch查看分词结果

    万次阅读 2018-03-30 17:29:25
    如下:GET googleplay/app/com.pearlabyss.blackdesertm/_termvectors?fields=name_krGET your_index/your_type/your_id/_termvectors?fields=your_fieldsName
1 2 3 4 5 ... 20
收藏数 102,860
精华内容 41,144
关键字:

分词