该内容已被发布者删除 该内容被自由微信恢复
文章于 2017年4月2日 被检测为删除。
查看原文
被用户删除
其他

教程:用 RAKE 和 Maui 做 NLP 关键词提取

2015-10-05 Python开发者

(点击上方公号,可快速关注)


Alyona 经营着一家总部在新西兰的 NLP 咨询公司——Entopix,她有计算语言学硕士和计算机博士学位,是主题提取工具 Maui 的作者。


1.引言


在这个教程中,你将会学到如何用 Python 和 Java 自动提取关键词,而且你将理解与之相关的任务,例如有控制词表的关键短语提取(换句话说是把文本分类到各种可能类别的超大集合中),还有术语提取。


本教程如下组织:首先,我们讨论要一点背景——什么是关键词,一个关键词算法如何工作?然后我们用一个叫做Rake的Python库举一个简单但在很多情况下很有用的关键词提取的例子。最后,我们展示一个叫做Maui的Java工具如何用机器学习方法提取关键词。


1.1 为什么提取关键词


处理文档时,提取关键词是最重要的工作之一。读者受益于关键词,因为他们可以快速判断一篇文章是否值得一读。网站创立者从中受益,因为他们可以根据话题集中相似的内容。算法开发者从 关键词受益,因为关键词降低文本维度来显出最重要的特征。这只是一些有帮助的例子。


根据定义,关键词是一篇文档中表达的主要话题。,所以下面的图片在词汇的源头和被每个文档的话题数量方面比较了相关的任务。



这个教程中,我们会关注两个具体的任务并且评价它们:


  • 在给定文本中出现的最重要的词和短语

  • 从与给定文本匹配的预定词表中,识别一系列主题


如何多个文档间词汇一致性重要,我推荐你使用一个词表——或学科词表、分类词典,除非由于某些原因做不到这点。


给对文本分类(另一个做文本工作时流行的任务)有兴趣的人的几句话:如果类别的数量很大,你将会很难收集足够的训练集用于有监督的分类。因此,如果有一百多个类别,并且你可以给出这些类别的名字(而不是抽象类别),那么你面临是细粒度的分类。我们可以把这个任务看作带有受控词汇表的关键词提取,或者术语分配。所以,读下去,这个教程也是针对你的!


2 关键词提取如何工作?


通常关键词提取算法有三个主要成分:


  • 候选词选择:这里,我们提取所有可能是关键词的词,词组,术语或概念(取决于任务)。

  • 特性计算:对于每个候选词,我们需要计算表示它是否为关键词的特性。比如,一个候选词

  • 对关键词评分并选择:所有候选词可以通过把各性质结合进一个公式来评分,或者用机器学习技术来决定一个候选词是一个关键词的概率。然后一个分数或概率的阈值或者对关键词数量的限制用来选择最终的关键词集合。



最终,像候选词最小频率的参数,它的最小和最大词长,或者用来使候选词标准化的词干提取器,都有助于调整算法对于特定数据集的性能。


对于Python用户,有一个易用的关键词提取库叫做RAKE,其全称是 Rapid Automatic Keyword Extraction。算法本身表述在 Michael W. Berry的 一书中()。这里,我们使用已有的。这里有个,它使用了自然语言处理工具NLTK处理一些计算。对于这个教程,我已经 ,来使用额外的参数评价它的性能。


3.1 配置RAKE


首先你需要从这个地址获取RAKE仓库 .(若失效请找有效地址)


$ git clone https://github.com/zelandiya/RAKE-tutorial


然后,按照rake_tutorial.py中的步骤,import RAKE,并且为这个教程的”幕后”部分import operator:


import rake

import operator


3.2 对一小段文本使用RAKE


首先,我们用一个通向一个停止词表的路径初始化RAKE并且设置一些参数。


rake_object = rake.Rake("SmartStoplist.txt", 5, 3, 4)


现在,我们有一个提取关键词的RAKE对象,其中:


每个词至少有5个字符


每个短语至少有3个词


每个关键词至少在文本中出现4次


这些参数取决与你手上的文本,并且仔细选择这些参数是很关键的(试着用默认参数运行这个例子你就会明白)。更多信息在下一节。


接下来,我们已经有了存储在一个变量中的一段文本(在这个例子中,我们从一个文件中读取),我们可以应用RAKE并且打印关键词。


sample_file = open("data/docs/fao_test/w2167e.txt", 'r')

text = sample_file.read()

keywords = rake_object.run(text)

print "Keywords:", keywords


输出应该看起来像这样:


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: 幕后


这一次,我们将会使用一个短文本片段,并且我们可以在这里使用默认参数:


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把文本分割成句子,并且生成候选词:


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 计算每个候选词的属性,是各候选词的分数的总和。候选词是怎么打分的?根据候选词的出现频率,以及典型长度。


wordscores = rake.calculate_word_scores(phraseList)

