J'essaie d'obtenir des mots distinctifs de certains documents à l'aide de la classe TfIDFVectorizer dans scikit-learn. Il crée une matrice tfidf avec tous les mots et leurs scores dans tous les documents, mais ensuite, il semble également compter les mots courants. Voici une partie du code que je lance:
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(contents)
feature_names = vectorizer.get_feature_names()
dense = tfidf_matrix.todense()
denselist = dense.tolist()
df = pd.DataFrame(denselist, columns=feature_names, index=characters)
s = pd.Series(df.loc['Adam'])
s[s > 0].sort_values(ascending=False)[:10]
Je m'attendais à ce que cela retourne une liste de mots distinctifs pour le document 'Adam', mais son résultat renvoie une liste de mots courants:
and 0.497077
to 0.387147
the 0.316648
of 0.298724
in 0.186404
with 0.144583
his 0.140998
Je ne le comprends peut-être pas parfaitement, mais tel que je le comprends, tf-idf est supposé trouver des mots distinctifs d’un document dans un corpus, des mots figurant fréquemment dans un document mais pas dans d’autres. Ici, and
apparaît fréquemment dans d'autres documents, donc je ne sais pas pourquoi cela renvoie une valeur élevée ici.
Le code complet que j'utilise pour générer ceci est dans ce carnet Jupyter .
Lorsque je calcule tf/idfs de manière semi-manuelle, en utilisant NLTK et en calculant les scores de chaque mot, j'obtiens les résultats appropriés. Pour le document "Adam":
fresh 0.000813
prime 0.000813
bone 0.000677
relate 0.000677
blame 0.000677
enough 0.000677
Cela semble à peu près correct, car ce sont des mots qui apparaissent dans le document "Adam", mais pas autant dans d'autres documents du corpus. Le code complet utilisé pour générer cela se trouve dans ce cahier Jupyter .
Est-ce que je fais quelque chose de mal avec le code scikit? Existe-t-il un autre moyen d'initialiser cette classe où les bons résultats sont renvoyés? Bien sûr, je peux ignorer les mots vides en passant stop_words = 'english'
, mais cela ne résout pas vraiment le problème, car les mots communs de toute sorte ne devraient pas avoir des scores élevés ici.
De la documentation scikit-learn:
Comme tf – idf est très souvent utilisé pour les fonctions de texte, il existe également une autre classe appelée TfidfVectorizer qui combine toutes les options de CountVectorizer et de TfidfTransformer dans un seul modèle.
Comme vous pouvez le constater, TfidfVectorizer est un CountVectorizer suivi de TfidfTransformer .
Ce que vous cherchez probablement est TfidfTransformer et non TfidfVectorizer
Je pense que votre problème réside dans l'utilisation de différentes listes de mots vides. Scikit-learn et NLTK utilisent par défaut différentes listes de mots vides. Pour scikit-learn, il est généralement judicieux de faire passer une liste d’arrêts personnalisés à TfidfVectorizer, par exemple:
my_stopword_list = ['and','to','the','of']
my_vectorizer = TfidfVectorizer(stop_words=my_stopword_list)
Page de doc pour la classe TfidfVectorizer: [ http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html][1]
Je ne sais pas pourquoi ce n'est pas la valeur par défaut, mais vous voulez probablement sublinear_tf=True
dans l'initialisation de TfidfVectorizer. J'ai fourré votre dépôt et vous ai envoyé un PR avec un exemple qui ressemble probablement plus à ce que vous voulez.
en utilisant le code ci-dessous, j'obtiens de bien meilleurs résultats
vectorizer = TfidfVectorizer(sublinear_tf=True, stop_words='english')
Sortie
sustain 0.045090
bone 0.045090
thou 0.044417
thee 0.043673
timely 0.043269
thy 0.042731
prime 0.041628
absence 0.041234
rib 0.041234
feel 0.040259
Name: Adam, dtype: float64
et
thee 0.071188
thy 0.070549
forbids 0.069358
thou 0.068068
early 0.064642
earliest 0.062229
dreamed 0.062229
firmness 0.062229
glistering 0.062229
sweet 0.060770
Name: Eve, dtype: float64