向量化矩阵中不同对角线的总和
我想向量化以下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
的代码计算得分的表,小号,对于动态规划算法,从另一个得分表,Ç。
对角线求和是针对所有可能的部分(大小为r)生成用于生成的各个数据片段的分数,所述数据用于生成C。
在此先感谢您的任何答案!很抱歉,如果这一块应该是显而易见的......
注意
内置CONV2竟然是比convnfft更快,因为我的眼睛(R)是相当小的(5 < = R < = 20) 。 convnfft.m指出r应该是> 20以表示任何好处。
如果我理解正确,你试图计算C的每个子数组的对角线总和,你已经删除C的最后一行和一列(如果你不应该删除行/列,你需要循环到m-r + 1,并且您需要将整个数组C传递给我的解决方案中的函数)。
您可以通过convolution做这个手术,就像这样:
S = conv2(C(1:end-1,1:end-1),eye(r),'valid');
如果C和R都很大,你可能想看看CONVNFFT从MATLAB文件交换来加快计算。
我认为你可能需要将C重新排列成3D矩阵,然后沿着其中一个维度求和它。我会尽快发布答案。
编辑
我没能找到一个方法来清洁它vectorise,但我没有找到功能accumarray
,这可能有一定的帮助。当我回家时,我会更详细地看它。
EDIT#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);
创建S_offset
,一个(MR)通过(NR)中的R矩阵,使得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
等方法,使之更加高效;在这里我选择了为了清晰起见。我还没有对此进行基准测试,以了解它如何与双循环方法进行比较;我需要先回家吃晚饭!
这是你在找什么?该函数添加对角线并将它们放入一个类似于函数'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 [email protected] 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
干杯
太棒了,谢谢。 明天我会看看CONVNFFT。在我用于测试的数据子集(比实际数据大约小500倍)上,与循环相比,内置的conv2函数实现了69,652次调用次数减少和34.56次执行时间减少(23.5 vs 0.68秒)。 – 2010-05-19 12:33:12