web-dev-qa-db-ja.com

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にありますか?

9
Mehdi

コードはすべての行をループし、各行は(約)半分の行をループし、行の一意の組み合わせごとに内積を計算します。

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で除算することです。ここでは、2つのベクトルを乗算して、正規化する正方行列を生成します。

S2 = (S1 * S1.') ./ (norm_r * norm_r.');
5
Cris Luengo

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によって明示的に計算されません。

7