一.問題來源
來自於一份LSH代碼,記錄下來。
二.函數解析
2.1 bsxfun
bsxfun是一個matlab自版本R2007a來就提供的一個函數,作用是”applies an element-by-element binary operation to arrays a and b, with singleton expansion enabled。
函數用在兩個數組間元素逐個計算。比如當我們想對一個矩陣A的每一列或者每一行與同一個長度相等的向量a進行某些操作(比較大小,乘除等)時,我們只能用循環方法或者利用repmat函數將要操作的向量a復制成和A一樣尺寸的矩陣,進而進行操作。從MATLAB R2007a開始,再遇到類似的問題時,我們有了簡潔高效的方法,即利用bsxfun函數。
2.2 unique
格式 b = unique (a) %取集合a的不重復元素構成的向量。
b = unique (A,'rows') %返回A、B不同行元素組成的矩陣。
我發現b中內容由小到大排序了。
[b,i,j] = unique (…) %i體現b中元素在原向量(矩陣a)中的位置;j體現原向量(矩陣a)在b中的位置
參考文獻:http://blog.sina.com.cn/s/blog_5efed5800100crs2.html
三.實例分析
3.1 bsxfun
舉個例子。假設我們有一列向量和一行向量。a = randn(3,1), b = randn(1,3),我們可以很簡單的使用matlab的外乘c=a*b來得到,但如果我們想用”外加”呢?也就是說把上式求解過程中的乘號換做加號?
這時我們可以用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)。
這里repmat是顯式的復制,當然帶來內存的消耗。而bsxfun是虛擬的復制,實際上通過for來實現,等效於for(i=1:3),for(j=1:3),c(i,j)=a(i)+b(j);end,end。但bsxfun不會有使用matlab的for所帶來額外時間。從計算時間上來說前兩種實現差不多,遠高於for的實現。但如果數據很大,第二種實現可能會有內存上的問題。所以bsxfun最好。
這里@plus是加法的函數數柄,相應的有減法@minus, 乘法@times, 左右除等,具體可見 doc bsxfun.也可以是m文件。
@plus@minus@times@rdivide@ldivide@power@max@min@rem@mod@atan2@hypot@eq@ne@lt@le@gt@ge@and@or@xor
參考文獻http://blog.sina.com.cn/s/blog_9e67285801010ttn.html
3.2rempat
>> A=[1 1 2 2 4 4 6 4 6]
A =
1 1 2 2 4 4 6 4 6
>> [c,i,j]=unique(A)
c =
1 2 4 6
i =
2 4 8 9 %i體現b中元素在原向量(矩陣a)中的位置;
j =
1 1 2 2 3 3 4 3 4 %j體現原向量(矩陣a)在b中的位置
例1-40
>> A=[1 2 2 4;1 1 4 6;1 1 4 6]
A =
1 2 2 4
1 1 4 6
1 1 4 6
>> [c,i,j]=unique(A,'rows')
c =
1 1 4 6
1 2 2 4
i =
3
1
j =
2
1
1
如何將一個矩陣的每行或每列元素分別擴大不同的倍數?如[1 2 3;4 5 6 ;7 8 9],第一列元素乘以1,第二列元素以2,第三列元素乘以4。
利用bsxfun函數,可以給出下列代碼:a = [1,2,3;4,5,6;7,8,9];acol = bsxfun(@times,a,[1 2 4])