Matlab:线性拟合的最佳点数

5
我想对几个数据点进行线性拟合,如图所示。由于我知道截距(在这种情况下为0.05),因此我只想拟合具有特定截距的线性区域中的点。在这种情况下,它将是5:22的点(但不包括22:30)。 我正在寻找简单的算法来确定这些最佳点的数量,基于...嗯,问题就在这里... R ^ 2?有任何想法吗? 我考虑使用点1到2:30、2到3:30等来探测拟合的R ^ 2,但我真的不知道如何将其编写成清晰简单的函数。对于具有固定截距的拟合,我使用polyfit0 (http://www.mathworks.com/matlabcentral/fileexchange/272-polyfit0-m)。谢谢任何建议!
编辑: 样本数据:
intercept = 0.043;
x = 0.01:0.01:0.3;
y = [0.0530642513911393,0.0600786706929529,0.0673485248329648,0.0794662409166333,0.0895915873196170,0.103837395346484,0.107224784565365,0.120300492775786,0.126318699218730,0.141508831492330,0.147135757370947,0.161734674733680,0.170982455701681,0.191799936622712,0.192312642057298,0.204771365716483,0.222689541632988,0.242582251060963,0.252582727297656,0.267390860166283,0.282890010610515,0.292381165948577,0.307990544720676,0.314264952297699,0.332344368808024,0.355781519885611,0.373277721489254,0.387722683944356,0.413648156978284,0.446500064130389;];

linear fit


必须点始终连续吗?或者接受的拟合是否包括x范围中的间隙?例如(1:5,8:23,25,30)? - mathematician1975
我宁愿将它们保持连续。对于初始点来说,“非线性”来自定位误差,对于后来的点来说,则来自于长时间内的典型平均平方位移偏差。因此,没有理由排除单个点,除了一些特别明显的异常值(例如,MSD计算的拟合问题),这种情况通常不会发生。 - Art
2个回答

4
您所面临的问题是找到一个通用解决方案比较困难。
一种方法是计算所有相邻点之间的斜率/截距,然后对截距进行聚类分析:
slopes = diff(y)./diff(x);  
intersepts = y(1:end-1) - slopes.*x(1:end-1);

idx = kmeans(intersepts, 3);

x([idx; 3] == 2)  % the points with the intersepts closest to the linear one.

这需要使用统计工具箱(用于 kmeans)。这是我尝试的所有方法中最好的一种,虽然通过这种方式找到的点的范围可能会有一些小的空洞;例如,当起始和结束范围内两个点的斜率接近于线的斜率时,这些点将被检测为属于该线。这(和其他因素)需要对以这种方式找到的解进行更多的后处理。
另一种方法(我未能成功构建)是在循环中进行线性拟合,每次将点的范围从中间某个点向两个端点扩大,并查看平方误差的总和是否保持较小。我很快就放弃了这种方法,因为定义“小”是非常主观的,必须以某种启发式的方式完成。
我尝试了以上更系统和更健壮的方法:
function test

    %% example data
    slope = 2;
    intercept = 1.5;

    x = linspace(0.1, 5, 100).';

    y         = slope*x + intercept;
    y(1:12)   = log(x(1:12)) + y(12)-log(x(12));
    y(74:100) = y(74:100) + (x(74:100)-x(74)).^8;

    y = y + 0.2*randn(size(y));


    %% simple algorithm

    [X,fn] = fminsearch(@(ii)P(ii, x,y,intercept), [0.5 0.5])

    [~,inds] = P(X, y,x,intercept)

end

function [C, inds] = P(ii, x,y,intercept)
% ii represents fraction of range from center to end,
% So ii lies between 0 and 1. 

    N = numel(x);
    n = round(N/2);  

    ii = round(ii*n);

    inds = min(max(1, n+(-ii(1):ii(2))), N);

    % Solve linear system with fixed intercept
    A = x(inds);
    b = y(inds) - intercept;

    % and return the sum of squared errors, divided by 
    % the number of points included in the set. This 
    % last step is required to prevent fminsearch from
    % reducing the set to 1 point (= minimum possible 
    % squared error). 
    C = sum(((A\b)*A - b).^2)/numel(inds);    

end

在这个例子中,这只是找到了所需索引(12和74)的粗略近似。

当使用随机起始值(实际上只是rand(1,2))多次运行fminsearch时,它变得更加可靠,但我仍然不会把我的生命押在上面。

如果您拥有统计工具箱,请使用kmeans选项。


@Art:哦,等等,截距是固定的 - Rody Oldenhuis
是的,截距是固定的,这就是整个想法。因此,知道截距后,我想判断哪些点是“最佳”的(因为有时存在第二个范围,也是线性的,但具有完全不同的截距和斜率)。 - Art
这两种方法对我来说已经足够了。感谢Rody花费时间和精力解决像我这样的新手有时非常琐碎的问题,编程是解决其他问题的工具。再次感谢您的帮助! - Art
回答你的问题 - 幸运的是我不必经常这样做。它只发生在数据集几次之间。更像是自动拟合建议,或者说是可视化拟合的替代方案。谢谢! - Art
@Art:嗯,因为要处理的数据集非常少,而且我们能想到的自动方法有些不可靠,也许最好的办法是硬着头皮手动完成所有工作。通常情况下,人类的眼睛是无可替代的。 - Rody Oldenhuis
显示剩余5条评论

1
根据数据值的数量,我会将数据分成相对较少的重叠段,并为每个段计算线性拟合,或者说是一阶系数(请记住,你知道截距,所有段的截距都相同)。
然后,对于每个系数,计算这条假设线与整个数据集之间的均方误差(MSE),选择产生最小MSE的系数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接