J'essaie d'ajouter stemming à mon pipeline en PNL avec 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)) ])
Lorsque vous utilisez ce pipeline avec le CountVectorizer de sklearn, cela fonctionne. Et si je crée manuellement des fonctionnalités comme celle-ci, cela fonctionne également.
vectorizer = StemmedCountVectorizer(stemmer)
vectorizer.fit_transform(X)
tfidf_transformer = TfidfTransformer()
X_tfidf = tfidf_transformer.fit_transform(X_counts)
MODIFIER :
Si j'essaie ce pipeline sur mon ordinateur portable IPython, il affiche le [*] et rien ne se passe. Lorsque je regarde mon terminal, il donne cette erreur:
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'
Exemple
Voici l'exemple complet
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)
Si vous supprimez la racine des paramètres, cela fonctionne, sinon cela ne fonctionne pas.
MISE À JOUR :
Le problème semble être dans le processus de parallélisation car lors de la suppression n_jobs = -1 le problème disparaît.
Vous pouvez passer un appelable en tant que analyzer
au constructeur CountVectorizer
pour fournir un analyseur personnalisé. Cela semble fonctionner pour moi.
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())
Imprime:
(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']
Je sais que je suis un peu en retard pour poster ma réponse. Mais voilà, au cas où quelqu'un aurait encore besoin d'aide.
Voici l'approche la plus propre pour ajouter un stemmer de langue pour compter le vectoriseur en remplaçant 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')
Vous pouvez appeler librement les fonctions fit
et transform
de la classe CountVectorizer sur votre vectorizer_s
objet
Tu peux essayer:
def build_analyzer(self):
analyzer = super(CountVectorizer, self).build_analyzer()
return lambda doc:(stemmer.stem(w) for w in analyzer(doc))
et supprimez le __init__
méthode.