如何在python中运行非线性回归

Posted

技术标签:

【中文标题】如何在python中运行非线性回归【英文标题】:How to run non-linear regression in python 【发布时间】:2017-02-15 03:53:10 【问题描述】:

我在 python 中有以下信息(数据框)

product baskets scaling_factor
12345   475     95.5
12345   108     57.7
12345   2       1.4
12345   38      21.9
12345   320     88.8

我想运行以下非线性回归估计参数。

a、b 和 c

我想拟合的方程:

scaling_factor = a - (b*np.exp(c*baskets))

在sas中我们通常运行如下模型:(使用高斯牛顿法)

proc nlin data=scaling_factors;
 parms a=100 b=100 c=-0.09;
 model scaling_factor = a - (b * (exp(c*baskets)));
 output out=scaling_equation_parms 
parms=a b c;

是否有类似的方法来使用非线性回归估计 Python 中的参数,我如何在 python 中看到图。

【问题讨论】:

我建议你在scipy中检查非线性回归scipy-cookbook.readthedocs.io/items/robust_regression.html 是的,只是在看,但无法弄清楚他们如何在 y_train 中使用 t_train 【参考方案1】:

对于此类问题,我总是将scipy.optimize.minimize 与我自己的最小二乘函数一起使用。优化算法不能很好地处理各种输入之间的巨大差异,因此最好缩放函数中的参数,以便暴露给 scipy 的参数都在 1 的数量级上,就像我在下面所做的那样。

import numpy as np

baskets = np.array([475, 108, 2, 38, 320])
scaling_factor = np.array([95.5, 57.7, 1.4, 21.9, 88.8])

def lsq(arg):
    a = arg[0]*100
    b = arg[1]*100
    c = arg[2]*0.1
    now = a - (b*np.exp(c * baskets)) - scaling_factor
    return np.sum(now**2)

guesses = [1, 1, -0.9]
res = scipy.optimize.minimize(lsq, guesses)

print(res.message)
# 'Optimization terminated successfully.'

print(res.x)
# [ 0.97336709  0.98685365 -0.07998282]

print([lsq(guesses), lsq(res.x)])
# [7761.0093358076601, 13.055053196410928]

当然,与所有最小化问题一样,使用良好的初始猜测很重要,因为所有算法都可能陷入局部最小值。可以使用method关键字更改优化方法;一些可能性是

“内尔德-米德” “鲍威尔” ‘CG’ ‘BFGS’ “牛顿-CG”

根据the documentation默认为BFGS。

【讨论】:

非常感谢,出于好奇,默认使用哪种方法?我可以使用上面 sas 中的 proc nlin 中提到的 guesses=[100,100,-0.09] 吗?这与“scipy.optimize import least_squares”有何不同 @Mukul 我没有意识到这些是你的猜测,我不熟悉 SAS。我已经更新了使用这些值的答案。请注意,我已经对最小二乘函数中的参数进行了缩放,以使它们都接近 1。 好的。这似乎奏效了。但收到以下消息“由于精度损失不一定实现所需的错误”【参考方案2】:

同意 Chris Mueller 的观点,我也会使用 scipyscipy.optimize.curve_fit。 代码如下:

###the top two lines are required on my linux machine
import matplotlib
matplotlib.use('Qt4Agg')
import matplotlib.pyplot as plt
from matplotlib.pyplot import cm
import numpy as np
from scipy.optimize import curve_fit #we could import more, but this is what we need
###defining your fitfunction
def func(x, a, b, c):
    return a - b* np.exp(c * x) 
###OP's data
baskets = np.array([475, 108, 2, 38, 320])
scaling_factor = np.array([95.5, 57.7, 1.4, 21.9, 88.8])
###let us guess some start values
initialGuess=[100, 100,-.01]
guessedFactors=[func(x,*initialGuess ) for x in baskets]
###making the actual fit
popt,pcov = curve_fit(func, baskets, scaling_factor,initialGuess)
#one may want to
print popt
print pcov
###preparing data for showing the fit
basketCont=np.linspace(min(baskets),max(baskets),50)
fittedData=[func(x, *popt) for x in basketCont]
###preparing the figure
fig1 = plt.figure(1)
ax=fig1.add_subplot(1,1,1)
###the three sets of data to plot
ax.plot(baskets,scaling_factor,linestyle='',marker='o', color='r',label="data")
ax.plot(baskets,guessedFactors,linestyle='',marker='^', color='b',label="initial guess")
ax.plot(basketCont,fittedData,linestyle='-', color='#900000',label="fit with (0:0.2g,1:0.2g,2:0.2g)".format(*popt))
###beautification
ax.legend(loc=0, title="graphs", fontsize=12)
ax.set_ylabel("factor")
ax.set_xlabel("baskets")
ax.grid()
ax.set_title("$\mathrmcurve_\mathrmfit$")
###putting the covariance matrix nicely
tab= [[':.2g'.format(j) for j in i] for i in pcov]
the_table = plt.table(cellText=tab,
                  colWidths = [0.2]*3,
                  loc='upper right', bbox=[0.483, 0.35, 0.5, 0.25] )
plt.text(250,65,'covariance:',size=12)
###putting the plot
plt.show()
###done

最终,给你:

【讨论】:

哇。这与 sas 的输出完美匹配。非常感谢 @Mukul 不客气。请注意,您可以使用多个 scipy 函数获得类似的结果,包括 Chris Mueller 建议的 minimizeleastsq,例如如果您应用选项full_output,后一个也可以给出协方差矩阵。另请注意,对初始值的良好猜测总是有帮助的,但我猜你已经知道了。

以上是关于如何在python中运行非线性回归的主要内容,如果未能解决你的问题,请参考以下文章

Python和R之间的线性回归系数之间的差异

如何用Python进行线性回归以及误差分析

如何用Python进行线性回归以及误差分析

如何用Python进行线性回归以及误差分析

如何在 python 中使用 .predict() 方法进行线性回归?

有没有办法在 python 中使用数据集中的变量计数以日期作为预测变量来运行线性回归?