jru*_*ren 4 matlab matrix vectorization bsxfun
我正在使用bsxfun大小矩阵之间的单例扩展来向量化操作:
MS: (nms, nls)
KS: (nks, nls)
Run Code Online (Sandbox Code Playgroud)
操作的各值之间的绝对差之和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)));
Run Code Online (Sandbox Code Playgroud)
R很大(nls, nms).
我想将此操作推广到样本列表,因此新的大小将是:
MS: (nxs, nls, nms)
KS: (nxs, nls, nks)
Run Code Online (Sandbox Code Playgroud)
这可以通过for循环轻松实现,for循环执行每个2维矩阵的第一段代码,但我怀疑通过添加新维度来概括先前的代码可以更好地提高性能.
R 将是大小: (nxs, nls, nms)
我试图重塑MS到4个维度但没有成功.这可以通过重塑来完成bsxfun吗?
你可能需要这个:
% 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)
Run Code Online (Sandbox Code Playgroud)
这将产生一个大小的矩阵[2,3,4],即[nxs,nls,nms].每个元素[k1,k2,k3]都对应
R(k1,k2,k3) == sum_k abs(MS(k1,k2,k3) - KS(k1,k2,k))
Run Code Online (Sandbox Code Playgroud)
例如,在我的随机运行中
R(2,1,3)
ans =
1.255765020150647
>> sum(abs(MS(2,1,3)-KS(2,1,:)))
ans =
1.255765020150647
Run Code Online (Sandbox Code Playgroud)
诀窍是引入单例尺寸permute:permute(KS,[1,2,4,3])大小[nxs,nls,1,nks],而MS大小[nxs,nls,nms]也隐含大小[nxs,nls,nms,1]:假设MATLAB中的每个数组都具有可数无限数量的尾随单例尺寸.从这里可以很容易地看到如何bsxfun将大小数组合在一起,[nxs,nls,nms,1]并[nxs,nls,1,nks]分别获得一个大小的数组[nxs,nls,nms,nks].沿着维度4总结密封交易.
我在评论中指出,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]);
Run Code Online (Sandbox Code Playgroud)
我所做的是将求和nks维度放在第一位,然后按降序排列其余维度.这可以自动完成,我只是不想让这个例子过于复杂.在您的使用案例中,您可能会知道尺寸的大小.
使用上述两个代码的运行时:原始值为0.07028秒,重新排序的值为0.051162秒(最好为5个).不幸的是,现在更大的例子不适合我.
| 归档时间: |
|
| 查看次数: |
242 次 |
| 最近记录: |