3E7 x 3E7
是荒謬矩陣大小。在低性能筆記本電腦/臺式機上實現這一目標的唯一方法是使用生成器來減少內存佔用,並將問題細分爲效率問題。
以下函數使用的發電機廠,並使用雙for
遍歷組塊的笛卡爾乘積。我們預先計算語料庫中每個tfidf
的規範。
這不是設計爲較小的數據這樣做同樣的任務最快的解決方案。這是爲了在一臺適度的機器的內存中完成這項任務。
from scipy.sparse import coo_matrix
import numpy as np
def f(t, c, p=-1, v=False):
n = (t ** 2).sum(1) ** .5
g = lambda: ((x, t[x:x+c]) for x in range(0, t.shape[0], c))
h = lambda a, b, i, j: a.dot(b.T)/n[i:i+c, None]/n[j:j+c]
d = lambda s: (s * (1 - np.eye(s.shape[0])))
for i, a in g():
for j, b in g():
s = h(a, b, i, j)
if i == j:
s = d(s)
i_, j_ = np.where(s > p)
if v:
print('\r', 'i = {:0000000d}; j = {:0000000d}'.format(i, j), end='')
yield s[i_, j_], i_ + i, j_ + j
有了,我們通過計算它們自己在每個分塊和跟蹤的相似之處比我們的閾值提取餘弦相似。
最後,我們通過足夠的相似用的相似的座標以一個稀疏矩陣構造,並將結果指定到名稱m
。如果您需要矩陣表示,請使用m.toarray()
。
values, *ij = zip(*f(tfidf_matrix, 5000, .8, v=True))
values = np.concatenate(values)
ij = list(map(np.concatenate, ij))
m = coo_matrix((values, ij))
請注意,我零對角線。否則,如果我們使用閾值-1
,這將產生與sklearn.metrics.pairwise
中的cosine_similarity
完全相同的內容。
相同的煩躁的驗證
from sklearn.metrics.pairwise import cosine_similarity
tfidf_matrix = np.random.randint(10, size=(1000, 100))
s = cosine_similarity(tfidf_matrix)
values, *ij = zip(*f(tfidf_matrix, 5000, -1, v=True))
values = np.concatenate(values)
ij = list(map(np.concatenate, ij))
m = coo_matrix((values, ij))
# This should be equal the 1000. The number of 1's in the diagonal.
(s - m.toarray()).sum()
1000.0
cosine_similarity將輸出一個方陣並且它可能的是在單個列中的一個值是> 0.65和其它的是以下。那麼在那種情況下,您希望該列出現在數據框中? –
@VivekKumar好問題。我希望數據框的所有值都堆疊在一起。即數據幀中的每一行應該只有一個相似度分數和相應的文檔ID。 'similar_values = similarity_values.stack()。reset_index()。rename(columns = {'level_0':'ID1','level_1':'ID2',0:'Score'})' – Minu