ベクトル化された行列操作 (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