matlab中的余弦相似度内置函数

时间:2018-01-04 18:36:05

标签: matlab matrix cosine-similarity

我想在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中是否有任何函数可以比上面的代码更快地计算矩阵行之间的余弦相似度?

2 个答案:

答案 0 :(得分:7)

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

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

说明:

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

我们可以将其转换为方形矩阵,其中元素(i,j)对应于行ijsquareform(1-pdist(S1,'cosine'))之间的相似度。

最后我们必须将主对角线设置为1,因为行本身的相似性显然为1,但pdist未明确计算。

答案 1 :(得分:5)

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

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.');