Matlab中用內建函數代替for循環


在使用matlab進行矩陣計算的時候,經常會遇到要使用for循環的情況。但其實很多操作可以用內部的一些函數代替。 bsxfun, arrayfun, cellfun, spfun, structfun

bsxfun:

1
C = bsxfun(fun,A,B)

bsxfun可以對矩陣A和矩陣B進行對應元素的fun函數操作。其中,fun是任何標量輸入輸出的二元操作的函數,例如基本的加減乘除,三角函數,大小比較,以及其他任何符合條件的自定義函數。

注意,fun不能是符號,例如+,*之類,這些符號都有對應的函數名。例如+ 對應 plus, >= 對應 ge,等等。可以通過matlab命令行輸入

help <運算符號>

來查詢。

一般來說,如果兩個矩陣一樣大,我們可以直接通過 A+B 這樣的方式一樣實現,但是bsxfun有一個優點,就是當A,B中任何一維長度為1的時候,函數會自動將該維度和另一個矩陣對應維度的每一行(列)進行運算。如果我們自己進行這樣的操作,我們或者要使用循環,或者要使用repmat來擴展矩陣,這都比bsxfun在底層內部實現慢很多,或者要消耗更多內存。

網友提供了這樣一個例子:假設我們有數據A和B, 每行是一個樣本,每列是一個特征。我們要計算高斯核,既:

k(||x-xc||)=exp{- ||x-xc||^2/(2*σ)^2) } 其中xc為核函數中心,σ為函數的寬度參數 , 控制了函數的徑向作用范圍。

當然可以用雙重for實現:

1
2
3
4
5
6
K1 = zeros(size(A,1),size(B,1));
for i = 1 : size(A,1)
for j = 1 : size(B,1)
K1(i,j) = exp(-sum((A(i,:)-B(j,:)).^2)/beta);
end
end

使用2,000×1,000大小的A和B, 運行時間為88秒。

考慮下面向量化后的版本:

1
2
3
sA = (sum(A.^2, 2));
sB = (sum(B.^2, 2));
K2 = exp(bsxfun(@minus,bsxfun(@minus,2*A*B', sA), sB')/beta);

使用同樣數據,運行時間僅0.85秒,加速超過100倍。

arrayfun:

1
2
[B1,...,Bm] = arrayfun(func,A1,...,An)
[B1,...,Bm] = arrayfun(func,A1,...,An,Name,Value)

這個函數可以直接對數組中的元素進行func函數操作。其中,func函數接受n個輸入,m個輸出。當輸出可以進行合並的時候,可以設置 'UniformOutput' 為true,這樣所有 A1..An經過func的第m個輸出就會合並為一個數組 Bm,如果'UniformOutput'為false,表示不同輸入元素對應的輸出不能合並,這樣每個Bm就會是一個cell。

matlab的幫助里有個很好的例子,這里就不貼上來了。

cellfun:

1
2
[A1,...,Am] = cellfun(func,C1,...,Cn)
[A1,...,Am] = cellfun(func,C1,...,Cn,Name,Value)

和arrayfun的用法類似,不過是對cell的對應元素進行操作。

structfun:

1
2
[A1,...,An] = structfun(func,S)
[A1,...,An] = structfun(func,S,Name,Value)

類似的用法,對結構體S的所有域進行func操作。

spfun:

1
f = spfun(fun,S)

這個函數可以對一個稀疏矩陣S的每個有值的元素進行fun操作。

這個函數的用途不僅僅是可以提升速度,更重要的是能夠保持返回的f中,沒有數據的地方依然為0. 例如:

1
2
S = spdiags([1:4]',0,4,4)
f = spfun(@exp,S)

S =
(1,1) 1
(2,2) 2
(3,3) 3
(4,4) 4
f =
(1,1) 2.7183
(2,2) 7.3891
(3,3) 20.0855
(4,4) 54.5982
而直接運行

1
exp(S)

的話,沒有數據的地方都變成1了。

1
full(exp(S))

ans =
2.7183 1.0000 1.0000 1.0000
1.0000 7.3891 1.0000 1.0000
1.0000 1.0000 20.0855 1.0000
1.0000 1.0000 1.0000 54.5982


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM