6

我正在尝试编写一个脚本来计算几个文档的相似性。我想通过使用 LSA 来做到这一点。我找到了以下代码并对其进行了一些更改。我有一个输入 3 个文档,然后作为输出一个 3x3 矩阵,它们之间的相似性。我想做同样的相似度计算,但只用 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)

来自@ogrisel 的回答:

我运行下面的代码,但我的嘴仍然张着 :) 当 TFIDF 在具有相同主题的两个文档上具有最大 80% 的相似性时,这段代码给了我 99.99%。这就是为什么我认为这是错误的: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)
4

1 回答 1

10

您可以使用sklearn 0.14+中的TruncatedSVDfit_transform转换器:您在文档数据库上调用它,然后在查询文档上调用transform方法(来自相同的TruncatedSVD方法),然后可以计算转换后的查询文档与转换后的查询文档的余弦相似度具有功能的数据库:sklearn.metrics.pairwise.cosine_similaritynumpy.arg对结果进行排序以查找最相似文档的索引。

请注意,在后台,scikit-learn 也使用 NumPy,但比您提供的代码段更有效(通过使用Halko、Martinsson 和 Tropp的随机 SVD技巧)。

于 2013-09-25T07:49:39.967 回答