很久以前,我用过TFIDF做过行业关键词提取。TFIDF仅仅从词的统计信息出发,而没有充分考虑词之间的语义信息。现在本文将介绍一种考虑了相邻词的语义关系、基于图排序的关键词提取算法TextRank。

1. 介绍

TextRank由Mihalcea与Tarau于EMNLP'04 [1]提出来,其思想非常简单:通过词之间的相邻关系构建网络,然后用PageRank迭代计算每个节点的rank值,排序rank值即可得到关键词。PageRank本来是用来解决网页排名的问题,网页之间的链接关系即为图的边,迭代计算公式如下:

\[PR(V_i) = (1-d) + d * \sum_{j \in In(V_i)} \frac{1}{|Out(V_j)|}PR(V_j)
\]

其中,\(PR(V_i)\)表示结点\(V_i\)的rank值,\(In(V_i)\)表示结点\(V_i\)的前驱结点集合,\(Out(V_j)\)表示结点\(V_j\)的后继结点集合,\(d\)为damping factor用于做平滑。

网页之间的链接关系可以用图表示,那么怎么把一个句子(可以看作词的序列)构建成图呢?TextRank将某一个词与其前面的N个词、以及后面的N个词均具有图相邻关系(类似于N-gram语法模型)。具体实现:设置一个长度为N的滑动窗口,所有在这个窗口之内的词都视作词结点的相邻结点;则TextRank构建的词图为无向图。下图给出了由一个文档构建的词图(去掉了停用词并按词性做了筛选):

考虑到不同词对可能有不同的共现(co-occurrence),TextRank将共现作为无向图边的权值。那么,TextRank的迭代计算公式如下:

\[WS(V_i) = (1-d) + d * \sum_{j \in In(V_i)} \frac{w_{ji}}{\sum_{V_k \in Out(V_j)} w_{jk}} WS(V_j)
\]

2. 评估

接下来将评估TextRank在关键词提取任务上的准确率、召回率与F1-Measure,并与TFIDF做对比;准确率计算公式如下:

\[Precision = \frac{1}{N} \sum_{i=0}^{N-1} \frac{\left|P_i \cap T_i\right|}{\left|P_i\right|}
\]

其中,\(N\)为文档数量,\(P_i\)为文档\(i\)所提取出的关键词,\(T_i\)为文档的标注关键词。召回率与F1的计算公式如下:

\[Recall = \frac{1}{N} \sum_{i=0}^{N-1} \frac{\left|P_i \cap T_i\right|}{\left|T_i\right|}
\]

\[F1 = \frac{2*Precision*Recall}{Precision + Recall}
\]

测试集是由刘知远老师提供的网易新闻标注数据集,共有13702篇文档。Jieba完整地实现了关键词提取TFIDF与TextRank算法,基于Jieba-0.39的评估实验代码如下:

import jieba.analyse
import json
import codecs def precision_recall_fscore_support(y_true, y_pred):
"""
evaluate macro precision, recall and f1-score.
"""
doc_num = len(y_true)
p_macro = 0.0
r_macro = 0.0
for i in range(doc_num):
tp = 0
true_len = len(y_true[i])
pred_len = len(y_pred[i])
for w in y_pred[i]:
if w in y_true[i]:
tp += 1
p = 1.0 if pred_len == 0 else tp / pred_len
r = 1.0 if true_len == 0 else tp / true_len
p_macro += p
r_macro += r
p_macro /= doc_num
r_macro /= doc_num
return p_macro, r_macro, 2 * p_macro * r_macro / (p_macro + r_macro) file_path = 'data/163_chinese_news_dataset_2011.dat'
with codecs.open(file_path, 'r', 'utf-8') as fr:
y_true = []
y_pred = []
for line in fr.readlines():
d = json.loads(line)
content = d['content']
true_key_words = [w for w in set(d['tags'])]
y_true.append(true_key_words)
# for w in true_key_words:
# jieba.add_word(w)
key_word_pos = ['x', 'ns', 'n', 'vn', 'v', 'l', 'j', 'nr', 'nrt', 'nt', 'nz', 'nrfg', 'm', 'i', 'an', 'f', 't',
'b', 'a', 'd', 'q', 's', 'z']
extract_key_words = jieba.analyse.extract_tags(content, topK=2, allowPOS=key_word_pos)
# trank = jieba.analyse.TextRank()
# trank.span = 5
# extract_key_words = trank.textrank(content, topK=2, allowPOS=key_word_pos)
y_pred.append(extract_key_words)
prf = precision_recall_fscore_support(y_true, y_pred)
print('precision: {}'.format(prf[0]))
print('recall: {}'.format(prf[1]))
print('F1: {}'.format(prf[2]))

