首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Matlab中用一系列分段直线拟合一条曲线?

如何在Matlab中用一系列分段直线拟合一条曲线?
EN

Stack Overflow用户
提问于 2012-09-24 05:38:15
回答 3查看 9.7K关注 0票数 5

我有一个简单的对数曲线,如上所述。Matlab中有没有一些函数可以用分段的直线来拟合这条曲线,并显示这些直线段的起点和终点?我已经检查了matlab中的曲线拟合工具箱。他们似乎是通过一条直线或一些函数来进行曲线拟合。我不想只用一条线来拟合曲线。

如果没有直接函数,任何实现相同目标的替代方案都可以。我的目标是通过分段直线来拟合曲线,并获得这些分段的端点位置。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-24 06:30:00

首先,你的问题不叫曲线拟合。曲线拟合是当你有数据的时候,在某种意义上,你找到了描述它的最佳函数。另一方面,您希望创建函数的分段线性近似。

我建议采取以下策略:

  1. 手动拆分为多个部分。截面大小应取决于导数,大导数和小截面
  2. 采样分段之间的节点处的函数
  3. 找到通过上述点的线性插值。

下面是一个这样做的代码示例。您可以看到,红线(插值)非常接近原始函数,尽管有少量的部分。这是由自适应截面大小引起的。

代码语言:javascript
复制
function fitLogLog()
   x = 2:1000;
   y = log(log(x));

   %# Find section sizes, by using an inverse of the approximation of the derivative
   numOfSections = 20;
   indexes = round(linspace(1,numel(y),numOfSections));
   derivativeApprox = diff(y(indexes));
   inverseDerivative = 1./derivativeApprox;
   weightOfSection =  inverseDerivative/sum(inverseDerivative);   
   totalRange = max(x(:))-min(x(:));   
   sectionSize = weightOfSection.* totalRange;

   %# The relevant nodes
   xNodes = x(1) + [ 0 cumsum(sectionSize)];
   yNodes = log(log(xNodes));

   figure;plot(x,y);   
   hold on;
   plot (xNodes,yNodes,'r');
   scatter (xNodes,yNodes,'r');
   legend('log(log(x))','adaptive linear interpolation');
end
票数 7
EN

Stack Overflow用户

发布于 2012-09-24 07:33:33

Andrey的自适应解决方案提供了更精确的整体拟合。但是,如果您想要的是固定长度的片段,那么这里有一些东西应该是有效的,使用一个方法也可以返回所有拟合值的完整集合。如果需要速度,可以矢量化。

代码语言:javascript
复制
Nsamp = 1000;     %number of data samples on x-axis
x = [1:Nsamp];    %this is your x-axis
Nlines = 5;       %number of lines to fit

fx = exp(-10*x/Nsamp);  %generate something like your current data, f(x)
gx = NaN(size(fx));     %this will hold your fitted lines, g(x)

joins = round(linspace(1, Nsamp, Nlines+1));  %define equally spaced breaks along the x-axis

dx = diff(x(joins));   %x-change
df = diff(fx(joins));  %f(x)-change

m = df./dx;   %gradient for each section

for i = 1:Nlines
   x1 = joins(i);   %start point
   x2 = joins(i+1); %end point
   gx(x1:x2) = fx(x1) + m(i)*(0:dx(i));   %compute line segment
end

subplot(2,1,1)
h(1,:) = plot(x, fx, 'b', x, gx, 'k', joins, gx(joins), 'ro');
title('Normal Plot')

subplot(2,1,2)
h(2,:) = loglog(x, fx, 'b', x, gx, 'k', joins, gx(joins), 'ro');
title('Log Log Plot')

for ip = 1:2
    subplot(2,1,ip)
    set(h(ip,:), 'LineWidth', 2)
    legend('Data', 'Piecewise Linear', 'Location', 'NorthEastOutside')
    legend boxoff
end

票数 5
EN

Stack Overflow用户

发布于 2014-01-22 08:01:13

这不是这个问题的确切答案,但由于我是基于搜索到达这里的,所以我想回答相关的问题,即如何创建(而不是拟合)分段线性函数,该函数旨在表示散点图中区间数据的平均值(或中值,或其他一些函数)。

首先,使用回归的一个相关但更复杂的替代方案是Multivariate adaptive regression splines,它显然具有some MATLAB code listed on the wikipedia page

这里的解决方案是只计算重叠区间的平均值来获得点

代码语言:javascript
复制
function [x, y] = intervalAggregate(Xdata, Ydata, aggFun, intStep, intOverlap)
% intOverlap in [0, 1); 0 for no overlap of intervals, etc.
% intStep    this is the size of the interval being aggregated.

minX = min(Xdata);
maxX = max(Xdata);

minY = min(Ydata);
maxY = max(Ydata);

intInc = intOverlap*intStep; %How far we advance each iteraction.
if intOverlap <= 0
   intInc = intStep;
end
nInt = ceil((maxX-minX)/intInc); %Number of aggregations

parfor i = 1:nInt
    xStart = minX + (i-1)*intInc;
    xEnd   = xStart + intStep;
    intervalIndices = find((Xdata >= xStart) & (Xdata <= xEnd));
    x(i) = aggFun(Xdata(intervalIndices));
    y(i) = aggFun(Ydata(intervalIndices));
end

例如,为了计算一些成对的X和Y数据的平均值,我手边有长度为0.1的间隔,它们彼此之间有大约1/3的重叠(参见散点图像):

均值x,y= intervalAggregate(Xdat,Ydat,@

,0.1,0.333)

X=

第1至8列

代码语言:javascript
复制
0.0552    0.0868    0.1170    0.1475    0.1844    0.2173    0.2498    0.2834

第9至15列

代码语言:javascript
复制
0.3182    0.3561    0.3875    0.4178    0.4494    0.4671    0.4822

Y=

第1至8列

代码语言:javascript
复制
0.9992    0.9983    0.9971    0.9955    0.9927    0.9905    0.9876    0.9846

第9至15列

代码语言:javascript
复制
0.9803    0.9750    0.9707    0.9653    0.9598    0.9560    0.9537

我们看到,随着x的增加,y趋于略微减小。从那里,很容易绘制线段和/或执行一些其他类型的平滑。

(请注意,我并没有试图向量化这个解决方案;如果对Xdata进行排序,则可以假定有一个速度快得多的版本。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12556491

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档