2013-09-25 62 views
5

Tôi đang cố gắng viết một kịch bản mà tôi sẽ tính toán sự giống nhau của một vài tài liệu. Tôi muốn làm điều đó bằng cách sử dụng LSA. Tôi đã tìm thấy đoạn mã sau và thay đổi nó một chút. Tôi có như là một đầu vào 3 tài liệu và sau đó là đầu ra một ma trận 3x3 với sự giống nhau giữa chúng. Tôi muốn thực hiện tính toán tương tự nhưng chỉ với thư viện sklearn. Điều đó có thể không?Sử dụng phân tích ngữ nghĩa tiềm ẩn với 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) 

Từ câu trả lời @ ogrisel của:

tôi chạy đoạn mã sau, nhưng miệng tôi vẫn mở cửa :) Khi TFIDF có tối đa 80% tương đồng trên hai tài liệu với cùng một chủ đề, mã này cung cấp cho tôi 99,99%. Đó là lý do tại sao tôi nghĩ rằng nó là một cái gì đó sai: 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

Ở trên, giá trị của X mà bạn đang xem xét là thước đo tương tự như thế nào? –

Trả lời

8

Bạn có thể sử dụng máy biến áp TruncatedSVD từ sklearn 0.14+: bạn gọi nó với fit_transform trên cơ sở dữ liệu của bạn trong tài liệu và sau đó gọi phương thức transform (so với cùng TruncatedSVD phương pháp) trên tài liệu truy vấn và sau đó có thể tính toán độ tương tự cosin của tài liệu truy vấn được chuyển đổi với cơ sở dữ liệu được chuyển đổi với hàm: sklearn.metrics.pairwise.cosine_similaritynumpy.argsort kết quả để tìm chỉ mục của tài liệu tương tự nhất. Lưu ý rằng dưới mui xe, scikit-learn cũng sử dụng NumPy nhưng theo cách hiệu quả hơn đoạn trích bạn đã đưa ra (bằng cách sử dụng thủ thuật Randomized SVD bởi Halko, Martinsson và Tropp).

+0

Bạn có thể xem qua câu hỏi được cập nhật không? – Tasos

+0

'TruncatedSVD' có' n_components = 2' theo mặc định. Bạn có thể cần nhiều hơn, ví dụ 'n_components = 100'. – ogrisel

+1

Tôi đã thực hiện một số bài kiểm tra và mọi thứ trên 2, cho kết quả tương tự trên 0,45. Thay vì 0,77 TFIDF. Tôi sẽ cố gắng tìm cách để cải thiện nó, nhưng câu trả lời của bạn là chính xác cho câu hỏi này. Cảm ơn bạn – Tasos