当前位置:   article > 正文

NLP学习笔记——TextRank算法

textrank算法

一、算法简介

TextRank算法是一种基于图排序算法,由谷歌的网页重要性排序算法PageRank算法改进而来,主要应用有关键词提取、文本摘要抽取等。该算法的主要思想是:把文档中的词(句)看成一个网络,词(句)之间的语义关系为网络之间的链接。通过迭代计算获得权重值依旧依赖词频,通常词频越高计算的权重值越高,一般需要进行停用词处理)公式如下:

W(vi)=(1d)+dvjIn(vi)WijvkOut(vj)WjkW(vj)

其中,W(v_{i})为节点i的权重值、d为学习率(一般为0.85)、v_{i}v_{j}分别表示节点i和节点jIn(v_{i})表示所有指向节点i的节点、W_{ij}表示节点i和节点j的链接的权重值。

也可以理解成无向图的形式:W_{ab}为两节点的边权重值,v为节点,W(v_{a})为节点权重值、\sum_{v_{k}\in Out(v_{j})}^{}W_{jk}为所有与节点j连接的边权值之和(主要是为了归一化操作,不理解的通过以下代码的运行去解读)。如下图所示:

优缺点: 

优:

  1. textrank只依赖文章本身,它认为一开始每个词的重要程度是一样的。
  2. 继承了PageRank的思想,效果相对较好,相对于TF-IDF方法,可以更充分的利用文本元 素之间的关系。
  3. 无监督方式,无需构造数据集训练。

缺:

  1. 结果受分词、文本清洗影响较大,即对于某些停用词的保留与否,直接影响最终结果。
  2. 虽然与TF-IDF比,不止利用了词频,但是仍然受高频词的影响,因此需要结合词性和词频进行筛选,以达到更好效果,但词性标注显然又是一个问题。

二、TextRank关键词提取步骤及实现

其实摘要抽取关键词提取原理一样的,无非就是文本细粒度的不同,通过句子的词权值相加(或者取平均值,记不清了,个人觉得取平均值比较靠谱)的结果为句子权重,再根据句子权重从大到小提取一定数量的句子为摘要。

关键词提取具体步骤如下:

1、把给定的文本T按照完整句子进行分割,即T=[S_{1},S_{2},...,S_{m}]

2、对于每个句子S; ∈T,进行分词和词性标注处理,并过滤掉停用词,只保留指定词性的单词,如名词、动词、形容词,即S =[t_{i1},t_{i2},...,t_{tn}],其中t_{ij}是保留后的候选关键词。

3、构建候选关键词图G=(V,E),其中V为节点集,由上步生成的候选关键词组成,然后采用共现关系构造任两点之间的边,两个节点之间存在边仅当它们对应的词汇在长度为k的窗口中共现,k表示窗口大小,即最多共现k个单词。

4、根据上面的公式,迭代传播各节点的权重,直至收敛。

5、对节点权重进行倒序排列,从而得到最重要的T个单词,作为候选关键词。

6、由上步得到最重要的T个单词,在原始文本中进行标记,若形成相邻词组,则组合成多词关键词

  1. import numpy as np
  2. import jieba.posseg as pseg
  3. class TextRank(object):
  4. def __init__(self, sentence, window, learn_rate, iterations):
  5. self.sentence = sentence
  6. self.window = window
  7. self.learn_rate = learn_rate
  8. self.edge_dict = {} # 记录节点的边连接字典
  9. self.iterations = iterations # 迭代次数
  10. def createNodes(self):
  11. # 对句子进行分词
  12. # jieba.load_userdict('user_dict.txt')
  13. # 这里进行了停用词处理,只保留的规定词性的词
  14. tag_filter = ['a', 'd', 'n', 'v']
  15. seg_result = pseg.cut(self.sentence)
  16. self.word_list = [s.word for s in seg_result if s.flag in tag_filter]
  17. print(self.word_list)
  18. # 根据窗口,构建每个节点的相邻节点,返回边的集合
  19. tmp_list = []
  20. word_list_len = len(self.word_list)
  21. for index, word in enumerate(self.word_list): #遍历句子的词
  22. if word not in self.edge_dict.keys(): #判断该词(中心词)是否处理过
  23. tmp_list.append(word)
  24. tmp_set = set()
  25. left = index - self.window + 1 # 窗口左边界
  26. right = index + self.window # 窗口右边界
  27. # 规范窗口边界
  28. if left < 0: left = 0
  29. if right >= word_list_len: right = word_list_len
  30. #查找窗口内除中心点意外的点
  31. for i in range(left, right):
  32. if i == index: #判断该点是不是中心点,是就跳过
  33. continue
  34. else:
  35. tmp_set.add(self.word_list[i]) #记录非中心点,集合可以去重
  36. self.edge_dict[word] = tmp_set #记录中心点周围点{'中心点1':{'周围点1','周围点2',...},'中心点2':{'周围点1','周围点2',...}}
  37. # 根据边的相连关系,构建矩阵
  38. def createMatrix(self):
  39. self.matrix = np.zeros([len(set(self.word_list)), len(set(self.word_list))])
  40. self.word_index = {} # 记录词的index
  41. self.index_dict = {} # 记录节点index对应的词
  42. #构建点和边的双向索引
  43. for i, v in enumerate(set(self.word_list)):
  44. self.word_index[v] = i
  45. self.index_dict[i] = v
  46. #构建无向图
  47. for key in self.edge_dict.keys(): #查找中心点
  48. for w in self.edge_dict[key]: #查找中心点对应的周围点
  49. self.matrix[self.word_index[key]][self.word_index[w]] = 1 #建立无向便,有边为1,反之为0
  50. self.matrix[self.word_index[w]][self.word_index[key]] = 1 #无相边的矩阵为对角矩阵
  51. # 根据textrank公式计算权重并输出结果
  52. def call(self):
  53. # 归一化(按公式里对j节点归一化)
  54. sum = np.sum(self.matrix, axis=0) # 按列求和
  55. for j in range(self.matrix.shape[1]):
  56. for i in range(self.matrix.shape[0]):
  57. self.matrix[i][j] /= sum[j] # 按列归一化
  58. self.nodeI = np.ones([len(set(self.word_list))])
  59. for i in range(self.iterations): #公式
  60. self.nodeI = (1 - self.learn_rate) + self.learn_rate * np.dot(self.matrix, self.nodeI)
  61. # 输出词和相应的权重
  62. word_pr = {}
  63. for i in range(len(self.nodeI)):
  64. word_pr[self.index_dict[i]] = self.nodeI[i]
  65. #items()函数返回列表里嵌套(键,值)元组
  66. res = sorted(word_pr.items(), key=lambda x: x[1], reverse=True) #对列表进行临时排序,reverse选择降序
  67. print(res)
  68. if __name__ == '__main__':
  69. s = '情感分析又称倾向性分析或观点挖掘,是一种重要的信息分析处理技术,其研究目的是自动挖掘文本中的立场、观点、看法、情绪和喜恶等。在情感状态的理论研究中,情感状态的主要表示方法有两种:离散类别型表示方法和维度连续型表示方法。'
  70. TextRank = TextRank(s, 3, 0.85, 700)
  71. TextRank.createNodes()
  72. TextRank.createMatrix()
  73. TextRank.call()
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/281631
推荐阅读
相关标签
  

闽ICP备14008679号