keywordcandidates = rake.generate_candidate_keyword_scores(phraseList, wordscores)


这里的一个问题是,候选词并没有标准化。所有我们可能会有看起来完全一样的关键词,比如:「small scale production 和 small scale producers」,或者 「skim milk powder 和 skimmed milk powder」。在理想情况下,关键词提取算法应首先应用于词干和其他标准化的关键词。


最后,我们根据RAKE的分数给候选关键词排序。关键词然后可以既是分数排名前五的候选词,也可以是超过一个选定分数阈值的,或者排名第三的,如同下面的例子:


sortedKeywords = sorted(keywordcandidates.iteritems(), key=operator.itemgetter(1), reverse=True)

totalKeywords = len(sortedKeywords)

for keyword in sortedKeywords[0:(totalKeywords / 3)]:

print "Keyword: ", keyword[0], ", score: ", keyword[1]



正常的输出信息如下:



Keyword: minimal generating sets , score: 8.66666666667

Keyword: linear diophantine equations , score: 8.5

Keyword: minimal supporting set , score: 7.66666666667

Keyword: minimal set , score: 4.66666666667

Keyword: linear constraints , score: 4.5

Keyword: upper bounds , score: 4.0

Keyword: natural numbers , score: 4.0

Keyword: nonstrict inequations , score: 4.0


这还有两个有用的脚本。第一个用有文档和他们的手工分分配的关键词的目录,和应该评价的排名靠前的关键词的数量,评价了 RAKE 的准确度。例如:



$ python evaluate_rake.py data/docs/fao_test/ 10

...

Precision 4.44 Recall 5.17 F-Measure 4.78


精度(Precision)告诉我们在这些被提取的关键词中正确的百分比,回召(Recall)告诉我们在所有正确的关键词中,正确提取的百分比,F量度是两者的结合。


为了改善RAKE的性能,我们可以运行我为这个教程准备好的另一个脚本。它循环运转,每次使用不同的参数集,并且评估每次运转的关键词的质量。然后它返回在这个数据集上性能最好的参数。例如:


$ python optimize_rake.py data/docs/fao_test/ 10

Best result at 5.56

with min_char_length 3

max_words_length 5

min_keyword_frequency 6


这些值表示在这样长的文档上,RAKE最好不包括超过5个词的候选词,并且只考虑出现少于6词的候选词。


总结一下,RAKE是一个简单的关键词提取库,它主要解决找包含频繁词的多词短语。它的强大之处在于它的易用性,它的缺点是它有限的准确度,参数配置的必须,还有它抛弃很多有效短语并且不归一化候选词。


4 用Java写的Maui提取关键词


Maui表示多用途自动主题索引。它是一个GPL许可用Java写的库,它的核心是机器学习工具包Weka。它是在多年的研究后,对关键词提取算法KEA的再现。跟RAKE相比,Maui支持:


不仅单从文本,还可以参照受控词表,提取关键词

通过用手工选择的关键词训练Maui改善准确度


4.1 配置Maui


Maui的源码在Github和Maven Central可以下载,但是最简单的方法是从Github下载Maui完整jar包,然后把jar复制到RAKE-tutorial工作目录。


4.2 Mauti:从文本提取关键词


为了比较,我们把Maui用于我们之前给RAKE使用的同一段文本。然而,因为Maui需要一个训练模型,我们首先需要创建一个训练模型。为了训练Maui,我们执行下列命令:


$ java -Xmx1024m -jar maui-standalone-1.1-SNAPSHOT.jar run data/docs/fao_test/w2167e.txt -m data/models/keyword_extraction_model -v none -n 8


这些参数解释如下,train用来表明我们在训练一个模型


-I 表示文档和他们的手工关键词的路径

-m 表示模型输出路径,

-v none表示没有词表或者执行关键词提取,

-o 2 表示抛弃任何候选词出现少于两次的候选词。


因为训练目录非常大,我相应增加了Java的堆空间。


一旦这个命令完成(它需要几分钟),我们就有了一个训练模型并且我们可以把它用在我们的RAKE例子中的同样文档,如下:


$ java -Xmx1024m -jar maui-standalone-1.1-SNAPSHOT.jar run data/docs/fao_test/w2167e.txt -m data/models/keyword_extraction_model -v none -n 8

1

$ java -Xmx1024m -jar maui-standalone-1.1-SNAPSHOT.jar run data/docs/fao_test/w2167e.txt -m data/models/keyword_extraction_model -v none -n 8


run命令既可以用于一个文件路径或者一个文本串。输出应该像这样:


Keyword: food security 0.4168253968253969

Keyword: household 0.361691628264209

Keyword: food production 0.3374377787854522

Keyword: nutrition 0.2319136508627857

Keyword: household food security and nutrition 0.21550774200419887

Keyword: rural development 0.1905299881996819

Keyword: forest resources 0.13882003874950102

Keyword: trees 0.13051174278199784


