当前位置:   article > 正文

jieba库中基于 TextRank 算法的关键词抽取——源代码分析(三)_使用了jieba的textrank进行高频词的提取,请问textrank实现高频词提取的原理是

使用了jieba的textrank进行高频词的提取,请问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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

首先分析这两行:

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

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

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

这里其实是将一句话拆分成了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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

然后我们再分析__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)
       ……
  • 1
  • 2
  • 3
  • 4
  • 5

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

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])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/281577
推荐阅读
相关标签
  

闽ICP备14008679号