Textrank提取关键词的一些总结
最近一段时间做的主要工作是从文章中提取关键词,文章基本上是一些公司的介绍,量不算大,大概几万个。这件事儿本身实现起来不算很困难,所以大家也有些各行其是,缺乏一个能达成共识的方法(当然,这个task也比较难以进行评价),不少人也就得过且过,有一个差不多能用的算法就行了。我了解到的方法,基本的如tf-idf,textrank;看到某公司招聘的jd里写了“mi/ig”,我猜是mutual information和information gain,算是比较自然而然的idea;看了几篇文章使用global info来提取关键词(不要求提取的关键词一定在文章中出现,可以是更general的concept),大概是这些思路。
尝试了一些不同的方法,过于依赖统计的方法我排除了,毕竟我要分析的语料规模可能不是那么大,而且来源于互联网,规范化程度也比较低,纯统计的方法需要太多预处理的工作。最后上线的算法以textrank为基本核心,辅以使用global info的关键词联想算法,后者使用了LSI和比较流行的word2vec。今天主要写一些textrank相关的思考。
Textrank
Textrank其实是一个蛮简单的算法,假设我们用textrank来提取关键词,用最简单的话来说,就是给定一篇文章,过滤特定词性的词,指定一个定长的window size,以词为节点,同一个window内的两个词(节点)之间构建一条边(一般建模为双向,边无权),每篇文章构成了一个图,图中节点数量为文章的词汇表的词汇数。在这个图上运行pagerank算法(不知道pagerank的点上面的链接,看懂了再回来),over。
这篇文章发在04年的emnlp上,思路简单,充满了简洁之美。 作者的原文中,结果最佳的window size是2,收敛系数是0.0001.
坑
单纯使用Textrank来提取关键词的话,有下面两个问题:
- 节点的起始权重都是1,缺少先验信息的支持,文本长度不够长(比如所有的词的词频都是1)的时候,实际没什么产出。
- 文章开始与结尾位置的词有更小的概率被提取,window size越大,文章首尾的单词权重越位置敏感。
问题1比较好理解,先验信息缺乏导致算法对输入质量的要求比较高,文章的长度最好比较长(词汇丰富,词频差异也会相应增大),短文本上效果不好。
其实仔细想一下这个算法的idea,在不考虑先验信息和边权重的情况下,文章中tf高的词起始权重比较高,能接到不同词的词有更多的边(同时边没有权重),基本上相当于捏合了基于term frequency和mutual information的关键词提取方法。
问题2我也是一段时间才发现的,是我自己的想法,还没有完全认证。(stackoverflow上真是很少有人关注算法的问题哈)举例来说,如果window size设为2,那么文章的第一个词和第二个词构建了双向边,和构建了一个双向边,以此类推。比较和可以发现,比多了一次构建边的机会,也就是多了一个incoming的权重,而这个区别仅仅是由于词所在的位置造成的。在文章长度较长的情况下,这个的影响比较小,但是文章长度短的情况下,文章首尾的词有更小的可能性被选为关键词。
改进尝试
我的一个改进尝试就是在初始化图的时候,引入先验权重,先验权重是从全部文章中统计出来的,使用类似tf-idf方式。同时为了让本领域(互联网)关注的词有更高的可能性被提取,也应用领域词表。
整个先验知识分成两部分,一部分是统计得出的,为词和其对应的权重,权重的值域为[0.2, 1);另一部分是词表得来的,权重设为0.2.也就是在初始化文章对应的图的时候,对每一个词先查看先验知识,更新的权重为原始权重(1)加上先验知识中对应的权重。在Textrank迭代之前,所有节点权重的值域即为[0, 2).
其他
Textrank的实现比较简单,我参考了jieba中Textrank的实现,并对其做了一些改进。