使用具有三维矩阵的单独扩展的bsxfun

时间:2016-01-13 21:52:05

标签: matlab matrix vectorization bsxfun

我正在使用bsxfun来对大小矩阵之间的单例扩展进行矢量化操作:

MS: (nms, nls)
KS: (nks, nls)

该操作是MS(m,l)m1:nmsl1:nlsKS(k,l)以及每k之间的绝对差值之和在1:nks中使用[~, nls] = size(MS); MS = reshape(MS',1,nls,[]); R = sum(abs(bsxfun(@minus,MS,KS)));

我通过代码来实现这一目标:

R

(nls, nms)的大小为MS: (nxs, nls, nms) KS: (nxs, nls, nks)

我想将此操作概括为样本列表,因此新的大小将为:

R

这可以通过for循环轻松实现,该for循环执行每个2维矩阵的第一段代码,但我怀疑通过添加新维度来概括前面的代码可以提高性能。

(nxs, nls, nms)的大小为:MS

我试图将bsxfun重塑为4维并没有成功。这可以通过重塑和#define CONDITION int conditional function(); //... int foo() { #ifdef CONDITION return conditional_function(); #endif int value = 0; //...many more lines return value; } 来完成吗?

1 个答案:

答案 0 :(得分:6)

你可能需要这个:

% generate small dummy data
nxs = 2;
nls = 3;
nms = 4;
nks = 5;
MS = rand(nxs, nls, nms);
KS = rand(nxs, nls, nks);

R = sum(abs(bsxfun(@minus,MS,permute(KS,[1,2,4,3]))),4)

这将生成大小为[2,3,4]的矩阵,即[nxs,nls,nms]。每个元素[k1,k2,k3]都对应

R(k1,k2,k3) == sum_k abs(MS(k1,k2,k3) - KS(k1,k2,k))

例如,在我的随机运行中

R(2,1,3)

ans =

   1.255765020150647

>> sum(abs(MS(2,1,3)-KS(2,1,:)))

ans =

   1.255765020150647

诀窍是引入带有permute的单身尺寸:permute(KS,[1,2,4,3])的尺寸为[nxs,nls,1,nks],而尺寸MS的{​​{1}}隐含的尺寸为[nxs,nls,nms] {1}}:假设MATLAB中的每个数组都具有可数无限数量的尾随单例维度。从这里可以很容易地看到如何[nxs,nls,nms,1]分别将大小为bsxfun[nxs,nls,nms,1]的数组放在一起,以获得大小为[nxs,nls,1,nks]的数组。沿着维度4总结可以达成协议。

我在评论中指出,汇总指数[nxs,nls,nms,nks]可能会更快。事实证明,这本身使代码运行更慢。但是,通过重新整形数组以减小尺寸大小,整体性能会提高(由于最佳内存访问)。比较一下:

permute

我所做的是将求和% generate larger dummy data nxs = 20; nls = 30; nms = 40; nks = 500; MS = rand(nxs, nls, nms); KS = rand(nxs, nls, nks); MS2 = permute(MS,[4 3 2 1]); KS2 = permute(KS,[3 4 2 1]); R3 = permute(squeeze(sum(abs(bsxfun(@minus,MS2,KS2)),1)),[3 2 1]); 维度放在第一位,然后按降序排列其余维度。这可以自动完成,我只是不想让这个例子过于复杂。在您的使用案例中,您可能无论如何都知道尺寸的大小。

使用上述两个代码的运行时:原始值为0.07028秒,重新排序的值为0.051162秒(最好为5个)。不幸的是,更大的例子现在不适合我。