2017-07-13 52 views
0

我一直在向量化Matlab中的for循環,因爲它瓶頸了整個程序,但我不知道如何在循環內的單個矩陣的不同行或列上迭代時如何做到這一點。下面的代碼:如何向同一個矩陣/數組的不同索引上的嵌套循環操作進行矢量化?

// X is an n*k matrix, W is n*n 
// W(i,j) stores the norm of the vector resulting from subtracting 
// the j-th line of X from its i-th line. 
for i = 1:n 
    for j = 1:n 
     W(i,j) = norm(X(i,:) - X(j,:)) 
    end 
end 

編輯:

我選擇了路易斯Mendo的答案,因爲它是最方便的,我和這更接近我的算法背後的數學概念之一,但所有三個答案是正確的,我建議使用最方便的一個,具體取決於您擁有的Matlab工具箱或您希望編碼的方式。

我還注意到,所有答案的共同點是使用不同的格式,例如:使用一個數組,將存儲索引,重新塑造當前數組,使用一個更多的維度... 所以我認爲這就是如果你有類似的問題,那麼你應該去探索一下。

+0

你是否已經嘗試vectorise內只有循環? – m7913d

回答

0
  • 如果您有統計工具箱,使用pdist

    W = squareform(pdist(X)); 
    
  • 沒有工具箱:好老bsxfun

    W = sqrt(sum(bsxfun(@minus, permute(X, [1 3 2]), permute(X, [3 1 2])).^2, 3)); 
    
2

使用組合子:

% sample data 
X = randi(9,5,4); 
n = size(X,1); 

% row index combinations 
combIdx = combvec(1:n,1:n); 
% difference between row combinations 
D = X(combIdx(1,:),:)-X(combIdx(2,:),:); 
% norm of each row 
W = diag(sqrt(D*D')); 
% reshape 
W = reshape(W,n,[]); 
1

這裏是另一個解決方案,它可以是用於大矩陣更有效。

MATLAB的> = R2016,你可以簡單的使用

W = sqrt(sum(abs(reshape(X,n,1,k) - reshape(X,1,n,k)).^2,3)) 

(如果你的陣列是實值也可以跳過ABS)。對於早期版本的Matlab的,你需要添加一些repmat魔術,即:

W = sqrt(sum(abs(repmat(reshape(X,n,1,k),[1,n,1]) - repmat(reshape(X,1,n,k),[n,1,1])).^2,3)); 

P.S:R2017b可能使其更加方便,至少release notes提到一個叫vecnorm功能,可以代替有點醜陋sqrt(sum(abs(.).^2)))事情。但文件尚未完成,所以我不知道它會做什麼。 「

相關問題