Nltk: Porter Stemmer 的输出与参考实现的输出不一致

创建于 2012-01-17  ·  8评论  ·  资料来源: nltk/nltk

我最近使用了 NLTK 的 Porter 词干分析器,发现它的输出与我使用过的另一个版本的 Porter 词干分析器的输出之间存在一些差异。 跟进这些差异后,我发现 NLTK 的实现可能存在一些问题。

这里有 Martin Porter 自己收集的 Porter 词干分析器的各种参考实现:

http://tartarus.org/~martin/PorterStemmer/

我尝试了 Ruby 对 NLTK 的健全性检查(它从标准输出中取出一个词并立即吐出其词干形式,也在标准输出中):

脚本 $ ruby​​ porter_stemmer.rb
闪亮的
信一

我对照 NLTK 进行了检查:

脚本 $ python
Python 2.6.1(r261:67515,2010 年 6 月 24 日,21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] 在达尔文上
输入“帮助”、“版权”、“信用”或“许可”以获取更多信息。

        import nltk
        nltk.stem.porter.PorterStemmer().stem_word('shiny')

'shini'

到现在为止还挺好。 如果我将这些结果与在同一页面上为示例用户 dict 文件 (voc.txt) 提供的预期结果 (output.txt) 进行比较,它们看起来是正确的:

脚本 $ egrep -n '^shiny$' voc.txt
18333:闪亮
脚本 $ egrep -n '^shini$' output.txt
18333:shini

但是,如果我系统地将 NLTK 结果与预期结果文件中的结果进行比较,我会看到很多差异(格式:单词、正确的预期词干、坏的 NLTK 词干以星号标记):

脚本 $ ./show_bad_stemming_in_nltk.py voc.txt output.txt
修道院 修道院 *修道院
修道院修道院 *修道院
abed ab *abe
阿布西阿布西*阿布西
[...]
苦苦哀求*wri
昨天昨天 *昨天
昨天昨天 *昨天
yongrey yongrei *yongrey

针对 Ruby 参考实现的抽查确认 NLTK 结果实际上是问题所在:

脚本 $ ruby​​ porter_stemmer.rb
修道院
阿贝
修道院
阿贝

AB
深渊
阿塞
绞尽脑汁
苦笑
昨天
昨天
昨天
昨天
永格雷
永雷

我附上了 NLTK 的 Porter 词干分析器提供意外结果的完整单词列表。

(此错误与 2.0b9 版有关。我怀疑它存在于所有以前的版本中,但我尚未确认。)

从 http://code.google.com/p/nltk/issues/detail?id=625 迁移


之前的评论

gregg.lind 在 2011-02-09T20:22:57.000Z 说:

如果没有其他人想要的话,我很乐意(在星期五之前)接受这个。 我经常使用这个模块。 格雷格·林德

StevenBird1 在 2011-02-14T07:14:49.000Z 说:

附件是 Stuart Robinson 的修复,发送到 nltk-dev。 这似乎是对先前版本的进一步编辑,而不是最初讨论的 Ruby 版本的新移植。 在合并这个新版本之前,我们需要将一组测试用例添加到 test/stem.doctest。

goodfirstbug

最有用的评论

@paulproteus – 终于解决了

所有8条评论

我只是在这个上贴了“goodfirstbug”标签。 “好的第一个错误”将添加一堆测试用例到 stem.doctest (https://github.com/nltk/nltk/blob/master/nltk/test/stem.doctest)——如果你想合并在 Stuart 的修复中,那太好了!

大家好,尤其是@alexrudnick ,现在应该将其标记为已解决吗?

略读一下,看起来没有,它还没有解决。 但想听听维护者的意见。

@paulproteus – 终于解决了

请注意,Steven 刚刚合并的 PR 的 _default_ 词干分析器行为没有改变; 您需要显式地将mode=PorterStemmer.MARTIN_EXTENSIONS传递给PorterStemmer构造函数以获得与 Martin 的参考实现(它们本身与 Martin 的原始算法不一致)一致的行为。

可以说,将MARTIN_EXTENSIONS作为默认模式(为了与参考实现保持一致)会更好,因为用户会期望名为PorterStemmer东西像 Martin 的参考实现一样开箱即用。 问题是这会破坏向后兼容性,而且非常不明显。 使用 NLTK 先前实现升级 NLTK 的人可能在很长一段时间内都没有注意到他们的词干发生了变化,这可能会根据他们的用例引入细微的错误。 另一种选择是根本没有默认值,并要求每个用户阅读不同模式的文档并明确选择要使用的模式。 这也会破坏向后兼容性,但会以_明显_的方式这样做(只是尝试以旧方式实例化词干分析器会爆炸),因此不会在不阅读发行说明的情况下进行升级的人被发现。 这种方法可以避免上述任何一种糟糕的情况,但代价是要求词干分析器的每个新用户进行更多的前期工作。

没有一个选项是完美的。 我已选择将NLTK_EXTENSIONS作为默认值,但仍有不同意的余地。 有人有意见吗?

@ExplodingCabbage :我赞成你的最后一个选项,没有默认值,并在下一个主要版本(不是你的作品首先出现的次要版本)中这样做,并在发行说明中给出适当的警告。 我认为让人们被迫阅读文档并从您的工作中受益是有好处的。 我很想知道其他人的想法。

嗨,大家好,

我一直在用 nltk 中的默认 PorterStemmer 编写一个搜索引擎后端,但不知道它的行为方式与许多其他 Porter Stemmer 实现不同。 现在我正在使用 Javascript 处理前端,我遇到了前端和后端词干不同的错误。 我想知道如果我需要在 Javascript 中重新创建 nltk 的默认 PorterStemmer 行为,我应该看什么,以便我可以在浏览器中运行它。 我希望也许有人(也许@ExplodingCabbage ?)可以指出我正确的方向。

我真的没有时间使用 MARTIN_EXTENSIONS 模式重新索引所有内容,因为这需要数周时间才能完成...

@josephcc porter.py基本上没有依赖关系,也没有做任何深刻或神奇的事情,只是一系列的字符串操作。 您只需要将PorterStemmer类移植到 JavaScript,仅保留if self.mode == self.NLTK_EXTENSIONS分支并丢弃其他分支的逻辑。

诚然,这不是一项 5 分钟的任务或万无一失的任务,但可行。 另请查看https://github.com/nltk/nltk/blob/develop/nltk/test/unit/test_stem.py 中的PorterTest并考虑在那里针对您的 JavaScript 实现运行测试用例以检查正确性你的工作。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

libingnan54321 picture libingnan54321  ·  3评论

ndvbd picture ndvbd  ·  4评论

alvations picture alvations  ·  4评论

talbaumel picture talbaumel  ·  4评论

chaseireland picture chaseireland  ·  3评论