我想对绘制的数据拟合衰减指数。我没有曲线拟合或优化工具箱。
x = [0 0.0036 0.0071 0.0107 0.0143 0.0178 0.0214 0.0250 0.0285 0.0321 0.0357 0.0392 0.0428 0.0464 0.0464];
y = [1.3985 1.3310 1.2741 1.2175 1.1694 1.1213 1.0804 1.0395 1.0043 0.9691 0.9385 0.9080 0.8809 0.7856 0.7856];
figure()
plot(x,y,'*')
我怎样才能在MATLAB中实现这个目标?
答案 0 :(得分:8)
假设输入和输出点之间存在高斯分布式误差,并假设误差是加性的,您可以通过经典least squares来解决这个问题。它归结为具有超定线性方程组,其中每个约束定义一个输入 - 输出观察。以最少的残余误差求解这个超定线性系统是您正在寻找的解决方案。
Jubobs在下面对我的评论中提出了一个非常有趣的观点。通常,最小化该残余误差的参数不会使原始问题的残留误差最小化。这个线性化步骤允许我们以更简单的方式解决参数,但这不是等效问题。但是,它通常在实践中被接受,因为解决方案足够好。
为了将其变为线性系统,我们需要做一些巧妙的重新排列。由于您希望使用指数模型拟合一系列点,因此输入x
和输出y
之间的关系为:
为了使其成为“线性”,我们可以采用双方的自然对数:
通过使用ln(ab) = ln(a) + ln(b)
的事实,我们有:
同时知道,这简化为:
如您所见,上述等式现在相对于对数空间是“线性的”。给定一堆x
和y
值,(x_1, x_2, ..., x_n)
和(y_1, y_2, ..., y_n)
,我们可以在线性系统中将一组方程连接在一起:
如果我们让ln(A) = A'
为了便于表示法,并重新排列它以使其呈矩阵形式,我们得到:
因此,我们只需要解决A'
和b
,您可以通过pseudoinverse来解决问题。具体而言,上述问题的形式如下:
因此,我们需要解决X
,以及:
M^{+}
是矩阵的伪逆。完成后,只需点击exp
上的A'
运算符即可获得原始A
。 MATLAB具有非常高效的线性系统求解器和最小二乘求解器。具体来说,您可以使用\
或ldivide
运算符。您所要做的就是从M
值创建x
矩阵,创建y
值的向量并解决您的系统问题。这很简单:
x = ...; %// Define numbers here - either row or column vectors
y = ...;
M = [ones(numel(x),1), x(:)]; %// Ensure x is a column vector
lny = log(y(:)); %// Ensure y is a column vector and take ln
X = M \ lny; %// Solve for parameters
A = exp(X(1)); %// Solve for A
b = X(2); %// Get b
因此,使用您的x
和y
值,这就是我得到的:
A =
1.3882
b =
-11.508
如果我们绘制上述点以及符合该线的指数曲线,我们可以这样做:
xval = linspace(min(x), max(x));
yval = A*exp(b*xval);
plot(x,y,'r.',xval,yval,'b');
第一行代码定义了一堆x
值,这些值跨越我们数据集的最小和最大x
值。对于下一行,我们接着x
值并通过指数模型运行它们。最后,我们将原始数据点以及指数曲线与上述过程中找到的参数一起绘制。这些点为红色,而线条为蓝色。
我们得到:
我认为看起来很不错!对于那些注意到的人,上面的图看起来与MATLAB生成的普通图和图窗口略有不同。该图是在Octave中生成的,因为我目前正在处理的计算机上没有MATLAB。但是,上面的代码仍然适用于MATLAB。
答案 1 :(得分:1)
对于像我这样愚蠢的人来说,整个代码(感谢rayryeng)是:
x = [0 0.0036 0.0071 0.0107 0.0143 0.0178 0.0214 0.0250 0.0285 0.0321 0.0357 0.0392 0.0428 0.0464 0.0464];
y = [1.3985 1.3310 1.2741 1.2175 1.1694 1.1213 1.0804 1.0395 1.0043 0.9691 0.9385 0.9080 0.8809 0.7856 0.7856];
M = [ones(numel(x),1), x(:)]; %// Ensure x is a column vector
lny = log(y(:)); %// Ensure y is a column vector and take ln
X = M\lny; %// Solve for parameters
A = exp(X(1)); %// Solve for A
b = X(2); %// Get b
xval = linspace(min(x), max(x));
yval = A*exp(b*xval);
plot(x,y,'r.',xval,yval,'b');