摘要:这个问题涉及线性回归计算算法的改进。
我有一个3D(dlMAT
)数组,表示在不同曝光时间(矢量IT
)拍摄的同一场景的单色照片。在数学上,dlMAT
的第三维上的每个向量代表一个需要解决的单独的线性回归问题。需要估计其系数的等式具有以下形式:
DL = R*IT^P
,其中DL
和IT
是通过实验获得的,R
和P
必须进行估算。
在应用对数后,上述方程可以转换为简单的线性模型:
log(DL) = log(R) + P*log(IT) => y = a + b*x
下面给出的是解决这个方程组最“天真”的方法,它主要涉及迭代所有“第三维向量”并拟合1
到(IT,DL(ind1,ind2,:)
的多项式:
%// Define some nominal values:
R = 0.3;
IT = 600:600:3000;
P = 0.97;
%// Impose some believable spatial variations:
pMAT = 0.01*randn(3)+P;
rMAT = 0.1*randn(3)+R;
%// Generate "fake" observation data:
dlMAT = bsxfun(@times,rMAT,bsxfun(@power,permute(IT,[3,1,2]),pMAT));
%// Regression:
sol = cell(size(rMAT)); %// preallocation
for ind1 = 1:size(dlMAT,1)
for ind2 = 1:size(dlMAT,2)
sol{ind1,ind2} = polyfit(log(IT(:)),log(squeeze(dlMAT(ind1,ind2,:))),1);
end
end
fittedP = cellfun(@(x)x(1),sol); %// Estimate of pMAT
fittedR = cellfun(@(x)exp(x(2)),sol); %// Estimate of rMAT
上面的方法似乎是矢量化的一个很好的候选者,因为它没有利用MATLAB的主要优势,即MATrix操作。出于这个原因,它不能很好地扩展,并且执行时间比我想象的要长得多。
存在基于矩阵划分执行此计算的替代方法,如here和here所示,其中包含以下内容:
sol = [ones(size(x)),log(x)]\log(y);
即,将1
s的向量附加到观测值,然后mldivide
来求解方程系统。
我面临的主要挑战是如何使我的数据适应算法(反之亦然)。
问题#1:如何扩展基于矩阵划分的解决方案以解决上述问题(并可能替换我正在使用的循环)?
问题#2(奖金):这种基于矩阵划分的解决方案背后的原理是什么?
答案 0 :(得分:9)
包含矩阵划分的解决方案背后的秘密成分是Vandermonde matrix。这个问题讨论了一个线性问题(线性回归),那些问题总是可以表示为一个矩阵问题,\
(mldivide
)可以用均方误差意义求解 {{3 }} 。解决类似问题的这种算法在‡中得到了证明和解释。
以下是基准测试代码,用于将原始解决方案与聊天 this answer,1 中建议的两个替代方案进行比较:
function regressionBenchmark(numEl)
clc
if nargin<1, numEl=10; end
%// Define some nominal values:
R = 5;
IT = 600:600:3000;
P = 0.97;
%// Impose some believable spatial variations:
pMAT = 0.01*randn(numEl)+P;
rMAT = 0.1*randn(numEl)+R;
%// Generate "fake" measurement data using the relation "DL = R*IT.^P"
dlMAT = bsxfun(@times,rMAT,bsxfun(@power,permute(IT,[3,1,2]),pMAT));
%% // Method1: loops + polyval
disp('-------------------------------Method 1: loops + polyval')
tic; [fR,fP] = method1(IT,dlMAT); toc;
fprintf(1,'Regression performance:\nR: %d\nP: %d\n',norm(fR-rMAT,1),norm(fP-pMAT,1));
%% // Method2: loops + Vandermonde
disp('-------------------------------Method 2: loops + Vandermonde')
tic; [fR,fP] = method2(IT,dlMAT); toc;
fprintf(1,'Regression performance:\nR: %d\nP: %d\n',norm(fR-rMAT,1),norm(fP-pMAT,1));
%% // Method3: vectorized Vandermonde
disp('-------------------------------Method 3: vectorized Vandermonde')
tic; [fR,fP] = method3(IT,dlMAT); toc;
fprintf(1,'Regression performance:\nR: %d\nP: %d\n',norm(fR-rMAT,1),norm(fP-pMAT,1));
function [fittedR,fittedP] = method1(IT,dlMAT)
sol = cell(size(dlMAT,1),size(dlMAT,2));
for ind1 = 1:size(dlMAT,1)
for ind2 = 1:size(dlMAT,2)
sol{ind1,ind2} = polyfit(log(IT(:)),log(squeeze(dlMAT(ind1,ind2,:))),1);
end
end
fittedR = cellfun(@(x)exp(x(2)),sol);
fittedP = cellfun(@(x)x(1),sol);
function [fittedR,fittedP] = method2(IT,dlMAT)
sol = cell(size(dlMAT,1),size(dlMAT,2));
for ind1 = 1:size(dlMAT,1)
for ind2 = 1:size(dlMAT,2)
sol{ind1,ind2} = flipud([ones(numel(IT),1) log(IT(:))]\log(squeeze(dlMAT(ind1,ind2,:)))).'; %'
end
end
fittedR = cellfun(@(x)exp(x(2)),sol);
fittedP = cellfun(@(x)x(1),sol);
function [fittedR,fittedP] = method3(IT,dlMAT)
N = 1; %// Degree of polynomial
VM = bsxfun(@power, log(IT(:)), 0:N); %// Vandermonde matrix
result = fliplr((VM\log(reshape(dlMAT,[],size(dlMAT,3)).')).');
%// Compressed version:
%// result = fliplr(([ones(numel(IT),1) log(IT(:))]\log(reshape(dlMAT,[],size(dlMAT,3)).')).');
fittedR = exp(real(reshape(result(:,2),size(dlMAT,1),size(dlMAT,2))));
fittedP = real(reshape(result(:,1),size(dlMAT,1),size(dlMAT,2)));
方法2可以被矢量化为方法3的原因基本上是矩阵乘法可以由第二矩阵的列分开。如果A*B
生成矩阵X
,则根据定义A*B(:,n)
会为X(:,n)
提供n
。使用A
将mldivide
移到右侧,这意味着可以使用A\X(:,n)
为所有n
一次性完成分部A\X
。同样适用于2(线性回归问题),其中一般没有确切的解决方案,mldivide
找到overdetermined system的矩阵。在这种情况下,操作A\X(:,n)
(方法2)可以一次性完成n
A\X
(方法3)。
在增加dlMAT
的大小时改进算法的含义可以在下面看到:
minimizes the mean-square error
对于500*500
(或2.5E5
)元素的情况,从Method 1
到Method 3
的加速大约是 x3500 !
观察 output(这里是500 * 500的情况)也很有意思:
从上面可以看出,通过和squeeze
重新排列元素大约占Method 2
运行时的一半(!)。还可以看出,溶液从细胞转化为基质的过程中损失了一些时间。
由于第3个解决方案避免了所有这些陷阱,以及完全循环(这主要意味着在每次迭代时重新评估脚本) - 毫不奇怪,这会导致相当大的加速。
Method 3
的版本支持&#34; explicit&#34;版。因此,它不包括在比较中。Method 3
的输入为gpuArray
- ed。这并没有提供改进的性能(甚至有些降低它们),可能是由于错误的实现,或者与RAM和VRAM之间来回复制矩阵相关的开销。