我有一个简单的 loglog 曲线,如上所述。Matlab中是否有一些函数可以通过分段线拟合这条曲线并显示这些线段的起点和终点?我已经检查了matlab中的曲线拟合工具箱。他们似乎通过一条线或某些功能进行曲线拟合。我不想仅通过一条线进行曲线拟合。
如果没有直接功能,那么实现相同目标的任何替代方法对我来说都可以。我的目标是通过分段线拟合曲线并获取这些段的端点位置。
我有一个简单的 loglog 曲线,如上所述。Matlab中是否有一些函数可以通过分段线拟合这条曲线并显示这些线段的起点和终点?我已经检查了matlab中的曲线拟合工具箱。他们似乎通过一条线或某些功能进行曲线拟合。我不想仅通过一条线进行曲线拟合。
如果没有直接功能,那么实现相同目标的任何替代方法对我来说都可以。我的目标是通过分段线拟合曲线并获取这些段的端点位置。
首先,您的问题不称为曲线拟合。曲线拟合是当你有数据时,你会找到描述它的最佳函数,在某种意义上。另一方面,您想要创建函数的分段线性逼近。
我建议以下策略:
这是执行此操作的代码示例。您可以看到红线(插值)非常接近原始函数,尽管部分数量很少。这是由于自适应部分大小而发生的。
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
Andrey 的自适应解决方案提供了更准确的整体拟合。但是,如果您想要的是固定长度的片段,那么这里应该可以使用一种方法,该方法还返回所有拟合值的完整集。如果需要速度,可以矢量化。
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
这不是这个问题的确切答案,但是由于我是根据搜索到达这里的,所以我想回答有关如何创建(不适合)旨在表示均值(或散点图中区间数据的中位数或其他一些函数)。
首先,使用回归的一个相关但更复杂的替代方案是多元自适应回归样条,它显然在维基百科页面上列出了一些 MATLAB 代码。
这里的解决方案是只计算重叠间隔的平均值以获得积分
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, @mean, 0.1, 0.333)
x =
第 1 至 8 列
0.0552 0.0868 0.1170 0.1475 0.1844 0.2173 0.2498 0.2834
第 9 至 15 列
0.3182 0.3561 0.3875 0.4178 0.4494 0.4671 0.4822
y =
第 1 至 8 列
0.9992 0.9983 0.9971 0.9955 0.9927 0.9905 0.9876 0.9846
第 9 至 15 列
0.9803 0.9750 0.9707 0.9653 0.9598 0.9560 0.9537
我们看到随着 x 的增加,y 趋于略微减小。从那里,很容易绘制线段和/或执行一些其他类型的平滑。
(请注意,我没有尝试对这个解决方案进行矢量化;如果对 Xdata 进行了排序,可以假设一个更快的版本。)