jieba库中基于 TextRank 算法的关键词抽取——源代码分析(三)

2021SC@SDUSC
2021SC@SDUSC

TextRank第一步:分词——jieba.cut方法之有向无环图
在上篇博客中分析jieba.cut方法,最后if结构中在不同的情况下调用了__cut_DAG方法和__cut_DAG_NO_HMM方法以及__cut_all方法,打开这三种方法代码,会发现都调用了get_DAG方法,DAG在这里指的就是有向无环图,注意,TextRank第三步生成的是无向带权图
那么我们首先分析生成有向无权图的get_DAG方法,代码如下:

def get_DAG(self, sentence):
        self.check_initialized()
        DAG = {}
        N = len(sentence)
        for k in xrange(N):
            tmplist = []
            i = k
            frag = sentence[k]
            while i < N and frag in self.FREQ:
                if self.FREQ[frag]:
                    tmplist.append(i)
                i += 1
                frag = sentence[k:i + 1]
            if not tmplist:
                tmplist.append(k)
            DAG[k] = tmplist
        return DAG

首先分析这两行:

DAG = {}                             #构建了一个空的有向无环图
        N = len(sentence)            #将senten中词的长度(个数)赋给N

这两行比较简单,容易理解,而在接下来for循环的代码中主要是逻辑需要理解。

for k in xrange(N):             #创建长度未N的列表xrange,然后开始遍历
            tmplist = []		#从字开始能在FREQ中的匹配到的词末尾位置所在的list
            i = k				#令i=k,计数功能,可以在后续遍历中使用而不改变k的值           

这里其实是将一句话拆分成了N个部分,然后在后续while循环中,生成合适的分词,我们在这里可以以一个简单的例子来分析,例如现在分词的是“你好,明天!”这句话。

	frag = sentence[k]         #从sentence取传入的第k值,例如k=0时,我们取了“你”
            	while i < N and frag in self.FREQ:		#当传入的词,在FREQ中时,就给tmplist赋值,构建字开始可能去往的所有的路径列表
                	if self.FREQ[frag]:		#每个词在FREQ中查找查到,则将下标传入templist中
                    	tmplist.append(i)		#添加词语所在位置
                	i += 1						#查找i=0后,i+1后通过while循环继续查找与之紧邻的字组成的词语,例如查找完 你 后,查找 你好
                	frag = sentence[k:i + 1]    	#通过不同i大小,从sentence中截取不同长度的词语
            	if not tmplist:                #当取的frag在FREG中查询不到时
                	tmplist.append(k)
            	DAG[k] = tmplist			#将templist赋值给DAG
return DAG    #最后返回生成的DAG

然后我们再分析__cut_DAG方法和__cut_DAG_NO_HMM方法,以__cut_DAG方法为例,会发现里面最重要的一行代码是使用了calc方法,用于动态规划计算最大概率路径。

def __cut_DAG_NO_HMM(self, sentence):
        DAG = self.get_DAG(sentence)
        route = {}
        self.calc(sentence, DAG, route)
       ……

方法代码如下,具体分析可见代码旁注释

def calc(self, sentence, DAG, route):
        N = len(sentence)
        route[N] = (0, 0)	#route[N]:最大路径的值,(0,0):当前这个词的末尾坐标
        logtotal = log(self.total)
        for idx in xrange(N - 1, -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])

其原理是将log(词频/总词频)作为有向无环图边的权值,并假设词与词之间相互独立,从图论的角度出发,将最大概率组合问题变成了最大路径问题,那么函数calc(self, sentence, DAG, route)就是计算概率的过程。
但是注意的是这里是从后往前动态规划查找最大概率路径。
那么到这里可以看出jieba分词具体流程:构建有向无环图–>计算最大概率路径。
同时TextRank的第一步——将待抽取关键词的文本进行分词,也分析完毕,下篇博客我们会就第二步进行代码分析。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值