我有一些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
];
答案 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;
此处假设您反复想要计算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