我想要矢量化以下MATLAB代码。我认为它必须简单,但我发现它令人困惑。
r = some constant less than m or n
[m,n] = size(C);
S = zeros(m-r,n-r);
for i=1:m-r+1
for j=1:n-r+1
S(i,j) = sum(diag(C(i:i+r-1,j:j+r-1)));
end
end
代码从另一个得分表 C 计算动态编程算法的分数表 S 。
对角线求和是为所有可能的片段(大小为r)生成用于生成 C 的单个数据片段的分数。
提前感谢您的任何答案!对不起,如果这个显而易见......
注意
内置的conv2比convnfft更快,因为我的眼睛(r)非常小(5 <= r <= 20)。 convnfft.m表明r应该> 20表示任何利益。
答案 0 :(得分:10)
如果我理解正确,你试图计算C的每个子数组的对角线和,你已经删除了C的最后一行和一列(如果你不应该删除行/ col,你需要循环到m-r + 1,你需要将整个数组C传递给我的解决方案中的函数。)
您可以通过convolution执行此操作,如下所示:
S = conv2(C(1:end-1,1:end-1),eye(r),'valid');
如果C和r很大,您可能需要查看Matlab文件交换中的CONVNFFT以加快计算速度。
答案 1 :(得分:3)
基于JS的概念,以及评论中指出的Jonas,可以使用IM2COL
和一些数组操作在两行中完成:
B = im2col(C, [r r], 'sliding');
S = reshape( sum(B(1:r+1:end,:)), size(C)-r+1 );
基本上B
包含矩阵C
上大小为r-by-r的所有滑块的元素。然后我们采用每个块B(1:r+1:end,:)
的对角线上的元素,计算它们的总和,并将结果重新整形为预期的大小。
将此与Jonas基于卷积的解决方案相比较,这不执行任何矩阵乘法,只进行索引...
答案 2 :(得分:2)
我认为您可能需要将C重新排列成3D矩阵,然后再将其与其中一个维度相加。我很快就会回答。
修改强>
我没有找到一种方法来干净利落地进行矢量化,但我确实找到了函数accumarray
,这可能会有所帮助。我回家时会更详细地看一下。
修改#2 强>
使用线性索引找到了一个更简单的解决方案,但这可能是内存密集型的。
在C(1,1)处,我们想要求和的指数是1 + [0,m + 1,2 * m + 2,3 * m + 3,4 * m + 4,...],或(0:r-1)+(0:m:(r-1)* m)
sum_ind = (0:r-1)+(0:m:(r-1)*m);
通过r矩阵创建S_offset
,(mr)by(nr),使得S_offset(:,:,1)= 0,S_offset(:,,2)= m + 1,S_offset( :,:,3)= 2 * m + 2,依此类推。
S_offset = permute(repmat( sum_ind, [m-r, 1, n-r] ), [1, 3, 2]);
创建S_base
,一个基数组地址矩阵,将从中计算偏移量。
S_base = reshape(1:m*n,[m n]);
S_base = repmat(S_base(1:m-r,1:n-r), [1, 1, r]);
最后,使用S_base+S_offset
来解决C的值。
S = sum(C(S_base+S_offset), 3);
当然,您可以使用bsxfun
和其他方法来提高效率;在这里,我选择将其列出来以保持清晰。我还没有对此进行基准测试,以了解它与双循环方法的对比情况;我需要先回家吃晚餐!
答案 3 :(得分:1)
这是你要找的吗?此函数添加对角线并将它们放入一个向量中,类似于函数“sum”如何将矩阵中的所有列相加并将它们放入向量中。
function [diagSum] = diagSumCalc(squareMatrix, LLUR0_ULLR1)
%
% Input: squareMatrix: A square matrix.
% LLUR0_ULLR1: LowerLeft to UpperRight addition = 0
% UpperLeft to LowerRight addition = 1
%
% Output: diagSum: A vector of the sum of the diagnols of the matrix.
%
% Example:
%
% >> squareMatrix = [1 2 3;
% 4 5 6;
% 7 8 9];
%
% >> diagSum = diagSumCalc(squareMatrix, 0);
%
% diagSum =
%
% 1 6 15 14 9
%
% >> diagSum = diagSumCalc(squareMatrix, 1);
%
% diagSum =
%
% 7 12 15 8 3
%
% Written by M. Phillips
% Oct. 16th, 2013
% MIT Open Source Copywrite
% Contact mphillips@hmc.edu fmi.
%
if (nargin < 2)
disp('Error on input. Needs two inputs.');
return;
end
if (LLUR0_ULLR1 ~= 0 && LLUR0_ULLR1~= 1)
disp('Error on input. Only accepts 0 or 1 as input for second condition.');
return;
end
[M, N] = size(squareMatrix);
if (M ~= N)
disp('Error on input. Only accepts a square matrix as input.');
return;
end
diagSum = zeros(1, M+N-1);
if LLUR0_ULLR1 == 1
squareMatrix = rot90(squareMatrix, -1);
end
for i = 1:length(diagSum)
if i <= M
countUp = 1;
countDown = i;
while countDown ~= 0
diagSum(i) = squareMatrix(countUp, countDown) + diagSum(i);
countUp = countUp+1;
countDown = countDown-1;
end
end
if i > M
countUp = i-M+1;
countDown = M;
while countUp ~= M+1
diagSum(i) = squareMatrix(countUp, countDown) + diagSum(i);
countUp = countUp+1;
countDown = countDown-1;
end
end
end
干杯