2016-03-23 1 views
8

Ich versuche stemming zu meiner Pipeline in NLP mit sklearn hinzuzufügen.hinzufügen Stemming-Unterstützung zu CountVectorizer (sklearn)

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)) ]) 

Wenn Sie diese Pipeline mit dem CountVectorizer von sklearn verwenden, funktioniert es. Und wenn ich die Funktionen manuell erstelle, funktioniert das auch.

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

EDIT:

Wenn ich diese Pipeline auf meinem IPython Notebook versuchen zeigt es die [*] und nichts passiert. Als ich in meinem Terminal aussehen, gibt es diesen Fehler:

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' 

Beispiel

Dies ist die komplette Beispiel

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) 

Wenn Sie aus den Parametern ergeben entfernen funktioniert es sonst funktioniert nicht.

UPDATE:

Das Problem scheint in der Parallelisierung Prozess zu sein, weil, wenn n_jobs Entfernen = -1 das Problem verschwinden.

+0

dies scheint ein Problem zu sein mit Beizen und Entkeimen. Wenn Sie zum Beispiel 'stemming' in ein importiertes Modul einfügen, wird es zuverlässiger unpickled. – joeln

+0

Könnten Sie bitte ein Beispiel oder einen Link angeben, um zu verstehen, was Sie gesagt haben? Wie wird 'stemming' in ein importiertes Modul eingefügt? Denn ohne die Parallelisierung ist die GridSearch ziemlich langsam mit einigen Parametern zu tunen. – dooms

+0

Für was es wert ist, kann ich Ihr komplettes Beispiel ohne Problem ausführen. Aber was ich meinte ist, den Code für 'stemming' zum Beispiel in' myutils.py' zu verschieben und 'from myutils import stemming' zu verwenden. – joeln

Antwort

1

können Sie versuchen:

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

und entfernen Sie die __init__ Methode.

+0

Es funktioniert nicht (geben Sie den gleichen Fehler) und ich brauche das Stemmer-Attribut. – dooms

+0

Können Sie mehr Informationen über den gedruckten Fehler geben? Welche Linie bricht zum Beispiel? – Till

+0

Ich verwende eine GridSearch mit n_jobs = -1, um die Arbeit zu parallelisieren. – dooms

14

Sie können einen aufrufbaren Code als analyzer an den CountVectorizer-Konstruktor übergeben, um einen benutzerdefinierten Analysator bereitzustellen. Dies scheint für mich zu funktionieren.

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()) 

Druckt:

(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'] 
+0

parameter = {'vect__analyzer': ['word', stemming]} Wenn Sie dies als Parameter für die Rastersuche verwenden, erhalten Sie den Fehler: AttributeError: 'module' Objekt hat kein Attribut 'stemming' – dooms

6

Ich weiß, ich bin etwas spät meine Antwort in der Veröffentlichung. Aber hier ist es, falls jemand noch Hilfe braucht.

Nach der sauberste Ansatz Sprache stemmer hinzufügen zu zählen vectorizer durch zwingende 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') 

Sie frei fit und transform Funktionen CountVectorizer Klasse aufrufen können über Ihre vectorizer_s Objekt