在Matlab中是否有用于向量的bsxfun类型函数?

时间:2016-12-10 00:16:50

标签: arrays matlab matrix vector bsxfun

具体来说,我试图从内核函数创建一个内核矩阵,该函数将向量作为输入并生成标量作为输出。然后,核矩阵是每对矢量的这种输出的2D矩阵。

如果向量输入本身是1D,我可以使用bsxfun做到这一点:

x = [1;2;3;4]; kerfun = @(s,t) (s-t) % some function, doesn't matter, except that it returns a scalar kernel = bsxfun(kerfun, x, x');

输出是内核,正如所料:

kernel =

     0    -1    -2    -3
     1     0    -1    -2
     2     1     0    -1
     3     2     1     0

但是,如果我将x中的点更改为N-D向量,则此方法会失败。我的问题是:有没有一种有效的方法来构造内核矩阵而不使用循环?我尝试过使用cellfun,但这似乎也没有用。感谢。

编辑:作为预期结果的示例,如果我按如下方式更改xkerfun

x = [1,15;23,2;13,5;4,7];
kerfun = @(s,t) norm(s-t); %some function, returns a scalar
ker = zeros(4,4);

然后用蛮力计算内核:

for i=1:size(x,1)
    for j=1:size(x,1)
        ker(i,j) = kerfun(x(i,:),x(j,:));
    end
end

我明白了:

ker =

         0   25.5539   15.6205    8.5440
   25.5539         0   10.4403   19.6469
   15.6205   10.4403         0    9.2195
    8.5440   19.6469    9.2195         0

1 个答案:

答案 0 :(得分:1)

bsxfun可以与 N - 维数组一起使用,它将扩展它们的单例维度。但它在元素方面有效。如果你想要一个功能来做一些"聚合"沿着行的操作,如在您的示例中,bsxfun只能执行元素部分(使用单例扩展)。然后,您需要补充其他一些聚合函数以获得最终结果。

对于您示例中的特定情况,您想要的函数可以分解为逐元素减法(这是bsxfun输入的位置),然后沿行(聚合部分)求和,然后逐元素求平方根。要使用bsxfun进行减法,您需要将x副本的第一维置换到第三维。这样,第一维和第三维跨越了两个循环中ij的所有组合。

然后沿着得到的3D数组的第二维求和,取平方根,并置换回来得到矩阵结果:

ker = sqrt(permute(sum(bsxfun(@minus, x, permute(x, [3 2 1])).^2, 2), [1 3 2]));

请注意,使用其中一个bsxfun的内置函数(例如此处为minus)比使用自定义函数更快。

对于x = [1,15;23,2;13,5;4,7],这会产生

ker =
         0   25.5539   15.6205    8.5440
   25.5539         0   10.4403   19.6469
   15.6205   10.4403         0    9.2195
    8.5440   19.6469    9.2195         0