其中,每个文档提取的关键词数为2,并按词性做过滤;span表示TextRank算法中的滑动窗口的大小。评估结果如下:

方法 Precision Recall F1-Measure
TFIDF 0.2697 0.2256 0.2457
TextRank span=5 0.2608 0.2150 0.2357
TextRank span=7 0.2614 0.2155 0.2363

如果将标注关键词添加到自定义词典,则评估结果如下:

方法 Precision Recall F1-Measure
TFIDF 0.3145 0.2713 0.2913
TextRank span=5 0.2887 0.2442 0.2646
TextRank span=7 0.2903 0.2455 0.2660

直观感受下关键词提取结果(添加了自定义词典):

// TFIDF, TextRank, labelled
['文强', '陈洪刚'] ['文强', '陈洪刚'] {'文强', '重庆'}
['内贾德', '伊朗'] ['伊朗', '内贾德'] {'制裁', '世博', '伊朗'}
['调控', '王珏林'] ['调控', '楼市'] {'楼市', '调控'}
['罗平县', '男子'] ['男子', '罗平县'] {'被砍', '副局长', '情感纠葛'}
['佟某', '黄玉'] ['佟某', '黄现忠'] {'盲井', '伪造矿难'}
['女生', '聚众淫乱'] ['女生', '聚众淫乱'] {'聚众淫乱', '东莞', '不雅视频'}
['马英九', '和平协议'] ['马英九', '推进'] {'国台办', '马英九', '和平协议'}
['东帝汶', '巡逻艇'] ['东帝汶', '中国'] {'东帝汶', '军舰', '澳大利亚'}
['墨西哥', '警方'] ['墨西哥', '袭击'] {'枪手', '墨西哥', '打死'}

从上述两组实验结果,可以发现:

  • TextRank与TFIDF均严重依赖于分词结果——如果某词在分词时被切分成了两个词,那么在做关键词提取时无法将两个词黏合在一起(TextRank有部分黏合效果,但需要这两个词均为关键词)。因此是否添加标注关键词进自定义词典,将会造成准确率、召回率大相径庭。
  • TextRank的效果并不优于TFIDF。
  • TextRank虽然考虑到了词之间的关系,但是仍然倾向于将频繁词作为关键词。

此外,由于TextRank涉及到构建词图及迭代计算,所以提取速度较慢。

3. 参考资料

[1] Rada, Mihalcea, and Paul Tarau. "TextRank: Bringing Order into Texts." empirical methods in natural language processing (2004): 404-411.

