我正在使用bsxfun
来对大小矩阵之间的单例扩展进行矢量化操作:
MS: (nms, nls)
KS: (nks, nls)
该操作是MS(m,l)
中m
与1:nms
中l
和1:nls
中KS(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;
}
来完成吗?
答案 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个)。不幸的是,更大的例子现在不适合我。