Alyona 经营着一家总部在新西兰的 NLP 咨询公司——Entopix,她有计算语言学硕士和计算机博士学位,是主题提取工具 Maui 的作者。
视频简介:https://www.youtube.com/watch?v=Chwm_AFZg-c
1 引言
在这个教程中,你将会学到如何用Python和Java自动提取关键词,而且你将理解与之相关的任务,例如有控制词表的关键短语提取(换句话说是把文本分类到各种可能类别的超大集合中),还有术语提取。
本教程如下组织:首先,我们讨论要一点背景——什么是关键词,一个关键词算法如何工作?然后我们用一个叫做Rake的Python库举一个简单但在很多情况下很有用的关键词提取的例子。最后,我们展示一个叫做Maui的Java工具如何用机器学习方法提取关键词。
1.1 为什么提取关键词
处理文档时,提取关键词是最重要的工作之一。读者受益于关键词,因为他们可以快速判断一篇文章是否值得一读。网站创立者从中受益,因为他们可以根据话题集中相似的内容。算法开发者从 关键词受益,因为关键词降低文本维度来显出最重要的特征。这只是一些有帮助的例子。
根据定义,关键词是一篇文档中表达的主要话题。这个术语有点迷惑,所以下面的图片在词汇的源头和被每个文档的话题数量方面比较了相关的任务。
这个教程中,我们会关注两个具体的任务并且评价它们:
- 在给定文本中出现的最重要的词和短语
- 从与给定文本匹配的预定词表中,识别一系列主题
如何多个文档间词汇一致性重要,我推荐你使用一个词表——或学科词表、分类词典,除非由于某些原因做不到这点。
给对文本分类(另一个做文本工作时流行的任务)有兴趣的人的几句话:如果类别的数量很大,你将会很难收集足够的训练集用于有监督的分类。因此,如果有一百多个类别,并且你可以给出这些类别的名字(而不是抽象类别),那么你面临是细粒度的分类。我们可以把这个任务看作带有受控词汇表的关键词提取,或者术语分配。所以,读下去,这个教程也是针对你的!
2 关键词提取如何工作?
通常关键词提取算法有三个主要成分:
- 候选词选择:这里,我们提取所有可能是关键词的词,词组,术语或概念(取决于任务)。
- 特性计算:对于每个候选词,我们需要计算表示它是否为关键词的特性。比如,一个候选词
- 对关键词评分并选择:所有候选词可以通过把各性质结合进一个公式来评分,或者用机器学习技术来决定一个候选词是一个关键词的概率。然后一个分数或概率的阈值或者对关键词数量的限制用来选择最终的关键词集合。
最终,像候选词最小频率的参数,它的最小和最大词长,或者用来使候选词标准化的词干提取器,都有助于调整算法对于特定数据集的性能。
3 Python下用RAKE提取关键词
对于Python用户,有一个易用的关键词提取库叫做RAKE,其全称是 Rapid Automatic Keyword Extraction。算法本身表述在 Michael W. Berry的 《文本挖掘和理论》一书中(免费pdf)。这里,我们使用已有的Python实现。这里有个修改过的版本,它使用了自然语言处理工具NLTK处理一些计算。对于这个教程,我已经 fork了原始的RAKE仓库并且将其拓展成了RAKE教程,来使用额外的参数评价它的性能。
3.1 配置RAKE
首先你需要从这个地址获取RAKE仓库 https://github.com/zelandiya/RAKE-tutorial.
1 |
$ git clone https://github.com/zelandiya/RAKE-tutorial |
然后,按照rake_tutorial.py中的步骤,import RAKE,并且为这个教程的”幕后”部分import operator:
1 2 |
import rake import operator |
3.2 对一小段文本使用RAKE
首先,我们用一个通向一个停止词表的路径初始化RAKE并且设置一些参数。
1 |
rake_object = rake.Rake("SmartStoplist.txt", 5, 3, 4) |
现在,我们有一个提取关键词的RAKE对象,其中:
- 每个词至少有5个字符
- 每个短语至少有3个词
- 每个关键词至少在文本中出现4次
这些参数取决与你手上的文本,并且仔细选择这些参数是很关键的(试着用默认参数运行这个例子你就会明白)。更多信息在下一节。
接下来,我们已经有了存储在一个变量中的一段文本(在这个例子中,我们从一个文件中读取),我们可以应用RAKE并且打印关键词。
1 2 3 4 |
sample_file = open("data/docs/fao_test/w2167e.txt", 'r') text = sample_file.read() keywords = rake_object.run(text) print "Keywords:", keywords |
输出应该看起来像这样:
1 |
Keywords: Keywords: [('household food security', 7.711414565826329), ('indigenous groups living', 7.4), ('national forest programmes', 7.249539170506913), ('wood forest products', 6.844777265745007)... |
这里,我们没有每个关键词的名字和它对应于这个算法的分数。
3.3 RAKE: 幕后
这一次,我们将会使用一个短文本片段,并且我们可以在这里使用默认参数:
1 2 3 4 5 6 7 8 9 10 |
stoppath = "SmartStoplist.txt" rake_object = rake.Rake(stoppath) text = "Compatibility of systems of linear constraints over the set of natural numbers. Criteria of compatibility " \ "of a system of linear Diophantine equations, strict inequations, and nonstrict inequations are considered. " \ "Upper bounds for components of a minimal set of solutions and algorithms of construction of minimal generating"\ " sets of solutions for all types of systems are given. These criteria and the corresponding algorithms " \ "for constructing a minimal supporting set of solutions can be used in solving all the considered types of " \ "systems and systems of mixed types." |
首先,RAKE把文本分割成句子,并且生成候选词:
1 2 3 |
sentenceList = rake.split_sentences(text) stopwordpattern = rake.build_stop_word_regex(stoppath) phraseList = rake.generate_candidate_keywords(sentenceList, stopwordpattern) |
这里,各种标点符号将会被认为句子边界。大多数情况这都很有用,但是对于标点是真实短语的一部分的情况(例,.Net或Dr. Who)没有用。
列在停止词文件中的所有词将会被认为是短语边界。这帮助我们生成包含一个或更多非停止词的候选词,比如这篇文本中的“compatibility”、“systems”、“linear constraints”、“set”,、“natural numbers”和“criteria”。大多数候选词将会是有效的,但是,对于停止词是短语的一部分的情况不会有用。例如,“new”列在RAKE的停止词中。这意味着“New York”或“New Zealand”都不会是一个关键词。
第二,RAKE 计算每个候选词的属性,是各候选词的分数的总和。候选词是怎么打分的?根据候选词的出现频率,以及典型长度。