jieba源代码解析——四种分词模式(三)

2021SC@SDUSC
2021SC@SDUSC
在分词时,构建完前缀词典,并以此为基础,生成了有向无环图DAG,再借此计算最大概率路径。
2021SC@SDUSC
2021SC@SDUSC
但其实在生成DAG时还使用到了一个方法——check_initialized,检查是否初始化,如果没有,则会初始化。

def check_initialized(self):
        if not self.initialized: #如果未初始化进行初始化
            abs_path = _get_abs_path(self.dictionary)
            if self.cache_file:
                cache_file = self.cache_file
            # 默认的cachefile
            elif abs_path:
                cache_file = "jieba.cache"
 
            load_from_cache_fail = True
            # cachefile 存在
            if os.path.isfile(cache_file):
 
                try:
                #打开cachefile
                    with open(cache_file, 'rb') as cf:
                        self.FREQ, self.total = marshal.load(cf)
                    load_from_cache_fail = False
                except Exception:
                    load_from_cache_fail = True
            if load_from_cache_fail:
                self.FREQ, self.total = self.gen_pfdict(abs_path)
                #把dict前缀集合,总词频写入文件
                try:
                    with open(cache_file, 'w') as temp_cache_file:
                        marshal.dump((self.FREQ, self.total), temp_cache_file)
                except Exception:
                    #continue
                    pass
            # 标记初始化成功
            self.initialized = True

接下来分析最大概率路径。

     #动态规划,计算最大概率的切分组合
    def calc(self, sentence, DAG, route):
        N = len(sentence)
        route[N] = (0, 0)
         # 对概率值取对数之后的结果(可以让概率相乘的计算变成对数相加,防止相乘造成下溢)
        logtotal = log(self.total)
        # 从后往前遍历句子 反向计算最大概率
        for idx in xrange(N - 1, -1, -1):
           # 列表推倒求最大概率对数路径
           # route[idx] = max([ (概率对数,词语末字位置) for x in DAG[idx] ])
           # 以idx:(概率对数最大值,词语末字位置)键值对形式保存在route中
           # route[x+1][0] 表示 词路径[x+1,N-1]的最大概率对数,
           # [x+1][0]即表示取句子x+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])

for循环中,idx为句末往句首倒推。
route为字典,key为idx,value为含有两个元素的元组,元组的第一个元素为:以idx为开头,第二个元素x位置为结尾组成的词语,在词典中成词的概率(取max后结果为x遍历,idx到x,以及x到句尾的分词方式最大概率,也就是idx到句尾的最大概率分词方式)。元组的第二个元素x为DAG[idx]的value遍历。当idx=0时,可得到句首到句尾的最大分词方式。

这里采用从后往前的计算方式,主要原因在于有向无环图是从前指向后,对于一个节点,DAG中存储了此节点指向后面哪些节点,但没有存储前面有哪些节点指向此节点。举个例子:’ABCD’,从后往前计算,我们可以在’C’节点先知道P(‘CD’),到’A’节点时,就可以比较P(‘ABCD’)与P(‘AB’)*P(‘CD’)的大小了,但如果是从前往后计算就不行,在A节点我们知道P(‘AB’)和P(‘ABCD’),但是不知道P(‘CD’),会加大程序的复杂性。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值