Python での NLTK ステミング異常の修正

Shikha Chaudhary 2023年6月21日
  1. Python での NLTK ステミング異常の修正
  2. Python の NLTKPorterStemmer モジュールのステミング異常の修正
  3. Python の NLTK でのステマーに対するレマタイザーの使用
  4. まとめ
Python での NLTK ステミング異常の修正

ステミングは、その名前が示すように、単語を原形に還元する方法です。 たとえば、happinesshappilyhappier などの単語はすべて語根の単語 happy に分類されます。

Python では、Python の NLTK ライブラリによって提供されるさまざまなモジュールの助けを借りてこれを行うことができますが、期待した結果が得られない場合があります。 たとえば、fairlyfairli になり、fair ではなく、NLTK ライブラリの PorterStemmer モジュールになります。

この記事では、このような違いが発生する理由と、必要なルート ワードを取得するためにそれらを修正する方法について説明します。 それでは、コーヒーを飲みながら読んでください!

Python での NLTK ステミング異常の修正

Python の NLTK ライブラリにはいくつかのステマーがありますが、最も一般的に使用されるのは PorterStemmer です。 PorterStemmer がどのように機能するかの例を次に示します。

まず、このコードで何が起こっているかを理解しましょう。

最初に PorterStemmernltk ライブラリからインポートし、そのインスタンスを作成します。 これで、このインスタンスを使用して、nltk ライブラリで提供されている stem() 関数を使用して、指定された単語のリストをステミングできます。

from nltk.stem import PorterStemmer

p = PorterStemmer()

similar_words = ["act", "acting", "acts"]

for x in similar_words:
    print(x, "comes from", p.stem(x))

出力:

act comes from act
acting comes from act
acts comes from act

このリストのすべての単語は、PorterStemmer モジュールの助けを借りて、ルート単語 act に縮小されます。 しかし、これはこのモジュールが常に機能する方法ではありません。

別の例を次に示します。

from nltk.stem import PorterStemmer

p = PorterStemmer()
print(p.stem("loudly"))

出力:

'loudli'

今度は loud ではなく loudli として出力が得られることがわかります。

なぜこれが起こるのだろうか。 そして、さらに重要なことに、これを修正する方法は?

Python の NLTKPorterStemmer モジュールのステミング異常の修正

PorterStemmer モジュールは 5つのフェーズで動作し、それぞれに独自のルールと手順があります。 さらに、それが一般的に与える結果は英語に基づいています。

これは、loudi という単語は私たちが望んでいたものではありませんが、PorterStemmer モジュールのルールに従って正しくステミングされた単語であることを意味します。

ただし、良いニュースもあります。NLTK モジュールのすべてのステマーが同じように機能するわけではありません。 今度は、SnowballStemmer を使って loudly という単語をステミングしてみましょう。

ここで、言語をパラメーターとして SnowballStemmer() 関数に渡す必要があることに注意してください。

from nltk.stem import SnowballStemmer

s = SnowballStemmer("english")
print(s.stem("loudly"))

出力:

'loud'

SnowballStemmer は確かに PorterStemmer とは異なる一連のルールを使用しているため、今回は目的の出力が得られていることがわかります。 ここで興味深いことがあります。

これらのモジュールの両方を使用して、単語 actor のステミングを試してみてください。 これは以下で行われます。

from nltk.stem import SnowballStemmer
from nltk.stem import PorterStemmer

p = PorterStemmer()
print(p.stem("actor"))


s = SnowballStemmer("english")
print(s.stem("actor"))

出力:

'actor'
'actor'

これらのモジュールはどちらも、ルート ワード act ではなく、同じ出力 actor を返すことがわかります。 LancasterStemmer と呼ばれる別のステマーでこれを試してみましょう。

from nltk.stem import LancasterStemmer

l = LancasterStemmer()
print(l.stem("actor"))

出力:

'act'

今度は目的の出力 act が得られていることがわかります。

さまざまなステマーが、さまざまな単語でさまざまな出力を生成する様子を確認しました。

他のさまざまなステマーを使用できますが、それらはすべて何らかのアルゴリズムに基づいているため、目的の出力が得られない可能性が常にあります。 また、これらのステマーは、アルゴリズムに基づいて単語を切り捨てる際に非常に厳密です。

また、ステミングは主にサフィックス部分で機能し、プレフィックスまたはインフィックスを削除して単語を解決するほどスマートではありません. ステミング アルゴリズムは、単語の意味と結果の語根を調べることさえしません。

この例を見てください。

これは、末尾に ing が付いたランダムな文字列で、ステマーはこの接尾辞を削除して出力を返します。

from nltk.stem import PorterStemmer

p = PorterStemmer()
print(p.stem("wkhfksafking"))

出力:

'wkhfksafk'

したがって、この問題を解決するには、レンマタイザーを使用することをお勧めします。 レマタイザーの働きを詳しく見てみましょう。

Python の NLTK でのステマーに対するレマタイザーの使用

ステマーとは異なり、レンマタイザーは単語を形態学的に分析し、単語が使用されるコンテキストに基づいて最も適切なレンマを見つけることができます。 補題は語幹とは異なり、すべての語形の基本形であるため、語幹と同じではないことに注意してください。

レンマタイザーがステマーよりも優れていることを示す例を見てみましょう。

ここでは、PorterStemmer を使用していくつかの単語をステミングしています。

from nltk.stem import PorterStemmer

p = PorterStemmer()

w = ["studies", "studying", "study"]

for i in w:
    print(p.stem(i))

出力:

studi
studi
studi

得られる出力があまり役に立たないことがわかります。 先に進んで、同じ単語セットでレンマタイザーを使用しましょう。

最初に WordNetLemmatizer モジュールをインポートし、そのインスタンスを作成します。 次に、lemmatize() 関数を for ループで使用して、各単語の補題を見つけます。

from nltk.stem import WordNetLemmatizer

l = WordNetLemmatizer()

w = ["studies", "studying", "study"]

for i in w:
    print(l.lemmatize(i))

出力:

study
studying
study

今回はばかげた出力は得られず、すべての言葉は理にかなっています。

これが、レンマタイザーを使用する方がステマーを使用するよりも優れている理由です。

ステマーとレンマタイザーの詳細については、この リンクを参照してください。

まとめ

この記事では、Python の NLTK のステマーとレンマタイザーについて説明しました。 ステマーがときどきばかげた結果を返す方法と理由、およびレンマタイザーを使用してより良い結果を得る方法について説明しました。