关键词提取算法TextRank的更多相关文章

  1. 关键词提取算法-TextRank

    今天要介绍的TextRank是一种用来做关键词提取的算法,也可以用于提取短语和自动摘要.因为TextRank是基于PageRank的,所以首先简要介绍下PageRank算法. 1.PageRank算法 ...

  2. TextRank:关键词提取算法中的PageRank

    很久以前,我用过TFIDF做过行业关键词提取.TFIDF仅仅从词的统计信息出发,而没有充分考虑词之间的语义信息.现在本文将介绍一种考虑了相邻词的语义关系.基于图排序的关键词提取算法TextRank [ ...

  3. 自然语言处理工具hanlp关键词提取图解TextRank算法

    看一个博主(亚当-adam)的关于hanlp关键词提取算法TextRank的文章,还是非常好的一篇实操经验分享,分享一下给各位需要的朋友一起学习一下! TextRank是在Google的PageRan ...

  4. 关键词提取算法TF-IDF与TextRank

    一.前言 随着互联网的发展,数据的海量增长使得文本信息的分析与处理需求日益突显,而文本处理工作中关键词提取是基础工作之一. TF-IDF与TextRank是经典的关键词提取算法,需要掌握. 二.TF- ...

  5. 关键字提取算法TF-IDF和TextRank(python3)————实现TF-IDF并jieba中的TF-IDF对比,使用jieba中的实现TextRank

    关键词:    TF-IDF实现.TextRank.jieba.关键词提取数据来源:    语料数据来自搜狐新闻2012年6月—7月期间国内,国际,体育,社会,娱乐等18个频道的新闻数据    数据处 ...

  6. NLP之关键词提取(TF-IDF、Text-Rank)

    1.文本关键词抽取的种类: 关键词提取方法分为有监督.半监督和无监督三种,有监督和半监督的关键词抽取方法需要浪费人力资源,所以现在使用的大多是无监督的关键词提取方法. 无监督的关键词提取方法又可以分为 ...

  7. TF-IDF算法之关键词提取

    (注:本文转载自阮一峰老师的博文,原文地址:http://www.ruanyifeng.com/blog/2013/03/tf-idf.html) 这个标题看上去好像很复杂,其实我要谈的是一个很简单的 ...

  8. HanLP 关键词提取算法分析

    HanLP 关键词提取算法分析 参考论文:<TextRank: Bringing Order into Texts> TextRank算法提取关键词的Java实现 TextRank算法自动 ...

  9. HanLP 关键词提取算法分析详解

    HanLP 关键词提取算法分析详解 l 参考论文:<TextRank: Bringing Order into Texts> l TextRank算法提取关键词的Java实现 l Text ...

随机推荐

  1. poj1041 【无向图欧拉回路】 按最小升序输出

    题目链接:http://poj.org/problem?id=1041 题目大意: 题目大意:一个城镇有n个二叉路口,这些路口由m条街道连接,某人想要从某个路口出发,经过所有的街道且每条街道只走一次, ...

  2. 001.Ceph简介概述

    一 Ceph简介 Red Hat Ceph是一个分布式的数据对象存储,系统设计旨在性能.可靠性和可扩展性上能够提供优秀的存储服务.分布式对象存储是存储的未来,因为它们适应非结构化数据,并且客户端可以同 ...

  3. 最近24小时记录:虚拟机与Wireshark 2.0

    最近24小时记录:虚拟机与Wireshark 2.0   (1)虚拟机如果NAT模式而无法联网,需要检查实体机中VMware的NAT服务是否开启. (2)从Wireshark 2.0版本开始,Wire ...

  4. Xamarin SQLite教程Xamarin.iOS项目添加引用

    Xamarin SQLite教程Xamarin.iOS项目添加引用 使用直接方式访问SQLite数据库,需要将System.Data和Mono.Data.SQlite库导入到创建的项目中.下面将分别讲 ...

  5. MySql基础笔记(一)Mysql快速入门

    Mysql快速入门 一)基本概念 1)表 行被称为记录,是组织数据的单位.列被称为字段,每一列表示记录的一个属性. 2)主键 主键用于唯一的标识表中的每一条记录.可以定义表中的一列或者多列为主键, 但 ...

  6. NIOH

    目录 NIOH中的双刀与阴阳术的应用 作战准备篇 2周目毕业装备: 加点: 双刀: 核心技能: 还行的技能: 被动技能: 忍术: 阴阳术: 必学: 选学: 守护灵: 隐世茶室 & 铁匠铺 出发 ...

  7. 2017.07.09【NOIP提高组】模拟赛B组

    Summary 今天放假,比赛于是就没有打了,但是看了一下题,发现都挺简单了,不想码~╮(╯▽╰)╭懒虫一条.最后一题居然做过原题.这次比赛让我对并查集“刮目相看”,对贪心感到“前途无量”,觉得树形D ...

  8. JS 数组方法

    1.栈方法 ECMAScript 提供了一些让数组行为类似其他数据结构的方法 栈是一种后进先出(LIFO)的数据结构,也就是最新添加的项最早被移除:而栈中数据的添加和删除只发生在栈的顶部 数组可以对其 ...

  9. EasyAR 开发实例---AR礼物(简单demo)

    一个节日礼物效果 --显示模型 在本次的案例中,我使用的是unity5.6.3版本,EasyAR 为2.0.(用1.0的版本,在渲染那块有问题) [导入SDK]到EasyAR官网(http://www ...

  10. ajax-异步加载片段

    片段一般用.htm后缀 下面是ajax加载片段的demo 涉及知识点为: jquery.load(url, data, callback); 必需的 URL 参数规定您希望加载的 URL. 可选的 d ...