Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的约束回归_Python_Regression - Fatal编程技术网

Python中的约束回归

Python中的约束回归,python,regression,Python,Regression,我有一个简单的回归模型: y = a + b * x + c * z + error 对参数具有约束: c = b - 1 在SO(like)上也有类似的问题。但是,约束的类型是lb,这就是使用GLM可以实现的方式: import statsmodels import statsmodels.api as sm import numpy as np # Set the link function to identity statsmodels.genmod.families.links.

我有一个简单的回归模型:

 y = a + b * x + c * z + error
对参数具有约束:

c = b - 1

在SO(like)上也有类似的问题。但是,约束的类型是
lb,这就是使用GLM可以实现的方式:

import statsmodels
import statsmodels.api as sm
import numpy as np

# Set the link function to identity
statsmodels.genmod.families.links.identity()

OLS_from_GLM = sm.GLM(y, sm.add_constant(np.column_stack(x, z)))

 '''Setting the restrictions on parameters in the form of (R, q), where R 
 and q are constraints' matrix and constraints' values, respectively. As
 for the restriction in the aforementioned regression model, i.e., 
 c = b - 1 or b - c = 1, R = [0, 1, -1] and q = 1.'''

res_OLS_from_GLM = OLS_from_GLM.fit_constrained(([0, 1.0, -1.0], 1))

print(res_OLS_from_GLM.summary())

Python中有一些约束优化包,如CVX、CASADI、GEKKO、Pyomo和其他可以解决这个问题的包。我为线性、非线性和混合整数优化问题开发了微分或代数约束

将numpy导入为np
从gekko进口gekko
#资料
x=np.rand.rand(10)
y=np.rand.rand(10)
z=np.rand.rand(10)
#约束回归的Gekko算法
m=GEKKO(远程=假);m、 选项。IMODE=2
a、 b,c=m.Array(m.FV,3)
a、 状态=1;b、 状态=1;c、 状态=1
x=m.Param(x);z=m.Param(z)
y=m.Var();ym=m.Param(y)
m、 方程(y==a+b*x+c*z)
m、 方程(c==b-1)
m、 最小化((ym-y)**2)
m、 选项。解算器=1
m、 求解(disp=True)
打印(a.值[0],b.值[0],c.值[0])
这提供了在运行时可能不同的解决方案,因为它对数据使用随机值

-0.021514129645 0.45830726553 -0.54169273447
约束
c=b-1
满足
-0.54169273447=0.45830726553-1
。以下是与其他无约束条件下的比较:

将numpy导入为np
从scipy.stats导入回归
将statsmodels.api作为sm导入
将matplotlib.pyplot作为plt导入
从gekko进口gekko
#资料
x=np.数组([4,5,2,3,-1,1,6,7])
y=np.数组([0.3,0.8,-0.05,0.1,-0.8,-0.5,0.5,0.65])
#计算R^2
def rsq(y1,y2):
yresid=y1-y2
SSresid=np.和(yresid**2)
SStotal=len(y1)*净现值(y1)
r2=1-SSresid/SStotal
返回r2
#方法1:scipy回归分析
斜率,截距,r,p_值,标准误差=线性回归(x,y)
a=[斜率,截距]
打印('R^2线性回归='+str(R**2))
#方法2:numpy多边形拟合(1=线性)
a=np.多边形拟合(x,y,1);印刷品(a)
yfit=np.polyval(a,x)
打印('R^2 polyfit='+str(rsq(y,yfit)))
#方法3:numpy-linalg溶液
#y=xa
#X^T y=X^T X a
X=np.vstack((X,np.one(len(X))).T
#矩阵运算
XX=np.点(X.T,X)
XTy=np.dot(X.T,y)
a=np.linalg.solve(XX,XTy)
#与lstsq相同的解决方案
a=np.linalg.lstsq(X,y,rcond=None)[0]
yfit=a[0]*x+a[1];印刷品(a)
打印('R^2矩阵='+str(rsq(y,yfit)))
#方法4:statsmodels普通最小二乘法
X=sm.add_常量(X,prepend=False)
model=sm.OLS(y,X).fit()
yfit=模型预测(X)
a=model.params
打印(model.summary())
#方法5:Gekko用于约束回归
m=GEKKO(远程=假);m、 选项。IMODE=2
c=m.Array(m.FV,2);c[0]。状态=1;c[1]。状态=1
c[1]。下限=-0.5
xd=m.Param(x);yd=m.Param(y);yp=m.Var()
m、 方程(yp==c[0]*xd+c[1])
m、 最小化((yd yp)**2)
m、 求解(disp=False)
c=[c[0]。值[0],c[1]。值[1]]
印刷品(c)
#绘图数据和回归线
plt.plot(x,y,'ko',label='data')
xp=np.linspace(-2,8100)
斜率=str(np.圆形(a[0],2))
截距=str(np.round(a[1],2))
方程n='LstSQ:y='+斜率+'x'+截距
plt.plot(xp,a[0]*xp+a[1],'r-',label=eqn)
斜率=str(np.圆形(c[0],2))
截距=str(np.圆形(c[1],2))
等式n='约束:y='+斜率+'x'+截距
plt.plot(xp,c[0]*xp+c[1],'b--',label=eqn)
plt.grid()
plt.legend()
plt.show()

代数消除b或c,进行回归,如果计算复杂到justify@f5r5e5d代数消除b或c将导致另一个约束模型。更具体地说,可以将原始回归方程改写为
y=a+b*(x+z)-z+error
,这相当于
y=a+b*w-d*z+error,s.t.d=1
(其中
w
,新的回归器是
x+z
)。此外,对原始问题的这种重新表述存在共线性。只是一个想法:看看模块。@Javad您可以将z移动到左侧,y-z~a+b(x+z)+错误。statsmodels对某些模型有
fit_constrated
,但可能不是OLS。@user333700这确实是个好主意!它将原始约束模型转换为一个(无约束)OLS,参数b(以及随后的c)可以完全识别。然而,这种重新表述可能不适用于更复杂类型的约束线性模型。对
links.identity()
的调用没有任何作用。选择链接必须通过
GLM
中的参数。但是,标识是Gaussian的默认链接,不需要指定。@user333700,来自
statsmodels.genmod.families.links
docstring:定义要与GLM和GEE族一起使用的链接函数。因此,似乎可以通过该语句设置link函数。通过GLM调用中的参数设置它可能是一种可能性,但我找不到任何关于它的信息。此外,正如您所提到的,标识是链接函数的默认值。是的,它创建了一个链接实例,但要在模型中使用,它必须作为参数提供给模型。像这样的一条语句只有在改变某些全局变量时才会产生效果。但是,statsmodels不使用全局变量,因为如果某些地方更改了这些全局变量,则很容易得到意外的结果。@user333700感谢您的澄清。因此,总而言之,使用默认形式的GLM(高斯误差和身份链接函数)作为OLS的替代方案就足够了,还可以在参数上定义线性约束。但是,如果想使用其他族(如Gamma)和链接函数(如逆幂),可以这样做:
link\u func=statsmodels.genmod.families.links.inverse\u power
然后
OLS\u from\u GLM=sm.GLM(y,X,family=sm.families.Gamma(link=link\u func))