2017-07-19 4 views
2

ich ein Lemma tokenizer mit Spacy für schrieb Scikit-Learn auf der Grundlage ihrer example, es OK Standalone funktioniert:Spacy und Scikit-Learn vectorizer

import spacy 
from sklearn.feature_extraction.text import TfidfVectorizer 

class LemmaTokenizer(object): 
    def __init__(self): 
     self.spacynlp = spacy.load('en') 
    def __call__(self, doc): 
     nlpdoc = self.spacynlp(doc) 
     nlpdoc = [token.lemma_ for token in nlpdoc if (len(token.lemma_) > 1) or (token.lemma_.isalnum()) ] 
     return nlpdoc 

vect = TfidfVectorizer(tokenizer=LemmaTokenizer()) 
vect.fit(['Apples and oranges are tasty.']) 
print(vect.vocabulary_) 
### prints {'apple': 1, 'and': 0, 'tasty': 4, 'be': 2, 'orange': 3} 

Es ist jedoch mit in GridSearchCV Fehler gibt, kann ein umluftunabhängiges Beispiel unten:

from sklearn.feature_extraction.text import TfidfVectorizer 
from sklearn.svm import SVC 
from sklearn.multiclass import OneVsRestClassifier 
from sklearn.pipeline import Pipeline 
from sklearn.grid_search import GridSearchCV 

wordvect = TfidfVectorizer(analyzer='word', strip_accents='ascii', tokenizer=LemmaTokenizer()) 
classifier = OneVsRestClassifier(SVC(kernel='linear')) 
pipeline = Pipeline([('vect', wordvect), ('classifier', classifier)]) 
parameters = {'vect__min_df': [1, 2], 'vect__max_df': [0.7, 0.8], 'classifier__estimator__C': [0.1, 1, 10]} 
gs_clf = GridSearchCV(pipeline, parameters, n_jobs=7, verbose=1) 

from sklearn.datasets import fetch_20newsgroups 
categories = ['comp.graphics', 'rec.sport.baseball'] 
newsgroups = fetch_20newsgroups(remove=('headers', 'footers', 'quotes'), shuffle=True, categories=categories) 
X = newsgroups.data 
y = newsgroups.target 
gs_clf = gs_clf.fit(X, y) 

### AttributeError: 'spacy.tokenizer.Tokenizer' object has no attribute '_prefix_re' 

der Fehler erscheint nicht, wenn ich spacigen außerhalb des Konstruktor der tokenizer laden, dann die GridSearchCV läuft:

spacynlp = spacy.load('en') 
    class LemmaTokenizer(object): 
     def __call__(self, doc): 
      nlpdoc = spacynlp(doc) 
      nlpdoc = [token.lemma_ for token in nlpdoc if (len(token.lemma_) > 1) or (token.lemma_.isalnum()) ] 
      return nlpdoc 

Aber das bedeutet, dass jeder meiner n_jobs vom GridSearchCV die gleiche spacynlp Objekt zuzugreifen und diese aufrufen, wird es unter diesen Stellen geteilt, die die Fragen verlässt:

  1. Ist das spacynlp Objekt von spacy.load('en') sicher von mehreren Jobs in GridSearchCV verwendet werden?
  2. Ist dies der richtige Weg, Spacy-Aufrufe innerhalb eines Tokenizers für scikit-learn zu implementieren?

Antwort

3

Sie verschwenden Zeit, indem Sie Spacy für jede Parametereinstellung im Raster ausführen. Der Speicheraufwand ist ebenfalls signifikant. Sie sollten alle Daten einmal durch Spacy ausführen und auf der Festplatte speichern und dann einen vereinfachten Vektorisierer verwenden, der vorlemmatisierte Daten einliest. Schauen Sie sich die tokenizer, analyser und preprocessor Parameter von TfidfVectorizer an. Es gibt viele Beispiele für den Stack-Überlauf, die zeigen, wie ein benutzerdefinierter Vektorisierer erstellt wird.

+0

Dies sind gute Punkte, und das könnte sehr gut sein, was stattdessen zu tun ist. Letztendlich möchte ich aber die spacY-Tokenisierung mit verschiedenen Optionen (zB POS) als Teil der Hyper-Parameter-Grid-Suche haben, daher meine Fragen. – tkja

+0

Sie können das auch tun. Speichern Sie Ihre Daten wie folgt: '[{" token ":" cats "," lemma ":" cat "}, {...}]'. Das sind im Grunde Spacy-Sätze, die zu JSON konvertiert wurden. Schreiben Sie einen Pipelineschritt, der dies als Eingabe verwendet und einen Parameter zur Ausgabe entweder eines Tokens oder eines Lemmas hat, und dort haben Sie es - Tokenisierung ist ein Teil Ihrer Rastersuche. – mbatchkarov

Verwandte Themen