2013-09-25 16 views
5

Birkaç belgenin benzerliğini hesaplayacağım bir komut dosyası yazmaya çalışıyorum. Bunu LSA kullanarak yapmak istiyorum. Aşağıdaki kodu buldum ve biraz değiştirdim. Ben bir giriş 3 belgeleri var ve daha sonra bunların arasındaki benzerliğe sahip bir 3x3 matris çıktı olarak. Aynı benzerlik hesaplamasını yapmak istiyorum ancak sadece sklearn kütüphanesi ile. Mümkün mü? Aşağıdaki kodu çalıştırın fakat TFIDF aynı konu ile iki belge üzerinde maksimum% 80 benzerlik varsa ağzım hala açık :) olanLatent Semantic Analysis'i sklearn ile kullanın

, bu kod vermek: @ ogrisel cevabı itibaren

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) 

% 99,99. P Sen 0.14+ sklearn gelen TruncatedSVD trafo kullanabilirsiniz

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

Yukarıdakilerde, benzerlik ölçüsü olarak düşündüğünüz X değeri nedir? –

cevap

8

: Eğer belgelerin veritabanı üzerinde fit_transform ile diyoruz ve daha sonra aynı TruncatedSVD den (transform yöntemini çağırın ben yanlış bir şey olduğunu düşünüyorum yüzden yöntem) sorgu belgesinde ve sonra dönüştürülmüş sorgu belgelerinin kosinüs benzerliğini işlev ile dönüştürülmüş veritabanı ile hesaplayabilir: sklearn.metrics.pairwise.cosine_similarity ve numpy.argsort en benzer belgenin dizinini bulmak için sonuç.

Başlık altında, scikit-learn'in de NumPy'yi kullandığını fakat verdiğiniz snippet'ten daha verimli bir şekilde kullandığını unutmayın (Halko, Martinsson ve Tropp tarafından Randomized SVD numarasını kullanarak).

+0

Güncellenmiş soruya bir göz atabilir misiniz? – Tasos

+0

'TruncatedSVD' varsayılan olarak' n_components = 2' değerine sahiptir. Muhtemelen daha fazlasına ihtiyacınız var, örneğin 'n_components = 100'. – ogrisel

+1

Birkaç test yaptım ve 2'nin üzerindeki her şey, aynı sonucu 0,45 olarak verdi. 0.77 TFIDF yerine. Bunu geliştirmenin bir yolunu bulmaya çalışacağım, ama cevabın bu soru için doğru. teşekkür ederim – Tasos

İlgili konular