在使用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
轉載:http://blog.sciencenet.cn/blog-791749-636036.html