将值的赋值向量化为 3D 数组
Vectorizing the assignment of values into a 3D array
这是简单的代码:
A=zeros(60,60,30);
a=rand(28,28,30);
for i=1:30
m=round(rand*32)+1; %because 60-28=32
n=round(rand*32)+1;
A(m:m+27,n:n+27,i)=a(:,:,i);
end
它所做的只是将一个 28*28 的随机矩阵 "plant" 放入一个更大的(零)矩阵中,并重复 30 次。每次,它随机选择一个不同的角位置(即'm'和'n')将小矩阵放在大矩阵里面。
我确信我可以在没有 for
循环的情况下做到这一点 - 只是不确定如何做到这一点。
这里的所有技巧都与 MATLAB 中使用的线性索引有关。我们创建偏移线性索引,牢记最终输出的大小。首先,将创建偏移索引以索引到 A
的一个 3D 切片,然后索引到整个 3D 数组。它们在代码中分别命名为 offset2D
和 offset3D
。最后,我们添加从 m
和 n
.
获得的线性索引
假设您将 m
和 n
索引保存到两个单独的一维数组中,例如 m_arr
和 n_arr
,您将得到最终的矢量化实现bsxfun
像这样 -
%// Say you have the m,n arrays are created like this -
m_arr = round(rand(30,1)*32)+1;
n_arr = round(rand(30,1)*32)+1;
%// Get linear indices with m,n
mn_arr = (n_arr-1)*size(A,1) + m_arr;
%// Calculate offset indices for 2D and then 3D versions
offset2D = bsxfun(@plus,[0:27]',[0:27]*size(A,1)); %//'
offset3D = bsxfun(@plus,offset2D(:),[0:30-1]*numel(A(:,:,1)));
%// Incorporate m,n indices into offset to get final linear indices to index into A
lidx = bsxfun(@plus,mn_arr(:).',offset3D); %//'
%// Initialize output array and then index into A to values from a
A = zeros(60,60,30);
A(lidx) = a;
对于未来的读者,这里是 for 循环和向量化代码的参数化版本 -
%// Parameters
M = 4;
D = 3;
mx = 3;
%// For-loop code
A = zeros(M+mx,M+mx,D);
a = rand(M,M,D);
m_arr = round(rand(D,1)*mx)+1;
n_arr = round(rand(D,1)*mx)+1;
for i=1:D
m = m_arr(i);
n = n_arr(i);
A(m:m+M-1,n:n+M-1,i) = a(:,:,i);
end
%// Vectorized code
mn_arr = (n_arr-1)*size(A,1) + m_arr;
offset2D = bsxfun(@plus,[0:M-1]',[0:M-1]*size(A,1)); %//'
offset3D = bsxfun(@plus,offset2D(:),[0:D-1]*numel(A(:,:,1)));
lidx = bsxfun(@plus,mn_arr(:).',offset3D); %//'
A_vectorized = zeros(M+mx,M+mx,D);
A_vectorized(lidx) = a;
最后,让我们比较循环代码和矢量化代码的输出 -
>> max(abs(A(:)-A_vectorized(:)))
ans =
0
这是简单的代码:
A=zeros(60,60,30);
a=rand(28,28,30);
for i=1:30
m=round(rand*32)+1; %because 60-28=32
n=round(rand*32)+1;
A(m:m+27,n:n+27,i)=a(:,:,i);
end
它所做的只是将一个 28*28 的随机矩阵 "plant" 放入一个更大的(零)矩阵中,并重复 30 次。每次,它随机选择一个不同的角位置(即'm'和'n')将小矩阵放在大矩阵里面。
我确信我可以在没有 for
循环的情况下做到这一点 - 只是不确定如何做到这一点。
这里的所有技巧都与 MATLAB 中使用的线性索引有关。我们创建偏移线性索引,牢记最终输出的大小。首先,将创建偏移索引以索引到 A
的一个 3D 切片,然后索引到整个 3D 数组。它们在代码中分别命名为 offset2D
和 offset3D
。最后,我们添加从 m
和 n
.
假设您将 m
和 n
索引保存到两个单独的一维数组中,例如 m_arr
和 n_arr
,您将得到最终的矢量化实现bsxfun
像这样 -
%// Say you have the m,n arrays are created like this -
m_arr = round(rand(30,1)*32)+1;
n_arr = round(rand(30,1)*32)+1;
%// Get linear indices with m,n
mn_arr = (n_arr-1)*size(A,1) + m_arr;
%// Calculate offset indices for 2D and then 3D versions
offset2D = bsxfun(@plus,[0:27]',[0:27]*size(A,1)); %//'
offset3D = bsxfun(@plus,offset2D(:),[0:30-1]*numel(A(:,:,1)));
%// Incorporate m,n indices into offset to get final linear indices to index into A
lidx = bsxfun(@plus,mn_arr(:).',offset3D); %//'
%// Initialize output array and then index into A to values from a
A = zeros(60,60,30);
A(lidx) = a;
对于未来的读者,这里是 for 循环和向量化代码的参数化版本 -
%// Parameters
M = 4;
D = 3;
mx = 3;
%// For-loop code
A = zeros(M+mx,M+mx,D);
a = rand(M,M,D);
m_arr = round(rand(D,1)*mx)+1;
n_arr = round(rand(D,1)*mx)+1;
for i=1:D
m = m_arr(i);
n = n_arr(i);
A(m:m+M-1,n:n+M-1,i) = a(:,:,i);
end
%// Vectorized code
mn_arr = (n_arr-1)*size(A,1) + m_arr;
offset2D = bsxfun(@plus,[0:M-1]',[0:M-1]*size(A,1)); %//'
offset3D = bsxfun(@plus,offset2D(:),[0:D-1]*numel(A(:,:,1)));
lidx = bsxfun(@plus,mn_arr(:).',offset3D); %//'
A_vectorized = zeros(M+mx,M+mx,D);
A_vectorized(lidx) = a;
最后,让我们比较循环代码和矢量化代码的输出 -
>> max(abs(A(:)-A_vectorized(:)))
ans =
0