MATLAB 中的余弦相似性内置函数



我想计算 matlab 中矩阵不同行之间的余弦相似性。我在 matlab 中编写了以下代码:

for i = 1:n_row
    for j = i:n_row
        S2(i,j) = dot(S1(i,:), S1(j,:)) / (norm_r(i) * norm_r(j));
        S2(j,i) = S2(i,j);

矩阵 S1 为 11000*11000,代码执行非常耗时。那么,我想知道matlab中是否有任何函数可以比上述代码更快地计算矩阵行之间的余弦相似性?

通过计算与pdist的相似性来缩短版本:

S2 = squareform(1-pdist(S1,'cosine')) + eye(size(S1,1));

解释:

pdist(S1,'cosine')计算 S1 中所有行组合之间的余弦距离。因此,所有组合之间的相似性1 - pdist(S1,'cosine')

我们可以将其转换为方阵,其中元素 (i,j) 对应于行ij行之间的相似性 squareform(1-pdist(S1,'cosine')) .

最后,我们必须将主对角线设置为 1,因为一行与自身的相似性显然是 1,但这不是由 pdist 明确计算的。

您的代码遍历所有行,并且对于每一行循环(大约(一半的行,计算每个唯一行组合的点积:

n_row = size(S1,1);
norm_r = sqrt(sum(abs(S1).^2,2)); % same as norm(S1,2,'rows')
S2 = zeros(n_row,n_row);
for i = 1:n_row
  for j = i:n_row
    S2(i,j) = dot(S1(i,:), S1(j,:)) / (norm_r(i) * norm_r(j));
    S2(j,i) = S2(i,j);
  end
end

(我冒昧地完成了您的代码,以便它实际运行。注意循环前S2的初始化,这样可以节省大量时间!

如果您注意到点积是带有列向量的行向量的矩阵乘积,您可以看到上面没有归一化步骤,与

S2 = S1 * S1.';

这比显式循环运行得更快,即使它(也许?(无法使用对称性。规范化只是将每一行除以norm_r,将每一列除以norm_r。在这里,我将两个向量相乘以生成一个方阵来归一化:

S2 = (S1 * S1.') ./ (norm_r * norm_r.');

最新更新