我正在尝试编写一个脚本,在其中计算几个文档的相似性。我想通过使用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)
您可以使用 sklearn 0.14+ 中的 TruncatedSVD 转换器:在文档数据库上使用 fit_transform
调用它,然后在查询文档上调用 transform
方法(来自相同的TruncatedSVD
方法),然后可以使用以下函数计算转换后的查询文档与转换后的数据库的余弦相似性: sklearn.metrics.pairwise.cosine_similarity
和numpy.arg排序结果以查找最相似文档的索引。
请注意,在引擎盖下,scikit-learn也使用NumPy,但方式比您给出的片段更有效(通过使用Halko,Martinsson和Tropp的Randomized SVD技巧)。