web-dev-qa-db-ja.com

CountVectorizerにステミングサポートを追加(sklearn)

Sklearnを使用して、NLPのパイプラインにステミングを追加しようとしています。

from nltk.stem.Snowball import FrenchStemmer

stop = stopwords.words('french')
stemmer = FrenchStemmer()


class StemmedCountVectorizer(CountVectorizer):
    def __init__(self, stemmer):
        super(StemmedCountVectorizer, self).__init__()
        self.stemmer = stemmer

    def build_analyzer(self):
        analyzer = super(StemmedCountVectorizer, self).build_analyzer()
        return lambda doc:(self.stemmer.stem(w) for w in analyzer(doc))

stem_vectorizer = StemmedCountVectorizer(stemmer)
text_clf = Pipeline([('vect', stem_vectorizer), ('tfidf', TfidfTransformer()), ('clf', SVC(kernel='linear', C=1)) ])

SklearnのCountVectorizerでこのパイプラインを使用すると、動作します。そして、このような機能を手動で作成した場合も機能します。

vectorizer = StemmedCountVectorizer(stemmer)
vectorizer.fit_transform(X)
tfidf_transformer = TfidfTransformer()
X_tfidf = tfidf_transformer.fit_transform(X_counts)

[〜#〜] edit [〜#〜]

IPython Notebookでこのパイプラインを試すと、[*]が表示され、何も起こりません。私の端末を見ると、このエラーが出ます:

Process PoolWorker-12:
Traceback (most recent call last):
  File "C:\Anaconda2\lib\multiprocessing\process.py", line 258, in _bootstrap
    self.run()
  File "C:\Anaconda2\lib\multiprocessing\process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Anaconda2\lib\multiprocessing\pool.py", line 102, in worker
    task = get()
  File "C:\Anaconda2\lib\site-packages\sklearn\externals\joblib\pool.py", line 360, in get
    return recv()
AttributeError: 'module' object has no attribute 'StemmedCountVectorizer'

完全な例はこちら

from sklearn.pipeline import Pipeline
from sklearn import grid_search
from sklearn.svm import SVC
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from nltk.stem.Snowball import FrenchStemmer

stemmer = FrenchStemmer()
analyzer = CountVectorizer().build_analyzer()

def stemming(doc):
    return (stemmer.stem(w) for w in analyzer(doc))

X = ['le chat est beau', 'le ciel est nuageux', 'les gens sont gentils', 'Paris est magique', 'Marseille est tragique', 'JCVD est fou']
Y = [1,0,1,1,0,0]

text_clf = Pipeline([('vect', CountVectorizer()), ('tfidf', TfidfTransformer()), ('clf', SVC())])
parameters = { 'vect__analyzer': ['Word', stemming]}

gs_clf = grid_search.GridSearchCV(text_clf, parameters, n_jobs=-1)
gs_clf.fit(X, Y)

パラメータからステミングを削除すると機能しますが、それ以外の場合は機能しません。

[〜#〜] update [〜#〜]

n_jobs = -1を削除すると問題がなくなるため、問題は並列化プロセスにあるようです。

18
dooms

CallableをanalyzerとしてCountVectorizerコンストラクターに渡して、カスタムアナライザーを提供できます。これは私のために働くようです。

from sklearn.feature_extraction.text import CountVectorizer
from nltk.stem.Snowball import FrenchStemmer

stemmer = FrenchStemmer()
analyzer = CountVectorizer().build_analyzer()

def stemmed_words(doc):
    return (stemmer.stem(w) for w in analyzer(doc))

stem_vectorizer = CountVectorizer(analyzer=stemmed_words)
print(stem_vectorizer.fit_transform(['Tu marches dans la rue']))
print(stem_vectorizer.get_feature_names())

プリントアウト:

  (0, 4)    1
  (0, 2)    1
  (0, 0)    1
  (0, 1)    1
  (0, 3)    1
[u'dan', u'la', u'march', u'ru', u'tu']
26
joeln

私は答えを投稿するのに少し遅れていることを知っています。しかし、誰かがまだ助けを必要とする場合のために、ここにあります。

以下は、build_analyser()をオーバーライドすることにより、カウントベクトライザーに言語ステマーを追加する最もクリーンなアプローチです。

from sklearn.feature_extraction.text import CountVectorizer
import nltk.stem

french_stemmer = nltk.stem.SnowballStemmer('french')
class StemmedCountVectorizer(CountVectorizer):
    def build_analyzer(self):
        analyzer = super(StemmedCountVectorizer, self).build_analyzer()
        return lambda doc: ([french_stemmer.stem(w) for w in analyzer(doc)])

vectorizer_s = StemmedCountVectorizer(min_df=3, analyzer="Word", stop_words='french')

vectorizer_sオブジェクトを介してCountVectorizerクラスのfitおよびtransform関数を自由に呼び出すことができます

15
Parth Gupta

あなたが試すことができます:

def build_analyzer(self):
    analyzer = super(CountVectorizer, self).build_analyzer()
    return lambda doc:(stemmer.stem(w) for w in analyzer(doc))

__init__メソッドを削除します。

1
Till