如何从一系列文本条目中提取常见/重要短语

73
我有一系列文本条目-来自MySQL数据库的原始HTML。我想找到这些条目中最常见的短语(不是单个最常见的短语,并且理想情况下,不强制逐字匹配)。
我的示例是Yelp.com上的任何评论,它显示给定餐厅数百条评论中的3个片段,格式为:
“试试汉堡”(在44篇评论中)
例如,此页面的“评论亮点”部分:

http://www.yelp.com/biz/sushi-gen-los-angeles/

我已经安装了NLTK并尝试了一些操作,但是对于它的选项感到有些不知所措。这似乎是一个普遍的问题,但我在这里搜索时没有找到简单明了的解决方案。

1
使用nltk,获取bigrams和trigrams非常容易,但我要找的是更有可能由7到8个单词组成的短语。我还没有想出如何让nltk(或其他方法)提供这样的“八元组”及以上内容。 - arronsky
也许你可以尝试使用基于图的算法,比如TextRank - https://github.com/ceteri/pytextrank - Ricardo Rivaldo
4个回答

103

我怀疑你不只是想要最常见的短语,而是想找最有趣的搭配词。否则,你可能会得到由常用单词组成的短语过多,而较少有趣和信息丰富的短语。

为了做到这一点,你需要从数据中提取n-gram,然后找出具有最高点互信息(PMI)的短语,也就是说,你需要找到那些共同出现的单词比随机出现的频率更高的单词。

NLTK搭配词入门介绍了如何用大约7行代码来实现这一点,例如:

import nltk
from nltk.collocations import *
bigram_measures = nltk.collocations.BigramAssocMeasures()
trigram_measures = nltk.collocations.TrigramAssocMeasures()

# change this to read in your data
finder = BigramCollocationFinder.from_words(
    nltk.corpus.genesis.words('english-web.txt'))

# only bigrams that appear 3+ times
finder.apply_freq_filter(3)

# return the 10 n-grams with the highest PMI
finder.nbest(bigram_measures.pmi, 10)

3
我同意,看了那个页面后,我可以理解二元组和三元组,但是如何扩展到n元组呢?我认为需要长度大于5的短语才能真正有趣,也许我表达得不好,但是这个演示页面只让我获取2个或3个单词的组合? - arronsky
5
为此,我认为你需要扩展nltk.collocations.AbstractCollocationFinder,可以参考BigramCollocationFinder和TrigramCollocationFinder,详见http://nltk.googlecode.com/svn/trunk/doc/api/nltk.collocations-pysrc.html。但是,你确定你真的需要这么长的短语吗?在Yelp上,他们似乎只突出显示单个词和其中包含几个词的词组,在你提供的例子中,他们有生鱼片、小东京和鱼。然后他们选择包含每个有趣的单词或短语的完整句子。 - dmcer
7
这个。我认为你完全正确。观察非常精彩(且简洁)! - arronsky

5
如果你只想得到大于3个ngrams,可以尝试这个方法。我假设你已经去除了所有的垃圾,比如HTML等。
import nltk
ngramlist=[]
raw=<yourtextfile here>

x=1
ngramlimit=6
tokens=nltk.word_tokenize(raw)

while x <= ngramlimit:
  ngramlist.extend(nltk.ngrams(tokens, x))
  x+=1

可能不是很符合Python编程规范,因为我自己也只学了一个月左右,但这可能会有所帮助!


1
-1 对我没有任何帮助。我和原帖作者处于同样的情况,你的方法只是返回了一个遵循原始文本结构的巨大元组列表。我该怎么办? - magnetar
1
一旦你有了那个列表,你需要循环遍历它来计算唯一ngrams的出现次数。其中一种方法是创建一个字典,其中键是ngram,并在每次匹配时递增它。 - Toby
我也不太明白。你如何计算唯一的 n 元组?这是一个由单个单词组成的袋子。 - Union find

5

我真的不明白分块与此有什么关系。 - magnetar
3
分块可以解析短语,一旦你有了短语,就可以识别常见且重要的短语。 - Jacob

0

首先,您可能需要删除所有HTML标签(搜索“<[^>]*>”并将其替换为“”)。之后,您可以尝试寻找每两个文本项之间最长的公共子串的幼稚方法,但我认为结果不会很好。

如果您先规范化单词(将它们缩减到基本形式,去除所有重音,将所有内容设置为小写或大写)然后进行分析,您可能会取得更好的效果。同样地,根据您想要实现的目标,如果允许一定的词序灵活性,即将文本项视为归一化单词的组袋,并测量组袋内容相似性,您可能能够更好地聚类文本项。

我曾在这里发表过类似(尽管不完全相同)的主题评论。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接