如何为这个matlab“for loop”做矢量化?

时间:2017-11-14 12:42:57

标签: matlab vectorization

我有一些matlab代码如下,构建KNN相似权重矩阵。

[D,I] = pdist2(X, X, 'squaredeuclidean', 'Smallest', k+1);
D = D < threshold;
W = zeros(n, n);
for i=1:size(I,2)
    W(I(:,i), i) = D(:,i);
    W(i, I(:,i)) = D(:,i)';
end

我想矢量化for循环。我试过了

W(I) = D;

但未能获得正确的值。

我在这里添加测试用例:

n = 5;

D = [
 1     1     1     1     1
 0     1     1     1     1
 0     0     0     0     0
];

I = [
 1     2     3     4     5
 5     4     5     2     3
 3     1     1     1     1
];

3 个答案:

答案 0 :(得分:2)

有一些未定义的变量使得很难检查它在做什么,但这应该与你的for循环相同:

D,I] = pdist2(X, X, 'squaredeuclidean', 'Smallest', k+1);
D = D < threshold;
W = zeros(n);

% set the diagonal values
W(sub2ind(size(X), I(1, :), I(1, :))) = D(1,:);
% set the other values
W(sub2ind(size(W), I(2, :), 1:size(I, 2))) = D(2, :);
W(sub2ind(size(W), 1:size(I, 2), I(2, :))) = D(2, :).';

我分开了指示,它现在适用于您的测试用例。

答案 1 :(得分:1)

你可以用线性索引剪切一些角,但如果你的矩阵很大,那么你应该只采用D的非零分量。以下复制D

的所有值
W = zeros(n);
W(reshape(sub2ind([n,n],I,[1;1;1]*[1:n]),1,[])) = reshape(D,1,[]);

答案 2 :(得分:1)

可能的解决方案:

idx1 = reshape(1:n*n,n,n).';
idx2 = bsxfun(@plus,I,0:n:n*size(I,2)-1);

W=zeros(n,n);
W(idx2) = D;
W(idx1(idx2)) = D;

此处假设您反复想要计算DI,因此只计算一次idx并重复使用。

n = 5;
idx1 = reshape(1:n*n,n,n).';
%for k = 1 : 1000
    %[D,I] = pdist2(X, X, 'squaredeuclidean', 'Smallest', k+1);
    %D = D < threshold;
    idx2 = bsxfun(@plus,I,0:n:n*size(I,2)-1);   
    W=zeros(n,n);
    W(idx2) = D;
    W(idx1(idx2)) = D;
%end

但是如果n不是常数并且在每次迭代中变化,那么最好改变计算idx1的方式:

n = 5;
%for k = 1 : 1000
    %n = randi([2 10]);%n isn't constant
    %[D,I] = pdist2(X, X, 'squaredeuclidean', 'Smallest', k+1);
    %D = D < threshold;
    idx1 = bsxfun(@plus,(0:n:n^2-1).',1:size(I,2));
    idx2 = bsxfun(@plus,I,0:n:n*size(I,2)-1);   
    W=zeros(n,n);
    W(idx2) = D;
    W(idx1(idx2)) = D;
%end