我怎样才能为这个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;
这里假设你要反复计算D
和I
,所以只计算一次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循环”做矢量化?的主要内容,如果未能解决你的问题,请参考以下文章