如何过滤单词排列以找到语义正确的n-gram?(Python 3, NLTK)

9 投票
3 回答
1906 浏览
提问于 2025-04-19 23:18

我想从一个包含200个单词的列表中创建一些排列组合,这显然会导致一个非常庞大的可能组合数(最多5个单词组成一个短语)。为了有效地限制这个数字,我有两个方法:

  1. 通过词性过滤器来处理这些单词,这样生成的短语在语言上是合理的;
  2. 筛选出那些实际上是n-gram的排列组合,也就是说,它们有较高的PMI(点互信息)或可能性评分。

这个想法的第二部分让我有些困惑——我知道NLTK可以找到n-gram,但我看到的每个例子都是分析一个语料库,这样做是有道理的,因为需要频率分布。 但是,是否可以找到一个单词排列的PMI?

是否可以根据一个自定义语料库中找到的常见搭配来计算我的单词排列的PMI评分? 这能手动完成吗?

举个例子,虽然排列(冗长的茶)在语言上是合理的,但在上下文中并不是一个好的排列。

我知道如何在一段文本或语料库中找到常见的搭配,但这是一个非常独特的问题,我希望有人能给我一些建议。至少,帮我理清思路!

示例

**KW**
 Ball
 Bat
 Pinch
 Home
 Run
 Base
 Hitter
 Pitcher
 Call
 etc...

更多背景信息: 从这个列表中可以生成许多排列组合,但只有少数是有意义的。通过词性过滤器处理这个列表,可以生成在语言上合理的关键词,但不一定是语义上正确的,比如“Call Ball Hitter”。这是我的难点,我想要根据某种评分标准(比如PMI)来创建语义上正确的排列组合。我的想法是抓取一个网站,比如http://en.wikipedia.org/wiki/Baseball,找到其中的常见n-gram,然后根据这个语料库来判断关键词排列的相对语义强度。但我在概念化这个过程时遇到了困难,不确定这是否可行。不过,我真的很想听听其他人关于如何有效找到n-gram排列组合的想法!这个练习的核心是高效地排除无意义的排列,而不需要手动分类或评分所有内容!

3 个回答

0

你没有透露你的词性列表,但除非你的关键词列表比你展示的片段复杂得多,否则这似乎可以简单地理解为“找到列表中最长的单词序列”。确保一个短语合法的唯一方法是它出现在输入的文本中,所以PMI的计算其实并没有帮助。也许词性过滤根本就不需要。

words='Ball|Bat|Pinch|Home|Run|Base|Hitter|Pitcher|Call'
curl -s 'http://en.wikipedia.org/wiki/Baseball' |
grep -Eio "\<($words)( +($words))+\>"

(我试过用grep -w,但在我的OSX上,这和grep -o配合使用时效果不太好,所以我加了\<...\>作为单词边界。)

对于这个特定的URL和部分关键词列表,输出结果如下(经过sort -u | uniq -c | sort -rn过滤):

  18 home run
   2 base ball
   1 pinch hitter

(这个问题简单到我都懒得写Python脚本,直接用Requests就能轻松搞定。)

在更一般的情况下,像“投手投的球是个变速球”这样的句子包含了一些跨越树状结构边界的片段,你可能想要过滤掉这些片段(比如如果你把“the”加到你的词列表中,就会得到“*the ball the pitcher”),这时候你就需要一些语言学(或者统计学)的知识了。

1

我自己找到了一个不错的解决方案!这个方法是基于一篇文章的,链接在这里:http://research.microsoft.com/en-us/um/people/jfgao/paper/webngram.sigirws.v2.pdf。这个想法是,不要随便生成一堆乱七八糟的排列,然后再去筛选出一个语义上正确的。我们要做的,是一开始就只生成语义上正确的排列。这可以通过分阶段构建句子来实现,基本原则是n-1,也就是一个词只和前面的词有语义上的依赖

所以计划是找到相关语料库中的所有二元组(bigrams)及其出现频率。频率越高,这个表达式在语义上就越可能是正确的。假设你有一个这样的列表,里面的二元组在语料库中各出现了10次:

The man
a plan
in Panama
Panama City
Man Who
Who is
is awesome

接下来,你根据n-1原则分阶段构建句子。首先,从你的原始列表中选一个关键词。然后,在你的第二个列表中找到一个以这个词开头的二元组,后面跟着另一个词,把它们组合在一起。比如说,从原始列表中取出'THE'这个词,经过查找,你应该得到一个短语'THE THE MAN'。然后继续这个过程:找一个符合n-1原则的二元组,接着找一个以'man'开头的二元组。现在你得到了'THE THE MAN MAN WHO'。继续这个过程!这样应该能生成语义上顺序正确的短语(当然最后要去掉重复的句子)。

你们觉得怎么样?

5

我在这里随便想想——谷歌图书NGram查看器已经抓取了它的语料库,并公开了所有出现超过40次的[1,2,3,4,5]-grams的列表和它们的频率统计。因此,你可以拿你生成的每个ngram,去谷歌的ngram数据库查一下它的出现频率。出现次数多的ngram更有可能是语义上合理的。

... 不过缺点是,下载谷歌的整个ngram数据集大概有1TB那么大,我不知道他们有没有提供相关的API。

补充:

如果没有API我会感到很惊讶。此外,谷歌似乎不是唯一的选择,快速搜索一下发现:

撰写回答