私はPorterStemmerとSnowballを試しましたが、両方ともすべての単語で機能するわけではなく、非常に一般的なものがいくつかありません。
私のテストワードは、「cats running ran cactus cactuses cacti community community」であり、両方とも半分以下になります。
以下も参照してください:
Pythonを知っている場合、- Natural Language Toolkit(NLTK) には WordNet を使用する非常に強力なレマタイザーがあります。
このレンマタイザーを初めて使用する場合は、使用する前にコーパスをダウンロードする必要があります。これは次の方法で実行できます。
>>> import nltk
>>> nltk.download('wordnet')
これは一度だけ行う必要があります。コーパスをダウンロードしたと仮定すると、次のように動作します。
>>> from nltk.stem.wordnet import WordNetLemmatizer
>>> lmtzr = WordNetLemmatizer()
>>> lmtzr.lemmatize('cars')
'car'
>>> lmtzr.lemmatize('feet')
'foot'
>>> lmtzr.lemmatize('people')
'people'
>>> lmtzr.lemmatize('fantasized','v')
'fantasize'
nltk.stem module には他のレンマタイザーがありますが、私は自分で試していません。
stanford nlp を使用して、見出し語化を実行します。私はここ数日間で同様の問題に悩まされています。この問題を解決するのに役立つstackoverflowに感謝します。
import Java.util.*;
import edu.stanford.nlp.pipeline.*;
import edu.stanford.nlp.ling.*;
import edu.stanford.nlp.ling.CoreAnnotations.*;
public class example
{
public static void main(String[] args)
{
Properties props = new Properties();
props.put("annotators", "tokenize, ssplit, pos, lemma");
pipeline = new StanfordCoreNLP(props, false);
String text = /* the string you want */;
Annotation document = pipeline.process(text);
for(CoreMap sentence: document.get(SentencesAnnotation.class))
{
for(CoreLabel token: sentence.get(TokensAnnotation.class))
{
String Word = token.get(TextAnnotation.class);
String lemma = token.get(LemmaAnnotation.class);
System.out.println("lemmatized version :" + lemma);
}
}
}
}
また、後で分類器で使用される場合は、出力語彙を最小化するためにストップワードを使用することをお勧めします。ジョン・コンウェルが書いた coreNlp 拡張機能をご覧ください。
このSnowballデモサイト で用語のリストを試しましたが、結果は大丈夫です...
ステマーは、語形変化した形を一般的な語根に変換することになっています。そのルートを「適切な」辞書Wordにすることは、実際にはステマーの仕事ではありません。そのためには、 形態学的/オルソグラフィックアナライザー を確認する必要があります。
この質問 はほぼ同じことだと思います。その質問に対するKaarelの答えは、私が2番目のリンクを取得した場所です。
ステマーとレンマタイザーの議論が続いています。効率よりも精度を優先することです。言語的に意味のあるユニットを達成するために、整理し、同じキーの下でWordとそのバリエーションにインデックスを付けながら、最小限のコンピューティングジュースを使用する必要があります。
ステマーvsレンマタイザー を参照
python NLTKの例を次に示します。
>>> sent = "cats running ran cactus cactuses cacti community communities"
>>> from nltk.stem import PorterStemmer, WordNetLemmatizer
>>>
>>> port = PorterStemmer()
>>> " ".join([port.stem(i) for i in sent.split()])
'cat run ran cactu cactus cacti commun commun'
>>>
>>> wnl = WordNetLemmatizer()
>>> " ".join([wnl.lemmatize(i) for i in sent.split()])
'cat running ran cactus cactus cactus community community'
Martin Porterの公式ページには、 PHPのPorter Stemmer と 他の言語 が含まれています。
ポーターアルゴリズムのようなものから始めなければならないが、良いステミングに本当に真剣な場合は、ルールを追加してデータセットに共通する誤ったケースを修正し、最終的にルールに多くの例外を追加することで洗練する。これはキー/値のペア(dbm/hash/dictionaries)を使用して簡単に実装できます。キーは検索するWordで、値は元の単語を置換する語幹です。私がかつて働いていた商用の検索エンジンは、修正されたポーターアルゴリズムのいくつかの例外で800になりました。
http://wordnet.princeton.edu/man/morph.3WN
私の多くのプロジェクトでは、より積極的なポーターステミングよりも、レキシコンベースのWordNet lemmatizerの方が好きです。
http://wordnet.princeton.edu/links#PHP には、PHP APIへのWNインターフェイスへのリンクがあります。
Stack Overflowと私が出会ったブログに関するさまざまな回答に基づいて、これは私が使用している方法であり、実際の単語を非常によく返すようです。アイデアは、着信テキストを単語の配列に分割し(好きな方法を使用)、それらの単語の品詞(POS)を見つけ、それを使用して単語の語幹化と見出し語化を支援することです。
上記のサンプルは、POSを判別できないためうまく機能しません。ただし、実際の文を使用すると、状況はずっと良くなります。
import nltk
from nltk.corpus import wordnet
lmtzr = nltk.WordNetLemmatizer().lemmatize
def get_wordnet_pos(treebank_tag):
if treebank_tag.startswith('J'):
return wordnet.ADJ
Elif treebank_tag.startswith('V'):
return wordnet.VERB
Elif treebank_tag.startswith('N'):
return wordnet.NOUN
Elif treebank_tag.startswith('R'):
return wordnet.ADV
else:
return wordnet.NOUN
def normalize_text(text):
Word_pos = nltk.pos_tag(nltk.Word_tokenize(text))
lemm_words = [lmtzr(sw[0], get_wordnet_pos(sw[1])) for sw in Word_pos]
return [x.lower() for x in lemm_words]
print(normalize_text('cats running ran cactus cactuses cacti community communities'))
# ['cat', 'run', 'ran', 'cactus', 'cactuses', 'cacti', 'community', 'community']
print(normalize_text('The cactus ran to the community to see the cats running around cacti between communities.'))
# ['the', 'cactus', 'run', 'to', 'the', 'community', 'to', 'see', 'the', 'cat', 'run', 'around', 'cactus', 'between', 'community', '.']
これはおもしろそうです:MIT Java WordnetStemmer: http://projects.csail.mit.edu/jwi/api/edu/mit/jwi/morph/WordnetStemmer。 html
LemmaGen -C#3.0で書かれたオープンソースライブラリを見てください。
テスト単語の結果( http://lemmatise.ijs.si/Services )
見出し語化の上位pythonパッケージ(特定の順序なし)は、spacy
、nltk
、gensim
、pattern
、CoreNLP
、およびTextBlob
です。 SpaCyとgensimの実装(パターンに基づく)が好まれるのは、WordのPOSタグを識別し、適切な補題を自動的に割り当てるためです。はより意味のある補題を与え、意味をそのまま保持します。
NltkまたはTextBlobを使用する予定がある場合は、適切なPOSタグを手動で検索し、適切な見出し語を検索する必要があります。
spaCyの補題の例:
# Run below statements in terminal once.
pip install spacy
spacy download en
import spacy
# Initialize spacy 'en' model
nlp = spacy.load('en', disable=['parser', 'ner'])
sentence = "The striped bats are hanging on their feet for best"
# Parse
doc = nlp(sentence)
# Extract the lemma
" ".join([token.lemma_ for token in doc])
#> 'the strip bat be hang on -PRON- foot for good'
Gensimでの補題の例:
from gensim.utils import lemmatize
sentence = "The striped bats were hanging on their feet and ate best fishes"
lemmatized_out = [wd.decode('utf-8').split('/')[0] for wd in lemmatize(sentence)]
#> ['striped', 'bat', 'be', 'hang', 'foot', 'eat', 'best', 'fish']
上記の例は、この lemmatization ページから引用されています。
Luceneで検索してください。PHPポートがあるかどうかはわかりませんが、Luceneが多くのプラットフォームで利用できることは知っています。 Luceneは、OSS(Apache製)のインデックス作成および検索ライブラリです。当然のことながら、コミュニティエクストラには興味深いものがあります。少なくとも1つの言語でどのように処理されるかを学習できるため、「アイデア」をPHPに翻訳できます。
Morphaステム機能を使用できます。 Javaアプリケーションから使用する場合、UWには Maven centralにモーファステマーがアップロードされています があります。使いやすくするラッパーがあります。依存関係として追加し、edu.washington.cs.knowitall.morpha.MorphaStemmer
クラスを使用するだけです。インスタンスはスレッドセーフです(元のJFlexには不必要にローカル変数のクラスフィールドがありました)。クラスをインスタンス化して、morpha
とステムするWordを実行します。
new MorphaStemmer().morpha("climbed") // goes to "climb"
NLTKのステマーの最新バージョンはSnowballです。
ここで使用方法の例を見つけることができます:
http://nltk.googlecode.com/svn/trunk/doc/api/nltk.stem.Snowball2-pysrc.html#demo
StompChickenが述べた質問に対する私の答えを引用することができたら:
ここでの中心的な問題は、ステミングアルゴリズムが音声ベースで動作し、使用している言語を実際に理解していないことです。
言語を理解しておらず、用語の辞書からは実行されないため、「run」/「ran」などの不規則なケースを適切に認識して対応する方法がありません。
不規則なケースを処理する必要がある場合は、別のアプローチを選択するか、ステマーが処理した後に実行する独自の修正辞書でステミングを強化する必要があります。
.Net luceneには、ポーターステマーが組み込まれています。あなたはそれを試すことができます。ただし、ポーターのステミングでは、補題を導出するときにWordのコンテキストは考慮されません。 (アルゴリズムとその実装を確認すると、その仕組みがわかります)
Spacy (ベーステキストの解析とタグ付け)および Textacy (Spacyの上に構築された高レベルのテキスト処理)を使用することを強くお勧めします。
語彙化された単語 Spacyでデフォルトで利用可能 トークンの.lemma_
属性として、テキストはテキスト化され、他の多くのテキスト前処理をtextacyで行うことができます。たとえば、 用語のバッグを作成中または単語 、または一般的にそれを必要とする処理を実行する直前。
コードを書く前に両方をチェックすることをお勧めします。これにより、多くの時間を節約できます。
Javaでは、 tartargus-Snowball を使用して単語をステミングします
Maven:
<dependency>
<groupId>org.Apache.lucene</groupId>
<artifactId>lucene-Snowball</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
サンプルコード:
SnowballProgram stemmer = new EnglishStemmer();
String[] words = new String[]{
"testing",
"skincare",
"eyecare",
"eye",
"worked",
"read"
};
for (String Word : words) {
stemmer.setCurrent(Word);
stemmer.stem();
//debug
logger.info("Origin: " + Word + " > " + stemmer.getCurrent());// result: test, skincar, eyecar, eye, work, read
}
ここでこれを試してください: http://www.twinword.com/lemmatizer.php
デモにクエリを入力した"cats running ran cactus cactuses cacti community communities"
と、オプションのフラグ["cat", "running", "run", "cactus", "cactus", "cactus", "community", "community"]
を含むALL_TOKENS
を取得しました。
サンプルコード
これはAPIなので、どの環境からでも接続できます。 PHP REST呼び出しは次のようになります。
// These code snippets use an open-source library. http://unirest.io/php
$response = Unirest\Request::post([ENDPOINT],
array(
"X-Mashape-Key" => [API KEY],
"Content-Type" => "application/x-www-form-urlencoded",
"Accept" => "application/json"
),
array(
"text" => "cats running ran cactus cactuses cacti community communities"
)
);
Martin PorterはSnowball(ステミングアルゴリズムの言語)を作成し、Snowballの「English Stemmer」を書き直しました。 CおよびJava用の英語のステマーがあります。
彼は、Porter Stemmerが歴史的な理由で再実装されたonlyであると明示的に述べているため、Porter Stemmerに対するステミングの正確さをテストすると、結果が得られます(すべきです)もう知っている。
から http://tartarus.org/~martin/PorterStemmer/index.html (エンファシス鉱山)
ポーターステマーは、「frozen」と見なされる必要があります。つまり、厳密に定義されており、さらに変更する必要はありません。ステム機能として、Snowball EnglishまたはPorter2ステム機能よりもわずかに劣ります。これは、それに由来し、時折改善されることがあります。したがって、実際の作業には、新しいSnowballステマーが推奨されます。 Porterステマーは、実験を正確に再現する必要があるステミングを含むIR研究作業に適しています。
ポーター博士は、ポーターステマーの代わりに英語またはポーター2ステマーを使用することを提案しています。英語のステマーは、@-StompChickenが以前に回答したように、実際に デモサイト で使用されているものです。