线性函数的快速拟合。软件

Fast fit of linear function. Matlab

在我的代码中我遇到了一个瓶颈,我在其中为我的数据拟合了一个线性函数。简单地用一条线拟合数据点并找到等式 y=k*x+b 的参数 kbR^2

MATLAB 中有很多函数可以做到这一点。我使用 polyfit() 函数。但这似乎对我的需求有点矫枉过正。问题是我必须执行大量这些拟合(10^8 或接近它)。

这是我的代码示例:

nLines=5; % may be up to 10^8;
X=cellfun(@(x) rand(randi([50 100]),1),num2cell([1:nLines]'),...
    'UniformOutput',false);
Y=cellfun(@(x) rand(numel(x),1),X,...
    'UniformOutput',false);
K=nan(numel(X),1);
B=nan(numel(X),1);
R=nan(numel(X),1);
for iLine=1:numel(X)   
   coefs = polyfit(X{iLine}, Y{iLine}, 1);
   yf=polyval(coefs,X{iLine});
   K(iLine)=coefs(1);
   B(iLine)=coefs(2);
   R(iLine)=corr(Y{iLine},yf);
end

您能帮助解决如此庞大的线性拟合问题吗?


P.S。我正在使用 MATLAB R2017b,具有以下工具箱:

Optimization Toolbox 
Signal Processing Toolbox 
Statistics and Machine Learning Toolbox  

看来我找到了答案。我可以让我的 seqs 大小相同,只是在最后添加 NaNs 这个变体非常快,然后是 polyfit 解决方案。

%% Generate data
nLines=10^3; % may be up to 10^8;
X=cellfun(@(x) rand(randi([50 100]),1),num2cell([1:nLines]'),...
    'UniformOutput',false);
Y=cellfun(@(x) rand(numel(x),1),X,...
    'UniformOutput',false);
K=nan(numel(X),1);
B=nan(numel(X),1);
R=nan(numel(X),1);
dur1=[];
dur2=[];
%% Small hack 
% elongate all seqs by NaNs to obtain same size
longestLineSize=max(cellfun(@(x) numel(x),X));
matrixX=[];
matrixY=[];
N=[];
for iLine=1:numel(X)
    matrixX=[matrixX,[X{iLine};nan(longestLineSize-numel(1,X{iLine}),1)]];
    matrixY=[matrixY,[Y{iLine};nan(longestLineSize-numel(1,X{iLine}),1)]];
    N=[N, numel(1,X{iLine})];
end
for iRep=1:100
%% Vectorized approach
start=tic;
sumX=nansum(matrixX);
sumY=nansum(matrixY);
sumX2=nansum(matrixX.^2);
sum2X=sumX.^2;

sum2Y=sumY.^2;
XY=matrixX.*matrixY;
sumXY=nansum(XY);
nominator=N.*sumXY-sumX.*sumY;
denominator=(N.*sumX2-sum2X);

k=nominator./denominator;
b=(sumY-k.*sumX)./N;
r=nominator./sqrt(denominator.*(N.*nansum(matrixY.^2)-sum2Y));
dur1(end+1)=toc(start);
%% polyfit solution
start=tic;
for iLine=1:numel(X)   
   coefs = polyfit(X{iLine}, Y{iLine}, 1);
   yf=polyval(coefs,X{iLine});
   K(iLine)=coefs(1);
   B(iLine)=coefs(2);

   R(iLine)=corr(Y{iLine},yf);
end
dur2(end+1)=toc(start);
end