Combinación de texto derivado y eliminación de puntuación en NLTK y scikit-learn

Estoy usando una combinación de scikit-learn y scikit-learn para CountVectorizer palabras y tokenización.

A continuación se muestra un ejemplo del uso simple del CountVectorizer :

 from sklearn.feature_extraction.text import CountVectorizer vocab = ['The swimmer likes swimming so he swims.'] vec = CountVectorizer().fit(vocab) sentence1 = vec.transform(['The swimmer likes swimming.']) sentence2 = vec.transform(['The swimmer swims.']) print('Vocabulary: %s' %vec.get_feature_names()) print('Sentence 1: %s' %sentence1.toarray()) print('Sentence 2: %s' %sentence2.toarray()) 

Que se imprimirá

 Vocabulary: ['he', 'likes', 'so', 'swimmer', 'swimming', 'swims', 'the'] Sentence 1: [[0 1 0 1 1 0 1]] Sentence 2: [[0 0 0 1 0 1 1]] 

Ahora, digamos que quiero eliminar las palabras clave y eliminarlas. Una opción sería hacerlo así:

 from nltk import word_tokenize from nltk.stem.porter import PorterStemmer ####### # based on http://www.cs.duke.edu/courses/spring14/compsci290/assignments/lab02.html stemmer = PorterStemmer() def stem_tokens(tokens, stemmer): stemmed = [] for item in tokens: stemmed.append(stemmer.stem(item)) return stemmed def tokenize(text): tokens = nltk.word_tokenize(text) stems = stem_tokens(tokens, stemmer) return stems ######## vect = CountVectorizer(tokenizer=tokenize, stop_words='english') vect.fit(vocab) sentence1 = vect.transform(['The swimmer likes swimming.']) sentence2 = vect.transform(['The swimmer swims.']) print('Vocabulary: %s' %vect.get_feature_names()) print('Sentence 1: %s' %sentence1.toarray()) print('Sentence 2: %s' %sentence2.toarray()) 

Que imprime:

 Vocabulary: ['.', 'like', 'swim', 'swimmer'] Sentence 1: [[1 1 1 1]] Sentence 2: [[1 0 1 1]] 

Pero, ¿cuál es la mejor forma de deshacerme de los caracteres de puntuación en esta segunda versión?

Hay varias opciones, intente eliminar la puntuación antes de la tokenización. Pero esto significaría que don't -> dont

 import string def tokenize(text): text = "".join([ch for ch in text if ch not in string.punctuation]) tokens = nltk.word_tokenize(text) stems = stem_tokens(tokens, stemmer) return stems 

O intente eliminar la puntuación después de la tokenización.

 def tokenize(text): tokens = nltk.word_tokenize(text) tokens = [i for i in tokens if i not in string.punctuation] stems = stem_tokens(tokens, stemmer) return stems 

Editado

El código anterior funcionará pero es bastante lento porque se repite en el mismo texto varias veces:

  • Una vez para eliminar la puntuación.
  • Segunda vez para tokenizar
  • Tercera vez para detener.

Si tiene más pasos como eliminar dígitos o eliminar palabras clave o hacer minúsculas, etc.

Sería mejor agrupar los pasos lo más posible, aquí hay varias respuestas mejores que son más eficientes si sus datos requieren más pasos de preprocesamiento: