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