MATLAB - 没有工具箱的指数曲线拟合
MATLAB - Exponential Curve Fitting without Toolbox
我有数据点 (x, y) 需要拟合指数函数,
y = A + B * exp(C * x),
但我既不能使用曲线拟合工具箱,也不能使用优化工具箱。
用户 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');
但是,这段代码只拟合方程没有偏移
y = A * exp(B * x).
如何扩展此代码以拟合三参数方程?
在另一次尝试中,我设法使用 fminsearch
:
来拟合函数
function [xval, yval] = curve_fitting_exponential_1_optimized(x,y,xval)
start_point = rand(1, 3);
model = @expfun;
est = fminsearch(model, start_point);
function [sse, FittedCurve] = expfun(params)
A = params(1);
B = params(2);
C = params(3);
FittedCurve = A + B .* exp(-C * x);
ErrorVector = FittedCurve - y;
sse = sum(ErrorVector .^ 2);
end
yval = est(1)+est(2) * exp(-est(3) * xval);
end
这里的问题是结果取决于随机选择的起点,所以我没有得到稳定的解决方案。但是因为我需要自动化的功能,所以我需要一些稳定的东西。如何获得稳定的解决方案?
如何为三个参数适配rayryeng的代码?
used the strategy to linearize a nonlinear equation so that standard regression methods can be applied. See also 回答类似问题。
如果存在非零偏移量 A,此策略将不再有效。我们可以通过粗略估计偏移量来解决这种情况。正如 rubenvb 在评论中提到的,我们可以通过 min(y)
来估计 A,但随后对数被应用于零。相反,我们可以在我们对 A 的猜测和数据的最小值之间留一点 space,比如其范围的一半。然后我们从数据中减去A,使用rayreng的方法:
x = x(:); % bring the data into the standard, more
y = y(:); % convenient format of column vectors
Aguess = min(y) - (max(y) - min(y) / 2;
guess = [ones(size(x)), -x] \ log(y - Aguess);
Bguess = exp(guess(1));
Cguess = guess(2);
对于给定的数据,这导致
Aguess = 0.4792
Bguess = 0.9440
Cguess = 21.7609
除了两个参数的情况,我们不能指望它是一个很好的拟合。它的 SSE 是 0.007331.
如何获得稳定的解决方案?
然而,这个猜测作为非线性优化的起点很有用:
start_point = [Aguess, Bguess, Cguess];
est = fminsearch(@expfun, start_point);
Aest = est(1);
Best = est(2);
Cest = est(3);
现在优化达到了稳定的估计,因为计算是确定性的:
Aest = -0.1266
Best = 1.5106
Cest = 10.2314
这个估计的 SSE 是 0.004041。
这是数据(蓝点)和拟合曲线(绿色:猜测,红色:优化)的样子:
这是整个功能的全部亮点 - 特别感谢 A. Donda!
function [xval, yval] = curve_fitting_exponential_1_optimized(x,y,xval)
x = x(:); % bring the data into the standard, more convenient format of column vectors
y = y(:);
Aguess = min(y) - (max(y)-min(y)) / 2;
guess = [ones(size(x)), -x] \ log(y - Aguess);
Bguess = exp(guess(1));
Cguess = guess(2);
start_point = [Aguess, Bguess, Cguess];
est = fminsearch(@expfun, start_point);
function [sse, FittedCurve] = expfun(params)
A = params(1);
B = params(2);
C = params(3);
FittedCurve = A + B .* exp(-C * x);
ErrorVector = FittedCurve - y;
sse = sum(ErrorVector .^ 2);
end
yval = est(1)+est(2) * exp(-est(3) * xval);
end
我有数据点 (x, y) 需要拟合指数函数,
y = A + B * exp(C * x),
但我既不能使用曲线拟合工具箱,也不能使用优化工具箱。
用户 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');
但是,这段代码只拟合方程没有偏移
y = A * exp(B * x).
如何扩展此代码以拟合三参数方程?
在另一次尝试中,我设法使用 fminsearch
:
function [xval, yval] = curve_fitting_exponential_1_optimized(x,y,xval)
start_point = rand(1, 3);
model = @expfun;
est = fminsearch(model, start_point);
function [sse, FittedCurve] = expfun(params)
A = params(1);
B = params(2);
C = params(3);
FittedCurve = A + B .* exp(-C * x);
ErrorVector = FittedCurve - y;
sse = sum(ErrorVector .^ 2);
end
yval = est(1)+est(2) * exp(-est(3) * xval);
end
这里的问题是结果取决于随机选择的起点,所以我没有得到稳定的解决方案。但是因为我需要自动化的功能,所以我需要一些稳定的东西。如何获得稳定的解决方案?
如何为三个参数适配rayryeng的代码?
如果存在非零偏移量 A,此策略将不再有效。我们可以通过粗略估计偏移量来解决这种情况。正如 rubenvb 在评论中提到的,我们可以通过 min(y)
来估计 A,但随后对数被应用于零。相反,我们可以在我们对 A 的猜测和数据的最小值之间留一点 space,比如其范围的一半。然后我们从数据中减去A,使用rayreng的方法:
x = x(:); % bring the data into the standard, more
y = y(:); % convenient format of column vectors
Aguess = min(y) - (max(y) - min(y) / 2;
guess = [ones(size(x)), -x] \ log(y - Aguess);
Bguess = exp(guess(1));
Cguess = guess(2);
对于给定的数据,这导致
Aguess = 0.4792
Bguess = 0.9440
Cguess = 21.7609
除了两个参数的情况,我们不能指望它是一个很好的拟合。它的 SSE 是 0.007331.
如何获得稳定的解决方案?
然而,这个猜测作为非线性优化的起点很有用:
start_point = [Aguess, Bguess, Cguess];
est = fminsearch(@expfun, start_point);
Aest = est(1);
Best = est(2);
Cest = est(3);
现在优化达到了稳定的估计,因为计算是确定性的:
Aest = -0.1266
Best = 1.5106
Cest = 10.2314
这个估计的 SSE 是 0.004041。
这是数据(蓝点)和拟合曲线(绿色:猜测,红色:优化)的样子:
这是整个功能的全部亮点 - 特别感谢 A. Donda!
function [xval, yval] = curve_fitting_exponential_1_optimized(x,y,xval)
x = x(:); % bring the data into the standard, more convenient format of column vectors
y = y(:);
Aguess = min(y) - (max(y)-min(y)) / 2;
guess = [ones(size(x)), -x] \ log(y - Aguess);
Bguess = exp(guess(1));
Cguess = guess(2);
start_point = [Aguess, Bguess, Cguess];
est = fminsearch(@expfun, start_point);
function [sse, FittedCurve] = expfun(params)
A = params(1);
B = params(2);
C = params(3);
FittedCurve = A + B .* exp(-C * x);
ErrorVector = FittedCurve - y;
sse = sum(ErrorVector .^ 2);
end
yval = est(1)+est(2) * exp(-est(3) * xval);
end