sklearn: Cómo acelerar un vectorizador (por ejemplo, Tfidfvectorizer)

Después de perfilar a fondo mi progtwig, he podido señalar que el vectorizador está disminuyendo su velocidad.

Estoy trabajando en datos de texto, y dos líneas de vectorización simple de tfidf unigram están ocupando el 99.2% del tiempo total que el código tarda en ejecutarse.

Aquí hay un ejemplo ejecutable (esto descargará un archivo de entrenamiento de 3 mb en su disco, omita las partes de urllib para que se ejecuten en su propia muestra):

##################################### # Loading Data ##################################### import urllib from sklearn.feature_extraction.text import TfidfVectorizer import nltk.stem raw = urllib.urlopen("https://s3.amazonaws.com/hr-testcases/597/assets/trainingdata.txt").read() file = open("to_delete.txt","w").write(raw) ### def extract_training(): f = open("to_delete.txt") N = int(f.readline()) X = [] y = [] for i in xrange(N): line = f.readline() label,text = int(line[0]), line[2:] X.append(text) y.append(label) return X,y X_train, y_train = extract_training() ############################################# # Extending Tfidf to have only stemmed features ############################################# english_stemmer = nltk.stem.SnowballStemmer('english') class StemmedTfidfVectorizer(TfidfVectorizer): def build_analyzer(self): analyzer = super(TfidfVectorizer, self).build_analyzer() return lambda doc: (english_stemmer.stem(w) for w in analyzer(doc)) tfidf = StemmedTfidfVectorizer(min_df=1, stop_words='english', analyzer='word', ngram_range=(1,1)) ############################################# # Line below takes 6-7 seconds on my machine ############################################# Xv = tfidf.fit_transform(X_train) 

Intenté convertir la lista X_train en un np.array pero no hubo diferencia en el rendimiento.

Como era de esperar, es NLTK que es lento:

 >>> tfidf = StemmedTfidfVectorizer(min_df=1, stop_words='english', analyzer='word', ngram_range=(1,1)) >>> %timeit tfidf.fit_transform(X_train) 1 loops, best of 3: 4.89 s per loop >>> tfidf = TfidfVectorizer(min_df=1, stop_words='english', analyzer='word', ngram_range=(1,1)) >>> %timeit tfidf.fit_transform(X_train) 1 loops, best of 3: 415 ms per loop 

Puede acelerar esto utilizando una implementación más inteligente de la bola de nieve, por ejemplo, PyStemmer :

 >>> import Stemmer >>> english_stemmer = Stemmer.Stemmer('en') >>> class StemmedTfidfVectorizer(TfidfVectorizer): ... def build_analyzer(self): ... analyzer = super(TfidfVectorizer, self).build_analyzer() ... return lambda doc: english_stemmer.stemWords(analyzer(doc)) ... >>> tfidf = StemmedTfidfVectorizer(min_df=1, stop_words='english', analyzer='word', ngram_range=(1,1)) >>> %timeit tfidf.fit_transform(X_train) 1 loops, best of 3: 650 ms per loop 

NLTK es un conjunto de herramientas de enseñanza. Es lento por diseño, porque está optimizado para facilitar la lectura.