2016-04-26 18 views
0

Ich versuche ein kleines Programm zu erstellen, das die Tfidf in Python berechnet. Es gibt zwei sehr schöne Tutorials, die ich verwendet habe (ich habe Code aus here und eine andere Funktion von kaggle)Python tfidf Rückgabe der gleichen Werte unabhängig von IDF

import nltk 
import string 
import os 
from bs4 import * 
import re 
from nltk.corpus import stopwords # Import the stop word list 
import numpy as np 

from sklearn.feature_extraction.text import TfidfVectorizer 
from nltk.stem.porter import PorterStemmer 

path = 'my/path' 
token_dict = {} 
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 

def review_to_words(raw_review): 
    # 1. Remove HTML 
    review_text = BeautifulSoup(raw_review).get_text() 
    # 2. Remove non-letters   
    letters_only = re.sub("[^a-zA-Z]", " ", review_text) 
    # 3. Convert to lower case, split into individual words 
    words = letters_only.lower().split()        
    # 4. In Python, searching a set is much faster than searching 
    # a list, so convert the stop words to a set 
    stops = set(stopwords.words("english"))     
    # 5. Remove stop words 
    meaningful_words = [w for w in words if not w in stops] 
    # 6. Join the words back into one string separated by space, 
    # and return the result. 
    return(" ".join(meaningful_words)) 



for subdir, dirs, files in os.walk(path): 
    for file in files: 
     file_path = subdir + os.path.sep + file 
     shakes = open(file_path, 'r') 
     text = shakes.read() 
     token_dict[file] = review_to_words(text) 

tfidf = TfidfVectorizer(tokenizer=tokenize, stop_words='english') 
tfs = tfidf.fit_transform(token_dict.values()) 


str = 'this sentence has unseen text such as computer but also king lord lord this this and that lord juliet'#teststring 
response = tfidf.transform([str]) 

feature_names = tfidf.get_feature_names() 
for col in response.nonzero()[1]: 
    print feature_names[col], ' - ', response[0, col] 

Der Code scheint gut zu funktionieren, aber dann habe ich einen Blick auf die Ergebnisse.

thi - 0.612372435696 
text - 0.204124145232 
sentenc - 0.204124145232 
lord - 0.612372435696 
king - 0.204124145232 
juliet - 0.204124145232 
ha - 0.204124145232 
comput - 0.204124145232 

Die IDFs scheinen für alle Wörter gleich zu sein, da die TFIDFs nur n * 0,204 sind. Ich habe mit tfidf.idf_ überprüft und dies scheint der Fall zu sein.

Gibt es etwas in der Methode, die ich nicht richtig implementiert habe? Wissen Sie, warum die IDF_s gleich sind?

+1

Untersuchen Sie Ihren Code Ich habe nicht sicher festgestellt, was falsch sein könnte. Ich fand jedoch etwas Seltsames. Warum strippen Sie Stoppwörter zweimal? Einmal in der 'review_to_words()' Funktion und auch bei der Initialisierung von 'TfidfVectorizer'. –

Antwort

0

Da Sie eine Liste mit 1 Dokument zur Verfügung gestellt haben, haben alle Begriffe idfs die gleiche binäre Häufigkeit.

idf ist die invertierte Termhäufigkeit über die Menge der Dokumente (oder nur invertierte Dokumenthäufigkeit). Die meisten, wenn nicht alle IDF-Formeln überprüfen nur die Präsenz von Terminen in einem Dokument. Es ist also egal, wie oft sie pro Dokument vorkommen.

Versuchen Sie, eine Liste mit 3 verschiedenen Dokumenten zum Beispiel zu füttern, so wird die IDFs nicht die gleiche sein.

0

Die inverse Dokumenthäufigkeit eines Terms t wird wie folgt berechnet.

enter image description here

N ist die Gesamtzahl der Dokumente und df_t ist die Anzahl der Dokumente, in denen der Begriff t erscheint.

In diesem Fall hat Ihr Programm ein Dokument (Variable str). Daher sind sowohl N als auch df_t gleich 1. Folglich sind die IDF für alle Terme gleich.