web-dev-qa-db-fra.com

Combiner la racine du texte et la suppression de la ponctuation dans NLTK et scikit-learn

J'utilise une combinaison de NLTK et scikit-learn 's CountVectorizer pour la racine des mots et la tokenisation.

Vous trouverez ci-dessous un exemple d'utilisation simple de 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())

Qui va imprimer

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

Maintenant, disons que je veux supprimer les mots vides et endiguer les mots. Une option serait de le faire comme ceci:

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

Qui imprime:

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

Mais comment pourrais-je me débarrasser au mieux des caractères de ponctuation dans cette deuxième version?

20
user2489252

Il existe plusieurs options, essayez de supprimer la ponctuation avant la tokenisation. Mais cela signifierait 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

Ou essayez de supprimer la ponctuation après la tokenisation.

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

ÉDITÉ

Le code ci-dessus fonctionnera mais il est plutôt lent car il boucle plusieurs fois le même texte:

  • Une fois pour supprimer la ponctuation
  • Deuxième fois pour tokenize
  • Troisième fois pour endiguer.

Si vous avez d'autres étapes comme la suppression de chiffres ou la suppression de mots vides ou de minuscules, etc.

Il serait préférable de regrouper les étapes autant que possible, voici plusieurs meilleures réponses plus efficaces si vos données nécessitent plus d'étapes de prétraitement:

26
alvas