我怎样才能为这个matlab“for循环”做矢量化?

Posted

技术标签:

【中文标题】我怎样才能为这个matlab“for循环”做矢量化?【英文标题】:How can I do vectorization for this matlab "for loop"? 【发布时间】:2017-11-14 12:42:56 【问题描述】:

我有一些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
];

【问题讨论】:

【参考方案1】:

有一些未定义的变量很难检查它在做什么,但这应该和你的 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, :).';

我拆分了方向,现在它适用于您的测试用例。

【讨论】:

感谢您的帮助。我已经尝试过您的代码并将其与原始循环进行比较。 W的一些条目不一样。【参考方案2】:

一个可能的解决方案:

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

【讨论】:

【参考方案3】:

您可以使用线性索引减少一些角落,但如果您的矩阵很大,那么您应该只取D 的非零分量。以下复制 D 的所有值

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

【讨论】:

以上是关于我怎样才能为这个matlab“for循环”做矢量化?的主要内容,如果未能解决你的问题,请参考以下文章

像 while 循环一样,我怎样才能跳过 for 循环中的一个步骤?

带有滑动窗口元素的矩阵

如何对 Matlab 流程进行基准测试?

Matlab:迭代循环

FFT 和改变频率并矢量化 FOR 循环

matlab 二维矩阵for循环逐行赋值