天天看點

matlab學習筆記 bsxfun函數

matlab學習筆記 bsxfun函數

最近總是遇到 bsxfun這個函數,前幾次因為無關緊要隻是大概看了一下函數體去對比結果,今天再一次遇見了這個函數,想想還是有必要掌握的,遂查了些資料總結如下。

函數bsxfun

【功能描述】兩個數組間元素逐個計算.

【應用場合】當我們想對一個矩陣A的每一列或者每一行與同一個長度相等的向量a進行某些操作(比較大小,乘除等)時,我們隻能用循環方法或者利用repmat函數将要操作的向量a複制成和A一樣尺寸的矩陣,進而進行操作。從MATLAB R2007a開始,再遇到類似的問題時,我們有了簡潔高效的方法,即利用bsxfun函數。

【函數描述】C=bsxfun(fun,A,B):兩個數組間元素逐個計算,fun是函數句柄或者m檔案,也可以為如下内置函數 :

@plus 加 ;         @minus 減 ;         @times 數組乘 ;         @rdivide 左除 ;        @ldivide 右除 。

Example1: 将一個矩陣的每行或每列元素分别擴大不同的倍數

如[1 2 3;4 5 6 ;7 8 9],第一列元素乘以1,第二列元素以2,第三列元素乘以4。利用bsxfun函數,可以給出下列代碼:

[plain] view plaincopy

  1. <pre name="code" class="plain">a = [1,2,3;4,5,6;7,8,9];  
  2. acol = bsxfun(@times,a,[1 2 4])  

Example2:假設我們有一列向量和一行向量。

[plain] view plaincopy

  1. <pre name="code" class="plain">a = randn(3,1);  
  2. b = randn(1,3);  
  3. a =  
  4.     0.7516  
  5.    -0.8637  
  6.    -1.0709  
  7. b =  
  8.    -0.3552    0.9559    0.1593  
我們可以很簡單的使用matlab的外乘來得到c=a*b,      

[plain] view plaincopy

  1. c = a * b  
  2. c =  
  3.    -0.2670    0.7184    0.1197  
  4.     0.3068   -0.8256   -0.1376  
  5.     0.3804   -1.0236   -0.1706  
但如果我們想用”外加”呢?也就是說把上式求解過程中的乘号換做加号?這時我們可以用         c=bsxfun(@plus,a,b)                來實作。      
bsxfun的執行是這樣的:如果a和b的大小相同,那麼c=a+b; 但如果有某維不同,且a或b必須有一個在這一維的維數為1, 那麼bsxfun就将少的這個虛拟的複制一些來使與多的維數一樣。在我們這裡,b的第一維隻有1(隻一行),是以bsxfun将b複制3次形成一個3×3的矩陣,同樣也将a複制成3×3的矩陣。這個等價于         c=repmat(a,1,3)+repmat(b,3,1)                。這裡,      

[plain] view plaincopy

  1. repmat(a,1,3)   
  2. ans =   
  3. -0.2453 -0.2453 -0.2453   
  4. -0.2766 -0.2766 -0.2766   
  5. -0.1913 -0.1913 -0.1913  
repmat是顯式的複制,當然帶來記憶體的消耗。而bsxfun是虛拟的複制,實際上通過for來實作,等效于:      

[plain] view plaincopy

  1. for(i=1:3)  
  2.     for(j=1:3)  
  3.     c(i,j)=a(i)+b(j);  
  4.     end  
  5. end  
但bsxfun不會有使用matlab的for所帶來額外時間。實際驗證下這三種方式:      

[plain] view plaincopy

  1. >> c = bsxfun(@plus,a,b)   
  2.    c =   
  3.       0.3609 0.3202 0.6604   
  4.       0.3296 0.2889 0.6291   
  5.       0.4149 0.3742 0.7144   

[plain] view plaincopy

  1. >> c = repmat(a,1,3)+repmat(b,3,1)   
  2.    c =   
  3.       0.3609 0.3202 0.6604   
  4.       0.3296 0.2889 0.6291   
  5.       0.4149 0.3742 0.7144   

[plain] view plaincopy

  1. >> for(i=1:3)  
  2.       for(j=1:3)  
  3.          c(i,j)=a(i)+b(j);  
  4.       end  
  5.    end  
  6. >> c   
  7.    c =   
  8.       0.3609 0.3202 0.6604   
  9.       0.3296 0.2889 0.6291   
  10.       0.4149 0.3742 0.7144  
從計算時間上來說前兩種實作差不多,遠高于for的實作。但如果資料很大,第二種實作可能會有記憶體上的問題。是以bsxfun最好。      

參考:http://blog.sina.com.cn/s/blog_9e67285801010ttn.html

http://blog.sina.com.cn/s/blog_6ca002a50100wvu1.html