为什么我对对数函数的拟合看起来如此错误

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

现在,我们需要找到 aC 的值。比方说,我们希望生成的图形靠近数据集的起点和终点。也就是说,我们想要

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)

最后找到 kb:

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 在评论中提出的问题: