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

Meh*_*hdi 8 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);
Run Code Online (Sandbox Code Playgroud)

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

Lea*_*ger 7

通过计算相似度的短版本pdist:

S2 = squareform(1-pdist(S1,'cosine')) + eye(size(S1,1));
Run Code Online (Sandbox Code Playgroud)

说明:

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

我们可以把它转换成其中元件的方矩阵(i,j)对应于行之间的相似性ijsquareform(1-pdist(S1,'cosine')).

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


Cri*_*ngo 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
Run Code Online (Sandbox Code Playgroud)

(我已经冒昧地完成你的代码,所以它实际运行.注意S2循环之前的初始化,这节省了很多时间!)

如果您注意到点积是具有列向量的行向量的矩阵乘积,您可以看到上面没有标准化步骤的上述内容与

S2 = S1 * S1.';
Run Code Online (Sandbox Code Playgroud)

这比显式循环运行得快得多,即使它(可能?)不能使用对称性.归一化只是将每一行norm_r和每一列分开norm_r.在这里,我将两个向量相乘以生成一个方阵,以便用以下标准化:

S2 = (S1 * S1.') ./ (norm_r * norm_r.');
Run Code Online (Sandbox Code Playgroud)