2013-09-25 6 views
5

Próbuję napisać skrypt, w którym obliczy podobieństwo kilku dokumentów. Chcę to zrobić za pomocą LSA. Znalazłem poniższy kod i trochę go zmieniłem. Mam jako dane wejściowe 3 dokumenty, a następnie jako wynik macierzy 3x3 z podobieństwem między nimi. Chcę wykonać to samo obliczenie podobieństwa, ale tylko z biblioteką sklearn. Czy to jest możliwe?Użyj analizy semantycznej ukrytej z sklearn

from numpy import zeros 
from scipy.linalg import svd 
from math import log 
from numpy import asarray, sum 
from nltk.corpus import stopwords 
from sklearn.metrics.pairwise import cosine_similarity 

titles = [doc1,doc2,doc3] 
ignorechars = ''',:'!''' 

class LSA(object): 
    def __init__(self, stopwords, ignorechars): 
     self.stopwords = stopwords.words('english') 
     self.ignorechars = ignorechars 
     self.wdict = {} 
     self.dcount = 0   
    def parse(self, doc): 
     words = doc.split(); 
     for w in words: 
      w = w.lower() 
      if w in self.stopwords: 
       continue 
      elif w in self.wdict: 
       self.wdict[w].append(self.dcount) 
      else: 
       self.wdict[w] = [self.dcount] 
     self.dcount += 1 
    def build(self): 
     self.keys = [k for k in self.wdict.keys() if len(self.wdict[k]) > 1] 
     self.keys.sort() 
     self.A = zeros([len(self.keys), self.dcount]) 
     for i, k in enumerate(self.keys): 
      for d in self.wdict[k]: 
       self.A[i,d] += 1 
    def calc(self): 
     self.U, self.S, self.Vt = svd(self.A) 
     return -1*self.Vt 

    def TFIDF(self): 
     WordsPerDoc = sum(self.A, axis=0)   
     DocsPerWord = sum(asarray(self.A > 0, 'i'), axis=1) 
     rows, cols = self.A.shape 
     for i in range(rows): 
      for j in range(cols): 
       self.A[i,j] = (self.A[i,j]/WordsPerDoc[j]) * log(float(cols)/DocsPerWord[i]) 

mylsa = LSA(stopwords, ignorechars) 
for t in titles: 
    mylsa.parse(t) 
mylsa.build() 
a = mylsa.calc() 
cosine_similarity(a) 

Od użytkownika @ ogrisel odpowiedź:

uruchomić poniższy kod, ale moje usta są nadal otwarte :) Kiedy TFIDF ma max 80% podobieństwa na dwóch dokumentach dotyczących tego samego zagadnienia, to kod give mi 99,99%. Dlatego myślę, że jest coś nie tak: P

dataset = [doc1,doc2,doc3] 
vectorizer = TfidfVectorizer(max_df=0.5,stop_words='english') 
X = vectorizer.fit_transform(dataset) 
lsa = TruncatedSVD() 
X = lsa.fit_transform(X) 
X = Normalizer(copy=False).fit_transform(X) 

cosine_similarity(X) 
+0

W powyższej tabeli, jaka jest wartość X, którą rozważasz jako miarę podobieństwa? –

Odpowiedz

8

Można użyć transformatora na TruncatedSVD z sklearn 0.14+: to nazwać z fit_transform na bazie dokumentów, a następnie wywołać metodę transform (z tego samego TruncatedSVD metoda) w dokumencie zapytania, a następnie może obliczyć podobieństwo kosinusa przekształconych dokumentów zapytania do przekształconej bazy danych z funkcją: sklearn.metrics.pairwise.cosine_similarity i numpy.argsort, aby znaleźć indeks najbardziej podobnego dokumentu.

Zauważ, że pod maską, scikit-learn używa również NumPy, ale w bardziej efektywny sposób niż podany fragment (przy użyciu sztuczki Randomized SVD autorstwa Halko, Martinsson i Tropp).

+0

Czy możesz sprawdzić zaktualizowane pytanie? – Tasos

+0

'TruncatedSVD' ma domyślnie' n_components = 2'. Prawdopodobnie potrzebujesz więcej, na przykład 'n_components = 100'. – ogrisel

+1

Zrobiłem kilka testów i wszystko powyżej 2, dał taki sam wynik na 0.45. Zamiast 0,77 TFIDF. Spróbuję znaleźć sposób, aby to poprawić, ale twoja odpowiedź jest poprawna dla tego pytania. Dziękuję Ci – Tasos

Powiązane problemy