美文网首页
基于最大概率的汉语分词 (下)具体实现

基于最大概率的汉语分词 (下)具体实现

作者: 4v3r9 | 来源:发表于2019-01-13 18:58 被阅读12次

本学期(2018秋季学期)完成了基于最大概率的汉语分词实验,本文为博客第二部分,介绍具体实现过程。实验基于人民日报1998年1月中文语料库,使用Python语言进行中文分词实验。实验实现了FMM、BMM和Bigram算法的分词功能,其中Bigram算法借助前两者分词结果发现歧义,使用Laplace平滑计算最大概率。

1 数据准备

本实验使用人民日报1998年1月中文语料库,经过去除标点符号、词性标注等预处理步骤后共余下19347条。随机取80%作为训练集,余下作为验证集。

训练数据格式

2 构建字典

本实验需要构造两个字典,一个用来记录每个字典词出现的词频,另一个用来记录每个词后面出现过那些词(bigram组合)。其中前者使用TrieTree数据结构实现,后者使用Python字典实现。

TrieTree名为字典树、前缀树,用来保存字符串可以提高检索速度。其原理在于,前缀树每一个节点的子节点都拥有相同的前缀。字典树的特点在于每个节点都只含有一个字符,从根节点到某一个节点,路上经过的每个单个字符连起来为该节点对应的字符串。


字典树结构示意图

构建TrieTree字典树的过程如下:

    def dict_add(self,word):
        '''
        add 'word' to self.tree
        :param word: the word to be added
        :return: nothing; change the self.tree in-place
        '''
        tree = self.tree
        for char in word:
            if char in tree:
                tree = tree[char]
            else:
                tree[char] = {}
                tree = tree[char]

        if "freq" in tree:
            tree["freq"] +=1
        else:
            tree["freq"] =1

得到的字典树结构实例:

{'迈': {'向': {'freq': 1}}, '充': {'满': {'freq': 1}}, '希': {'望': {'freq': 1}}, '的': {'freq': 1}, '新': {'freq': 1, '年': {'freq': 1}}}

判断某词语是否在字典中时,需要递归遍历字典树:

    def dict_search(self,word):
        '''
        search word frequency in the self.tree
        :param word:
        :return: frequency
        '''
        tree = self.tree

        for char in word:
            if char in tree:
                tree = tree[char]
            else:
                return False

        if "freq" in tree and tree["freq"] >=1:
            return tree["freq"]
        else:
            return 0

对于记录Bigram组合的词典,其结构如下所示:

{“BEG”:{“你”:3, “今天”:2}, “你”:{“好”:6}}

3 FMM和BMM

正向最大匹配算法(FMM)是一种基于词典的分词方法。对于每个句子从左到右扫描寻找词的最大匹配,在这里限定匹配词语最大长度为4。而BMM算法则是从句子后往前遍历,仅仅是方向相反。

FMM匹配过程如下:

 def fmm(self,sent):
        thedict = self.tree
        MAXLEN = self.MAXLEN
        sent = sent.strip()
        ans = []
        while len(sent):
            for i in range(min(len(sent), MAXLEN), 0, -1):
                tomatch = sent[:i]
                if self.dict_search(tomatch):
                    ans.append(tomatch)
                    sent = sent[i:]
                    break
                elif len(sent[:i]) == 1:
                    ans.append(tomatch)
                    sent = sent[i:]
        return ans

4 Bigram模型

通常情况下,FMM或BMM可以得到正确的分词结果。但对于少部分歧义语句,需要借助概率判断采用哪种分词方案。例如,"你有意见分歧上报"在BMM算法中会被切割成"你/有/意见/分歧/上报",而在FMM算法下则会切割成"你/有意/见/上报".

自然语言可看作一个马氏链模型,可根据前面的词预测后面出现的词语.依据训练语料中单个词汇出现的频率以及词语两两组合出现的次数(Bigram),我们可以通过概率进行比较.
对于:
C = "有意见分歧"
C1: 有/ 意见/ 分歧/
C2: 有意/ 见/ 分歧/

有贝叶斯公式:


而一个词的概率可以用其出现次数除以预料中总次数得到.

计算概率时,如果词语不在字典中,会使得概率为0的情况.为避免0值,这里采用拉普拉斯平滑算法,将词语出现频数设为1.

如果FMM和BMM算法的切分结果相同,说明没有歧义,直接采用其切分结果即可;如果FMM和BMM算法切分结果不同,说明该语句含有歧义。对比FMM和BMM结果得到歧义子串计算概率,概率更大的子串判断为正确切分.(这部分代码见文末Github链接)

5 评价指标

本分词实验采用准确率,召回率和F1作为评价指标,它们的计算方法如下:

Precision = 正确切分出的词的数目/切分出的词的总数
Recall = 正确切分出的词的数目/应切分出的词的总数
F1 = 2*Precisiton*Recall/(Precision+Recall)

本实验结果如下:

实验结果

可见进行语义消歧的分词方法具有更高的效果。

附:
项目源码

相关文章

网友评论

      本文标题:基于最大概率的汉语分词 (下)具体实现

      本文链接:https://www.haomeiwen.com/subject/wojldqtx.html