为什么我对对数函数的拟合看起来如此错误
Why my fit for a logarithm function looks so wrong
我正在策划 this dataset and making a logarithmic fit, but, for some reason, the fit seems to be strongly wrong,在某些时候我得到了足够好的契合度,但后来我重新策划了并且不太契合。一开始有一个 0.0 0.0076
但我将其更改为 0.001 0.0076
以避免渐近线。
我正在使用(不完全是上图中的这个,但现在我正在测试这个,也有不合适的)这个适合
f(x) = a*log(k*x + b)
fit = fit f(x) 'R_B/R_B.txt' via a, k, b
输出为this
此外,有时它说 7 次迭代如上面的屏幕截图所示,其他只有 1 次,当它“正确”适合时,它确实像 35 次迭代或其他东西并且得到 a = 32 如果我没记错
编辑:here is again the good one, the plot I got is this one。再一次,我重新策划并得到了那个奇怪的契合。奇怪的是,如果有0.0 0.0076
,当它即将显示合适的时候,gnuplot 会说“Undefined value during function evaluation
”,但是当我得到不好的时候,这条消息就不会显示了。
你知道为什么我总是遇到这种不一致的情况吗?感谢您的帮助
这里的问题是拟合算法从参数 a、k 和 b 的“错误”近似值开始,因此在最小化过程中它会找到局部最小值,而不是全局最小值。如果您为算法提供接近最佳值的起始值,则可以改善结果。例如,让我们从以下参数开始:
gnuplot> a=47.5087
gnuplot> k=0.226
gnuplot> b=1.0016
gnuplot> f(x)=a*log(k*x+b)
gnuplot> fit f(x) 'R_B.txt' via a,k,b
....
....
....
After 40 iterations the fit converged.
final sum of squares of residuals : 16.2185
rel. change during last iteration : -7.6943e-06
degrees of freedom (FIT_NDF) : 18
rms of residuals (FIT_STDFIT) = sqrt(WSSR/ndf) : 0.949225
variance of residuals (reduced chisquare) = WSSR/ndf : 0.901027
Final set of parameters Asymptotic Standard Error
======================= ==========================
a = 35.0415 +/- 2.302 (6.57%)
k = 0.372381 +/- 0.0461 (12.38%)
b = 1.07012 +/- 0.02016 (1.884%)
correlation matrix of the fit parameters:
a k b
a 1.000
k -0.994 1.000
b 0.467 -0.531 1.000
结果图是
现在的问题是如何找到参数的“良好”初始近似值?好吧,你从
开始
如果你对这个方程进行微分,你会得到
或
这个等式的 left-hand 边是某个常数 'C',所以 right-hand 边的表达式也应该等于这个常数:
换句话说,你的数据的导数的倒数应该用一个线性函数来近似。因此,根据您的数据 x[i]
、y[i]
,您可以构建倒数导数 x[i]
、(x[i+1]-x[i])/(y[i+1]-y[i])
以及这些数据的线性拟合:
拟合给出以下值:
C*k = 0.0236179
C*b = 0.106268
现在,我们需要找到 a
和 C
的值。比方说,我们希望生成的图形靠近数据集的起点和终点。也就是说,我们想要
a*log(k*x1 + b) = y1
a*log(k*xn + b) = yn
因此,
a*log((C*k*x1 + C*b)/C) = a*log(C*k*x1 + C*b) - a*log(C) = y1
a*log((C*k*xn + C*b)/C) = a*log(C*k*xn + C*b) - a*log(C) = yn
通过减去方程式,我们得到 a 的值:
a = (yn-y1)/log((C*k*xn + C*b)/(C*k*x1 + C*b)) = 47.51
然后,
log(k*x1+b) = y1/a
k*x1+b = exp(y1/a)
C*k*x1+C*b = C*exp(y1/a)
据此我们可以计算出C:
C = (C*k*x1+C*b)/exp(y1/a)
最后找到 k
和 b
:
k=0.226
b=1.0016
这些是上面用于找到更合适的值。
更新
您可以使用以下脚本自动执行上述过程:
# Name of the file with the data
data='R_B.txt'
# The coordinates of the last data point
xn=NaN
yn=NaN
# The temporary coordinates of a data point used to calculate a derivative
x0=NaN
y0=NaN
linearFit(x)=Ck*x+Cb
fit linearFit(x) data using (xn=,dx=-x0,x0=,):(yn=,dy=-y0,y0=,dx/dy) via Ck, Cb
# The coordinates of the first data point
x1=NaN
y1=NaN
plot data using (x1=):(y1=) every ::0::0
a=(yn-y1)/log((Ck*xn+Cb)/(Ck*x1+Cb))
C=(Ck*x1+Cb)/exp(y1/a)
k=Ck/C
b=Cb/C
f(x)=a*log(k*x+b)
fit f(x) data via a,k,b
plot data, f(x)
pause -1
正如我在评论中已经提到的那样,拟合反导数的方法比拟合导数要好得多,因为当数据稍微分散时,导数的数值演算会强烈分散。
拟合积分方程(由待拟合的原方程得到)的方法原理在https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales中有说明。 y=a.ln(c.x+b)的应用如下图
数值微积分:
为了获得更好的结果(根据一些指定的拟合标准),可以使用上述参数值作为迭代非线性回归方法的初始值,在一些方便的软件中实现。
注意:本例中使用的积分方程为:
注:上图可以用积分方程拟合的方法与用导数拟合的方法进行比较
致谢:Alex Sveshnikov 在应用导数回归方法方面做得非常出色。这允许进行有趣且有启发性的比较。如果目标只是计算要在非线性回归软件中使用的参数的近似值,则这两种方法是完全等价的。然而,在数据分散的情况下,积分方程的方法似乎更可取。
更新(在 Alex Sveshnikov 更新他的回答后)
下图是利用Alex Sveshnikov的结果进一步迭代拟合得到的
两条曲线几乎没有区别。这表明(在本例中)拟合积分方程的方法几乎已经足够了,无需进一步处理。
当然这并不总是那么令人满意。这是由于数据的低分散。
在 ADDITION 中,回答 CosmeticMichu 在评论中提出的问题:
我正在策划 this dataset and making a logarithmic fit, but, for some reason, the fit seems to be strongly wrong,在某些时候我得到了足够好的契合度,但后来我重新策划了并且不太契合。一开始有一个 0.0 0.0076
但我将其更改为 0.001 0.0076
以避免渐近线。
我正在使用(不完全是上图中的这个,但现在我正在测试这个,也有不合适的)这个适合
f(x) = a*log(k*x + b)
fit = fit f(x) 'R_B/R_B.txt' via a, k, b
输出为this
此外,有时它说 7 次迭代如上面的屏幕截图所示,其他只有 1 次,当它“正确”适合时,它确实像 35 次迭代或其他东西并且得到 a = 32 如果我没记错
编辑:here is again the good one, the plot I got is this one。再一次,我重新策划并得到了那个奇怪的契合。奇怪的是,如果有0.0 0.0076
,当它即将显示合适的时候,gnuplot 会说“Undefined value during function evaluation
”,但是当我得到不好的时候,这条消息就不会显示了。
你知道为什么我总是遇到这种不一致的情况吗?感谢您的帮助
这里的问题是拟合算法从参数 a、k 和 b 的“错误”近似值开始,因此在最小化过程中它会找到局部最小值,而不是全局最小值。如果您为算法提供接近最佳值的起始值,则可以改善结果。例如,让我们从以下参数开始:
gnuplot> a=47.5087
gnuplot> k=0.226
gnuplot> b=1.0016
gnuplot> f(x)=a*log(k*x+b)
gnuplot> fit f(x) 'R_B.txt' via a,k,b
....
....
....
After 40 iterations the fit converged.
final sum of squares of residuals : 16.2185
rel. change during last iteration : -7.6943e-06
degrees of freedom (FIT_NDF) : 18
rms of residuals (FIT_STDFIT) = sqrt(WSSR/ndf) : 0.949225
variance of residuals (reduced chisquare) = WSSR/ndf : 0.901027
Final set of parameters Asymptotic Standard Error
======================= ==========================
a = 35.0415 +/- 2.302 (6.57%)
k = 0.372381 +/- 0.0461 (12.38%)
b = 1.07012 +/- 0.02016 (1.884%)
correlation matrix of the fit parameters:
a k b
a 1.000
k -0.994 1.000
b 0.467 -0.531 1.000
结果图是
现在的问题是如何找到参数的“良好”初始近似值?好吧,你从
开始如果你对这个方程进行微分,你会得到
或
这个等式的 left-hand 边是某个常数 'C',所以 right-hand 边的表达式也应该等于这个常数:
换句话说,你的数据的导数的倒数应该用一个线性函数来近似。因此,根据您的数据 x[i]
、y[i]
,您可以构建倒数导数 x[i]
、(x[i+1]-x[i])/(y[i+1]-y[i])
以及这些数据的线性拟合:
拟合给出以下值:
C*k = 0.0236179
C*b = 0.106268
现在,我们需要找到 a
和 C
的值。比方说,我们希望生成的图形靠近数据集的起点和终点。也就是说,我们想要
a*log(k*x1 + b) = y1
a*log(k*xn + b) = yn
因此,
a*log((C*k*x1 + C*b)/C) = a*log(C*k*x1 + C*b) - a*log(C) = y1
a*log((C*k*xn + C*b)/C) = a*log(C*k*xn + C*b) - a*log(C) = yn
通过减去方程式,我们得到 a 的值:
a = (yn-y1)/log((C*k*xn + C*b)/(C*k*x1 + C*b)) = 47.51
然后,
log(k*x1+b) = y1/a
k*x1+b = exp(y1/a)
C*k*x1+C*b = C*exp(y1/a)
据此我们可以计算出C:
C = (C*k*x1+C*b)/exp(y1/a)
最后找到 k
和 b
:
k=0.226
b=1.0016
这些是上面用于找到更合适的值。
更新
您可以使用以下脚本自动执行上述过程:
# Name of the file with the data
data='R_B.txt'
# The coordinates of the last data point
xn=NaN
yn=NaN
# The temporary coordinates of a data point used to calculate a derivative
x0=NaN
y0=NaN
linearFit(x)=Ck*x+Cb
fit linearFit(x) data using (xn=,dx=-x0,x0=,):(yn=,dy=-y0,y0=,dx/dy) via Ck, Cb
# The coordinates of the first data point
x1=NaN
y1=NaN
plot data using (x1=):(y1=) every ::0::0
a=(yn-y1)/log((Ck*xn+Cb)/(Ck*x1+Cb))
C=(Ck*x1+Cb)/exp(y1/a)
k=Ck/C
b=Cb/C
f(x)=a*log(k*x+b)
fit f(x) data via a,k,b
plot data, f(x)
pause -1
正如我在评论中已经提到的那样,拟合反导数的方法比拟合导数要好得多,因为当数据稍微分散时,导数的数值演算会强烈分散。
拟合积分方程(由待拟合的原方程得到)的方法原理在https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales中有说明。 y=a.ln(c.x+b)的应用如下图
数值微积分:
为了获得更好的结果(根据一些指定的拟合标准),可以使用上述参数值作为迭代非线性回归方法的初始值,在一些方便的软件中实现。
注意:本例中使用的积分方程为:
注:上图可以用积分方程拟合的方法与用导数拟合的方法进行比较
致谢:Alex Sveshnikov 在应用导数回归方法方面做得非常出色。这允许进行有趣且有启发性的比较。如果目标只是计算要在非线性回归软件中使用的参数的近似值,则这两种方法是完全等价的。然而,在数据分散的情况下,积分方程的方法似乎更可取。
更新(在 Alex Sveshnikov 更新他的回答后)
下图是利用Alex Sveshnikov的结果进一步迭代拟合得到的
两条曲线几乎没有区别。这表明(在本例中)拟合积分方程的方法几乎已经足够了,无需进一步处理。
当然这并不总是那么令人满意。这是由于数据的低分散。
在 ADDITION 中,回答 CosmeticMichu 在评论中提出的问题: