matlab函数 bsxfun浅谈(转载)
网上关于bsxfun的东西不多,今天需要看到一个,由于原博文插入的图片显示不出来,于是笔者大发善心进行了contrl+V 以及alt+ctrl+A的操作,供大家交流学习。
bsxfun是一个matlab自版本R2007a来就提供的一个函数,作用是”applies an element-by-element binary operation to arrays a and b, with singleton expansion enabled.”
举个例子。假设我们有一列向量和一行向量。
a = randn(3,1), b = randn(1,3) a = -0.2453 -0.2766 -0.1913 b = 0.6062 0.5655 0.9057 我们可以很简单的使用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(a,1,3) ans = -0.2453 -0.2453 -0.2453 -0.2766 -0.2766 -0.2766 -0.1913 -0.1913 -0.1913
repmat是显式的复制,当然带来内存的消耗。而bsxfun是虚拟的复制,实际上通过for来实现,等效于for(i=1:3),for(j=1:3),c(i,j)=a(i)+b(j);end,end。但bsxfun不会有使用matlab的for所带来额外时间。实际验证下这三种方式
>> c = bsxfun(@plus,a,b) c = 0.3609 0.3202 0.6604 0.3296 0.2889 0.6291 0.4149 0.3742 0.7144 >> c = repmat(a,1,3)+repmat(b,3,1) c = 0.3609 0.3202 0.6604 0.3296 0.2889 0.6291 0.4149 0.3742 0.7144 >> for(i=1:3),for(j=1:3),c(i,j)=a(i)+b(j);end,end,c c = 0.3609 0.3202 0.6604 0.3296 0.2889 0.6291 0.4149 0.3742 0.7144
从计算时间上来说前两种实现差不多,远高于for的实现。但如果数据很大,第二种实现可能会有内存上的问题。所以bsxfun***。
这里@plus是加法的函数数柄,相应的有减法@minus, 乘法@times, 左右除等,具体可见 doc bsxfun.
下面看一个更为实际的情况。假设我们有数据A和B, 每行是一个样本,每列是一个特征。我们要计算高斯核,既:
k(||x-xc||)=exp{- ||x-xc||^2/(2*σ)^2) } 其中xc为核函数中心,σ为函数的宽度参数 , 控制了函数的径向作用范围。
当然可以用双重for实现(如果第一直觉是用三重for的话…)。
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秒。
考虑下面向量化后的版本: 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倍。
如要判断两者结果是不是一样,可以如下 assert(all(all(abs(K1-K2)<1e-12)))
C = bsxfun(fun,A,B) appliesthe element-by-element binary operation specified by the functionhandlefun to arrays A and B,with singleton expansion enabled.fun can be oneof the following built-in functions:
@plus
Plus
@minus
Minus
@times
Array multiply
@rdivide
Right array divide
@ldivide
Left array divide
@power
Array power
@max
Binary maximum
@min
Binary minimum
@rem
Remainder after division
@mod
Modulus after division
@atan2
Four quadrant inverse tangent
@hypot
Square root of sum of squares
@eq
Equal
@ne
Not equal
@lt
Less than
@le
Less than or equal to
@gt
Greater than
@ge
Greater than or equal to
@and
Element-wise logical AND
@or
Element-wise logical OR
@xor
Logical exclusive OR