如何计算scipy中曲线拟合的可能性?

8
我有一个非线性模型拟合,看起来像这样:
暗实线是模型拟合,灰色部分是原始数据。
简短的问题版本:如何获得此模型拟合的似然度,以便我可以执行对数似然比检验?假设残差服从正态分布。
我相对较新于统计学,我的当前想法是:
1.从曲线拟合中获取残差,并计算残差的方差; 2.使用以下公式并将残差方差插入sigma-squared,x_i作为实验和mu作为模型拟合; 3.计算对数似然比。
能否有人帮助我回答这两个完整的问题?
1.我的方法正确吗?(我认为是,但最好确保!) 2.python/scipy/statsmodels中是否有任何现成的函数可以为我完成此操作?

如果你的残差服从正态分布,你只需要使用最小二乘法来得到具有最高似然度的模型。你能展示一下你已经尝试过什么吗?只是想知道这不是作业吗? - usethedeathstar
@usethedeathstar 0) 哈哈 - 这不是作业,只是想回应一篇研究论文的评论; 2) 模型拟合已经通过残差的最小二乘法完成,我正在尝试执行似然比检验; 3) 要执行任何基于似然的工作,我需要先获得似然,这是我的问题4) 我已经在“我的当前想法是...”下写了我尝试过的内容。最后,对统计学真的很幼稚,感到抱歉:( - Yuxiang Wang
虽然这个问题写得很好,表述清晰,但是把这个问题转移到http://stats.stackexchange.com/可能更值得,因为这是一个_编程_网站。 - Hooked
@Hooked 感谢您的建议!请问能否告知具体操作方法...?我需要手动复制粘贴到那里吗? - Yuxiang Wang
你可以直接删除这个问题并重新发布它(格式已经完成!)。将评论纳入新问题中也不会有什么损失。祝好运! - Hooked
2个回答

7

你的似然函数是高斯分布概率密度函数对数和的总和。

enter image description here

它表示的是拟合残差mu和sigma的可能性,而不是模型给定数据的可能性。简单来说,你的方法是错误的

由于你在进行非线性最小二乘,所以按照@usethedeathstar提到的,你应该直接采用F检验。考虑下面的例子(修改自http://www.walkingrandomly.com/?p=5254),我们使用R进行F检验。最后我们将讨论如何将其翻译成python

# construct the data vectors using c()
> xdata = c(-2,-1.64,-1.33,-0.7,0,0.45,1.2,1.64,2.32,2.9)
> ydata = c(0.699369,0.700462,0.695354,1.03905,1.97389,2.41143,1.91091,0.919576,-0.730975,-1.42001)
# some starting values
> p1 = 1
> p2 = 0.2
> p3 = 0.01

# do the fit
> fit1 = nls(ydata ~ p1*cos(p2*xdata) + p2*sin(p1*xdata), start=list(p1=p1,p2=p2))
> fit2 = nls(ydata ~ p1*cos(p2*xdata) + p2*sin(p1*xdata)+p3*xdata, start=list(p1=p1,p2=p2,p3=p3))

# summarise
> summary(fit1)

Formula: ydata ~ p1 * cos(p2 * xdata) + p2 * sin(p1 * xdata)

Parameters:
   Estimate Std. Error t value Pr(>|t|)    
p1 1.881851   0.027430   68.61 2.27e-12 ***
p2 0.700230   0.009153   76.51 9.50e-13 ***
---
Signif. codes:  0 ?**?0.001 ?*?0.01 ??0.05 ??0.1 ??1

Residual standard error: 0.08202 on 8 degrees of freedom

Number of iterations to convergence: 7 
Achieved convergence tolerance: 2.189e-06

> summary(fit2)

Formula: ydata ~ p1 * cos(p2 * xdata) + p2 * sin(p1 * xdata) + p3 * xdata

Parameters:
   Estimate Std. Error t value Pr(>|t|)    
p1  1.90108    0.03520  54.002 1.96e-10 ***
p2  0.70657    0.01167  60.528 8.82e-11 ***
p3  0.02029    0.02166   0.937     0.38    
---
Signif. codes:  0 ?**?0.001 ?*?0.01 ??0.05 ??0.1 ??1

Residual standard error: 0.08243 on 7 degrees of freedom

Number of iterations to convergence: 9 
Achieved convergence tolerance: 2.476e-06

> anova(fit2, fit1)
Analysis of Variance Table

Model 1: ydata ~ p1 * cos(p2 * xdata) + p2 * sin(p1 * xdata) + p3 * xdata
Model 2: ydata ~ p1 * cos(p2 * xdata) + p2 * sin(p1 * xdata)
  Res.Df Res.Sum Sq Df     Sum Sq F value Pr(>F)
1      7   0.047565                             
2      8   0.053813 -1 -0.0062473  0.9194 0.3696

这里有两个模型,fit1有2个参数,因此残差自由度为8; fit2有一个额外的参数,残差自由度为7。第二个模型是否更好?不是的,F值为0.9194,在(1,7)自由度上不显著。

要得到ANOVA表:残差自由度很容易算出,残差平方和:0.08202*0.08202*8=0.053810.08243*0.08243*7=0.04756293(注意:'Residual standard error: 0.08243 on 7 degrees of freedom'等)。在python中,您可以通过(y_observed-y_fitted)**2来获得它,因为scipy.optimize.curve_fit()不返回残差。

F-ratio0.0062473/0.047565*7,而P值可通过1-scipy.stats.f.cdf(0.9194, 1, 7)获得。

将它们放在一起,我们有python等效代码:

In [1]:

import scipy.optimize as so
import scipy.stats as ss
xdata = np.array([-2,-1.64,-1.33,-0.7,0,0.45,1.2,1.64,2.32,2.9])
ydata = np.array([0.699369,0.700462,0.695354,1.03905,1.97389,2.41143,1.91091,0.919576,-0.730975,-1.42001])
def model0(x,p1,p2):
    return p1*np.cos(p2*x) + p2*np.sin(p1*x)
def model1(x,p1,p2,p3):
    return p1*np.cos(p2*x) + p2*np.sin(p1*x)+p3*x
p1, p2, p3 = 1, 0.2, 0.01
fit0=so.curve_fit(model0, xdata, ydata, p0=(p1,p2))[0]
fit1=so.curve_fit(model1, xdata, ydata, p0=(p1,p2,p3))[0]
yfit0=model0(xdata, fit0[0], fit0[1])
yfit1=model1(xdata, fit1[0], fit1[1], fit1[2])
ssq0=((yfit0-ydata)**2).sum()
ssq1=((yfit1-ydata)**2).sum()
df=len(xdata)-3
f_ratio=(ssq0-ssq1)/(ssq1/df)
p=1-ss.f.cdf(f_ratio, 1, df)
In [2]:

print f_ratio, p
0.919387419515 0.369574503394

正如@usethedeathstar所指出的那样:当残差服从正态分布时,非线性最小二乘法就是最大似然估计。因此F检验和似然比检验是等价的。因为F值是似然比λ的单调转换。
或者用描述性的方式来说,参见:http://www.stata.com/support/faqs/statistics/chi-squared-and-f-distributions/

非常感谢!那节省了我一周的时间。有一个跟进问题:如果拟合的残差不服从正态分布(尽管最小二乘法用于拟合),F检验仍然有效吗? - Yuxiang Wang
2
在stats.stackexchange.com上的人会有更好的意见。理论上可能是这样,但实际上,F检验在正态性假设方面非常稳健,因此大多数情况下仍然可以使用它。希望这能帮到你。祝你复习顺利! - CT Zhu
明白了。再次感谢您! - Yuxiang Wang

0

你的公式看起来对我来说是正确的。它应该会给你与 scipy.stats.norm.logpdf(x, loc=mu, scale=sigma) 相同的结果。

既然你已经有了 mu 和 sigma 的估计值,我不认为有一个函数可以让你将结果插入到似然比检验中。

如果你有两个模型的估计值,其中一个嵌套在另一个中,那么你可以很容易地自己计算。

http://en.wikipedia.org/wiki/Likelihood-ratio_test

这是statsmodels中一个方法的一部分,用于计算LR检验以比较两个嵌套线性模型。 https://github.com/statsmodels/statsmodels/blob/master/statsmodels/regression/linear_model.py#L1531

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接