0

このようにMatlabでコサイン類似度を実装しました。実際、50 行 50 列の 2 次元行列があります。コサインを取得するには、行ごとにアイテムを比較する必要があります。

for j = 1:50
    x = dat(j,:);
    for i = j+1:50
        y = dat(i,:);
        c = dot(x,y);
        sim = c/(norm(x,2)*norm(y,2));
    end
end

これは正しいです?問題はこれです: この状態での複雑さまたは O(n) は何ですか?

4

2 に答える 2

2

ベクトル化された行列操作 (MATLAB で最適化されています) を使用した同じことの効率的な実装に関するメモです。これにより、大規模な行列の時間を大幅に節約できます。

dat = randn(50, 50);

OP (ダブルフォー) の実装:

sim = zeros(size(dat));
nRow = size(dat,1);
for j = 1:nRow
    x = dat(j, :);
    for i = j+1:nRow
        y = dat(i, :);
        c = dot(x, y);
        sim(j, i) = c/(norm(x,2)*norm(y,2));
    end
end

ベクトル化された実装:

normDat = sqrt(sum(dat.^2, 2));           % L2 norm of each row 
datNorm = bsxfun(@rdivide, dat, normDat); % normalize each row 
dotProd = datNorm*datNorm';               % dot-product vectorized (redundant!) 
sim2 = triu(dotProd, 1);                  % keep unique upper triangular part 

1000 x 1000 行列の比較: (MATLAB 2013a、x64、Intel Core i7 960 @ 3.20GHz)

Elapsed time is 34.103095 seconds.
Elapsed time is 0.075208 seconds.
sum(sum(sim-sim2))
ans =
    -1.224314766369880e-14
于 2013-08-14T19:26:37.680 に答える
1

49 で終わる方がよいでしょう。また、sim にインデックスを追加する必要がありますか?

for j = 1:49
  x = dat(j,:);
  for i = j+1:50
      y = dat(i,:);
      c = dot(x,y);
      sim(j) = c/(norm(x,2)*norm(y,2));
  end
end

複雑さはおおよそ o(n^2) のようになるはずですよね。たぶん、相関関数を見た方がいいでしょう...何を書きたいのか正確にはわかりませんが、似たようなことをしたいようです。Matlab には組み込みの相関関数があります。

于 2013-08-14T10:10:01.213 に答える