最近、NLTKのPorterステマーを使用しましたが、その出力と、使用した別のバージョンのPorterステマーの出力との間にいくつかの不一致が見つかりました。 これらの不一致をフォローアップしたところ、NLTKの実装に問題がある可能性があることがわかりました。
MartinPorter自身が収集した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.ビルド5646)]ダーウィン
詳細については、「help」、「copyright」、「credits」、または「license」と入力してください。
import nltk
nltk.stem.porter.PorterStemmer().stem_word('shiny')
「しに」
ここまでは順調ですね。 そして、これらの結果を、サンプルのユーザーdictファイル(voc.txt)の同じページで提供される期待される結果(output.txt)と比較すると、正しく表示されます。
スクリプト$ egrep -n '^ shiny $' voc.txt
18333:光沢がある
スクリプト$ egrep -n '^ shini $' output.txt
18333:しに
しかし、NLTKの結果を期待される結果ファイルの結果と体系的に比較すると、多くの不一致が見られます(形式:単語、適切な期待されるステミング、アスタリスクでマークされた不良なNLTKステミング)。
スクリプト$。/ show_bad_stemming_in_nltk.py voc.txt output.txt
修道院修道院*修道院
修道院修道院*修道院
abed ab * abe
absey absei * absey
[...]
wrying wry * wri
昨日昨日*昨日
昨日昨日*昨日
yongrey yongrei * yongrey
Ruby参照の実装に対するスポットチェックにより、NLTKの結果が実際に問題であることが確認されます。
スクリプト$ ruby porter_stemmer.rb
修道院
アッベイ
修道院
アッベイ
ベッド
ab
アブシー
アブセイ
苦しむ
苦しむ
昨日
昨日
昨日
昨日
yongrey
ヨンレイ
NLTKのポーターステマーが予期しない結果をもたらす単語の完全なリストを添付しました。
(このバグはバージョン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で次のように述べています。
添付されているのは、nltk-devに送信されたStuartRobinsonの修正です。 これは、最初に説明したRubyバージョンの新しい移植ではなく、以前のバージョンをさらに編集したもののようです。 この新しいバージョンを組み込む前に、test /stem.doctestに一連のテストケースを追加する必要があります。
これに「goodfirstbug」というラベルを貼っただけです。 「最初の良いバグ」は、stem.doctest(https://github.com/nltk/nltk/blob/master/nltk/test/stem.doctest)に一連のテストケースを追加することです。スチュアートの修正でも、それは素晴らしいことです!
ねえ、特に@alexrudnick 、これは今解決済みとしてマークする必要がありますか?
スキムすると、いいえのように見えますが、まだ解決されていません。 しかし、メンテナから聞きたいです。
@paulproteus –最終的に解決
スティーブンがマージしたばかりの私のPRの時点での_default_ステマーの動作は変更されていないことに注意してください。 マーティンのリファレンス実装(マーティンの元のアルゴリズムとは矛盾している)と一貫性のある動作を得るには、 mode=PorterStemmer.MARTIN_EXTENSIONS
をPorterStemmer
コンストラクターに明示的に渡す必要があります。
間違いなく、デフォルトモードとしてMARTIN_EXTENSIONS
を使用すると(リファレンス実装との一貫性を保つため)、ユーザーはPorterStemmer
と呼ばれるものがMartinのリファレンス実装のようにすぐに動作することを期待するためです。 問題は、それが下位互換性の破れであり、ひどく非自明なものになるということです。 NLTKをアップグレードするNLTKの以前の実装を使用している人は、ステムの一部が変更されたことに長い間気付かず、ユースケースによっては微妙なバグが発生する可能性があります。 もう1つのオプションは、デフォルト値をまったく持たず、すべてのユーザーがさまざまなモードのドキュメントを読み、使用するモードを明示的に選択することを要求することです。 これは下位互換性も損なうでしょうが、_明らかな_方法でそうするので(古い方法でステマーをインスタンス化しようとすると爆発します)、リリースノートを読まずにアップグレードを行う人々が追い出されることはありません。 そのアプローチは、上記の悪いシナリオのいずれかを回避しますが、ステマーのすべての新しいユーザーに、より多くの先行作業を要求するという犠牲を払って行われます。
どのオプションも完璧ではありません。 デフォルトとしてNLTK_EXTENSIONS
を選択しましたが、反対する余地があります。 誰か意見がありますか?
@ExplodingCabbage :私はあなたの最後のオプションを好みます。デフォルトはありません。リリースノートに適切な警告を付けて、次のメジャーリリース(作業が最初に表示されるマイナーリリースではありません)でそれを行います。 人々がドキュメントを読むことを余儀なくされ、あなたの仕事から利益を得るのは良いことだと思います。 他の人の考えを知りたいです。
こんにちは、みんな、
私はnltkでデフォルトのPorterStemmerを使用して検索エンジンバックエンドを作成してきましたが、他の多くのPorterステマー実装と同じように動作しないことを知りませんでした。 Javascriptを使用してフロントエンドで作業しているので、フロントエンドとバックエンドの語幹が異なるバグが発生しています。 nltkのデフォルトのPorterStemmerの動作をJavascriptで再作成して、ブラウザーで実行できるようにする必要がある場合は、何を確認する必要があるのか疑問に思いました。 私はおそらく誰か(多分@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実装に対してテストケースを実行して正しいことを確認することを検討してください。あなたの仕事の。
最も参考になるコメント
@paulproteus –最終的に解決