我有这样一个数据集:
import numpy as np
a = np.array([1.2, 2.3, 4.2])
b = np.array([1, 5, 6])
c = np.array([5.4, 6.2, 1.9])
m = np.vstack([a,b,c])
y = np.array([5.3, 0.9, 5.6])
想要拟合一个约束线性回归
y = b1a + b2b + b3*c
其中所有b总和为1且为正:b1+b2+b3=1
在R中的类似问题在这里详细说明:
https://stats.stackexchange.com/questions/21565/how-do-i-fit-a-constrained-regression-in-r-so-that-coefficients-total-1
如何在python中执行此操作?
4条答案
按热度按时间oyxsuwqo1#
EDIT:* 这两种方法非常通用,适用于中小型示例。要获得更有效的方法,请查看*chthonicdaemon的答案(使用自定义的预处理和scipy的optimize.nnls)。
使用脚本
代码
输出
评估
使用由cvxpy建模的通用QP/SOCP优化
优点:
代码
输出
kpbpu0082#
你可以通过一些数学运算和
scipy.optimize.nnls
得到一个很好的解决方案:首先我们做一下数学计算:
如果
y = b1a + b2b + b3*c且b1 + b2 + b3 = 1,则b3 = 1 - b1 - b2。
如果我们进行替换和简化,我们最终得到
y - c = b1(a - c)+ b2(b - c)
现在,我们没有任何等式约束,nnls可以直接求解:
这恢复了使用cvxpy在另一个答案中获得的相同解。
这种方法可以推广到任意维数的情况,如下所示:假设我们有一个矩阵B,它是由原始问题中的a、b、c按列排列而成的,任何额外的维数都将被添加到其中。
现在,我们可以做
uidvcgyl3#
关于sascha的scipy实现的一点意见是:请注意,使用scipy minimize时,SLSQP的试错性质可能会使您得到一个“稍微”偏离的解决方案,除非您制定了一些其他规范,即最大迭代次数(maxiter)和最大容差(ftol),如此处的scipy文档中所详细说明的。
默认值为:最大值=100和FTOL= 1 E-06。
下面是一个使用矩阵表示法的示例:首先去掉约束和边界,为简单起见,还假设截距=0,在这种情况下,任何多元回归的系数(如第4页所述here)将(精确地)为:
现在,假设最小二乘回归的目标是使残差平方和最小化,那么我们可以使用萨莎的损失函数(稍微重写了一下):
给定实际的Y和X向量,你可以把上面第一个方程中的“真”beta值代入第二个方程,得到一个更好的“基准”。把这个基准与res的.fun属性(scipy最小化的结果)进行比较。即使是很小的变化也会对得到的系数产生有意义的变化。
所以长话短说,使用类似于
在Sascha的代码里
t9aqgxwy4#
你的问题是一个线性最小二乘问题,你可以使用qpsolvers中的
solve_ls
函数,直接用二次规划求解器来求解。在我的机器上,这段代码找到了解决方案
x = array([0.7760881, 0.0, 0.2239119])
。我已经将完整的代码上传到constrained_linear_regression.py
,请随时尝试。