将 bsxfun 与具有三维矩阵的单例扩展一起使用
Use of bsxfun with singleton expansion with matrixes of three dimensions
我正在使用 bsxfun
对大小矩阵之间的单例扩展操作进行向量化:
MS: (nms, nls)
KS: (nks, nls)
操作是MS(m,l)
与1:nms
中的m
和1:nls
中的l
的每个值的绝对差之和,并且每个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)
这可以通过 for 循环轻松实现,该 for 循环为每个二维矩阵执行第一段代码,但我怀疑通过添加新维度来概括以前的代码,性能可能会好得多。
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)
这将生成大小为 [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
的大小 [nxs,nls,nms]
也隐式为size [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]);
我所做的是将总和 nks
维度放在第一位,然后将其余维度按降序排列。这可以自动完成,我只是不想使示例过于复杂。在您的用例中,您可能无论如何都知道尺寸的大小。
以上两个代码的运行时间:原始代码为 0.07028 秒,重新排序的代码为 0.051162 秒(5 个中最好)。不幸的是,现在更大的例子不适合我的记忆。
我正在使用 bsxfun
对大小矩阵之间的单例扩展操作进行向量化:
MS: (nms, nls)
KS: (nks, nls)
操作是MS(m,l)
与1:nms
中的m
和1:nls
中的l
的每个值的绝对差之和,并且每个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)
这可以通过 for 循环轻松实现,该 for 循环为每个二维矩阵执行第一段代码,但我怀疑通过添加新维度来概括以前的代码,性能可能会好得多。
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)
这将生成大小为 [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
的大小 [nxs,nls,nms]
也隐式为size [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]);
我所做的是将总和 nks
维度放在第一位,然后将其余维度按降序排列。这可以自动完成,我只是不想使示例过于复杂。在您的用例中,您可能无论如何都知道尺寸的大小。
以上两个代码的运行时间:原始代码为 0.07028 秒,重新排序的代码为 0.051162 秒(5 个中最好)。不幸的是,现在更大的例子不适合我的记忆。