我们可以通过运行test命令评价关键词质量,它会使用Maui内置的评价:


$ java -Xmx1024m -jar maui-standalone-1.1-SNAPSHOT.jar test -l data/docs/fao_test/ -m data/models/keyword_extraction_model -v none -n 8

...

INFO MauiTopicExtractor - Avg. number of correct keyphrases per document: 2 +/- 1.03

INFO MauiTopicExtractor - Precision: 25 +/- 12.91

INFO MauiTopicExtractor - Recall: 26.16 +/- 15.07

INFO MauiTopicExtractor - F-Measure: 25.57


你可以得到显著提升的性能,如果你在整个手工标注文档集上训练Maui。但是确保从训练集中去掉你用于测试的文件。


如果你对用Maui提取术语有兴趣,仅用提高概率阈值。然后记数一个文档集合中最常用的一些词。


$ java -Xmx1024m -jar maui-standalone-1.1-SNAPSHOT.jar test -l data/docs/fao_test/ -m data/models/keyword_extraction_model -v none -n 100

$ cd data/docs/fao_test/

$ cat *.maui | sort | uniq -c | sort -n -r | head -n 20

14 FAO

11 used

11 training

11 supply

11 environment

10 market

10 developing countries

9 important

9 government

9 consumption

9 Asia

8 world

8 species

8 services


这给出了在这些文档中使用的术语种类的一个很好的指示。


4.3 Maui:用受控词表做关键词提取


假设我们在对一个文档集合的每个文档提取关键词。如果我们从文档的文本中提取关键词,他们受制于不一致性。一个作者可能会谈论“栽培树林”,另一个作者会说“人造树林”。为了对两个文档一致地使用相同关键词,用受控词表:一个术语列表、分类词典或者分类系统,是个好主意。用词表的另一个好处是它包含有助于提取过程的语义。比如,通过知道文档中“栽培树林”和“人工树林”等候选词是相关的,算法可以区分有联系的主题与联系少的主题。


Maui可以与任何RDF SKOS格式的词表工作,并且还有很多各领域的这样的可用词表。


在Maui中使用一个词表很容易。使用-v来指定词表文件的路径并且用-f指定它的格式,比如“skos”:


$ java -Xmx1024m -jar maui-standalone-1.1-SNAPSHOT.jar train -l data/docs/fao_train/ -m data/models/term_assignment_model -v data/vocabulary/agrovoc_en.rdf.gz -f skos

$ java -Xmx1024m -jar maui-standalone-1.1-SNAPSHOT.jar run data/docs/fao_test/w2167e.txt -m data/models/term_assignment_model -v data/vocabulary/agrovoc_en.rdf.gz -f skos

Keyword: Food security 0.5300188323917138

Keyword: Foods 0.4959033690020568

Keyword: Forestry 0.2994235942964757

Keyword: Forest products 0.29543300574208564

Keyword: Forest management 0.2359568256207246

Keyword: Community forestry 0.211907148358341

Keyword: Food production 0.19937233666335424

Keyword: Households 0.19101089588377723

Keyword: Forest resources 0.18298670742855433

Keyword: Natural resources 0.15789472654988765


这些关键词的两个主要优势是 a)它们与一个唯一的关联于这些短语实际含义的ID绑定,并且 b)他们对于任何由同一词表分析的文档会是一致的。


$ java -Xmx1024m -jar maui-standalone-1.1-SNAPSHOT.jar test -l data/docs/fao_test/ -m data/models/term_assignment_model -v data/vocabulary/agrovoc_en.rdf.gz -f skos

...

INFO MauiTopicExtractor - Avg. number of correct keyphrases per document: 2.94 +/- 1.57

INFO MauiTopicExtractor - Precision: 29.38 +/- 15.69

INFO MauiTopicExtractor - Recall: 36.18 +/- 17.6

INFO MauiTopicExtractor - F-Measure: 32.43


这里,在50个文档上训练后,我们使用默认特征和参数测试了Maui。在更多文档上训练并且也调整了参数后,性能可以提升35%甚至更多。


5 接下来有什么?


我们已经学到了关键词提取的核心准则并且用专门为这个任务设计的Python和Java库实验了。不论你使用的库或者编程语言,你现在可以开始把这些应用到你的项目中但是如果你想继续学习,这有一些选项:


了解更多关于Maui如何工作的问题,可以参考我的博士论文,其中详细解释了各个方面。在Maui的网站上也有一个文档。

运行更多实验,你可以下载并且尝试不同的关键词提取数据集和词表。


对比最先进的算法评估你自己的关键词提取算法,你可以在数据集上在SemEval的关键词提取测试中对它进行性能测试


如果你在上面某个中遇到问题,尽管通过AirPair网站来联系我。



Python开发者

微信号:PythonCoder

可能是东半球最好的 Python 微信号

--------------------------------------

投稿网址:top.jobbole.com

商务合作QQ:2302462408


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存