在使用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