使用 sklearn 线性回归,如何将计算出的回归系数约束为大于 0?
Posted
技术标签:
【中文标题】使用 sklearn 线性回归,如何将计算出的回归系数约束为大于 0?【英文标题】:Using sklearn linear regression, how can I constrain the calculated regression coefficients to be greater than 0? 【发布时间】:2018-07-27 14:40:52 【问题描述】:我在这里使用 sklearn 的参考http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html,但没有限制回归系数的选项。
有人知道python中的另一个包来执行多变量线性回归并将回归系数限制为大于0吗?
这是我目前的代码。
'''data:
date A B C
10/30/2015 0.063363323 -0.005218807 0.079777558
11/30/2015 -0.013171244 -0.008727599 0.010352028
12/31/2015 -0.017551268 8.09E-05 -0.020491923
1/29/2016 -0.042606469 0.052272139 -0.080362246
2/29/2016 -0.015224562 0.031250961 0.029988488
3/31/2016 0.058291876 -0.000238614 0.056727336
4/29/2016 0.000505675 -0.005325338 0.02854057
5/31/2016 0.012766515 0.008548162 -0.001631845
6/30/2016 -0.038981203 0.064236963 0.00570145
7/29/2016 0.033715429 0.024269606 0.02703294
8/31/2016 -0.002083837 -0.009439625 0.004129397
9/30/2016 -0.009825674 -0.01737909 -0.019251885
11/30/2016 0.0084733 -0.11668582 0.031928726
12/30/2016 0.017084282 -0.005553088 0.029372131
1/31/2017 0.014263947 0.004036504 0.00187079
2/28/2017 0.037375566 0.016081105 0.039331615
3/31/2017 -0.002494984 -0.005942793 -0.002097504
4/28/2017 -0.005054922 0.015685226 0.008243977
5/31/2017 0.002285393 0.020771375 0.002697755
6/30/2017 0.002841457 0.004886117 0.019202011
7/31/2017 0.014866638 -0.006900926 0.010126577
8/31/2017 -0.016647997 0.035687133 -0.008709075
9/29/2017 0.019523651 -0.022154361 0.020468398
10/31/2017 0.019407629 -0.000705663 0.016574416
11/30/2017 0.027486425 0.008008173 0.033427299
12/29/2017 0.007861222 0.018095096 0.017908809
1/31/2018 0.058702838 -0.032765285 0.05
'''
reg = linear_model.LinearRegression(fit_intercept=False)
reg.fit(df[['B', 'C']], df['A'])
print(reg.coef_)
# [ 0.67761268 -0.08845756]
下面的工作代码
from scipy.optimize import lsq_linear
lb = 0
ub = np.Inf
res = lsq_linear(df[['B', 'C']],
df['A'],
bounds=(lb, ub))
print(res.x)
【问题讨论】:
您的一些 y 值,例如df['A'], 是负数。也许尝试标准化您的数据,例如与 sklearn 的 MinMaxScaler? 【参考方案1】:sklearn 只是包装了 scipy 的 lstsq,它不支持这一点。
您可以轻松修改 sklearn 的 code:
if sp.issparse(X):
if y.ndim < 2:
out = sparse_lsqr(X, y)
self.coef_ = out[0]
self._residues = out[3]
else:
# sparse_lstsq cannot handle y with shape (M, K)
outs = Parallel(n_jobs=n_jobs_)(
delayed(sparse_lsqr)(X, y[:, j].ravel())
for j in range(y.shape[1]))
self.coef_ = np.vstack(out[0] for out in outs)
self._residues = np.vstack(out[3] for out in outs)
else:
self.coef_, self._residues, self.rank_, self.singular_ = \
linalg.lstsq(X, y)
self.coef_ = self.coef_.T
只需将 lstsq / lsqr 替换为 scipy 的 nnls(密集!!!)或手动设置边界的 lsq_linear(对于大规模:使用方法 lbfgs 的 optimize.minimize 是另一个候选者,尽管您需要准备渐变并且至少有两种不同的常用方法:例如使用预先计算的:A.T*A
失去稀疏性)。
备注:这些方法正在最小化不同的函数(范数与平方范数;0.5 因子与 1.0 因子)。就找到的向量而言,这不会改变结果,但目标当然看起来不同,您应该注意这一点(如果需要)。
【讨论】:
感谢帮助,我把上面写的代码贴出来了。【参考方案2】:对于在 2021 年获得此答案的人,您现在可以在调用 LinearRegression
时设置 positive = True
,以便将系数限制为 > 0。
【讨论】:
以上是关于使用 sklearn 线性回归,如何将计算出的回归系数约束为大于 0?的主要内容,如果未能解决你的问题,请参考以下文章
如何从sklearn LinearRegression中导出线性回归公式
如何使用 Matplotlib、pandas 和 sklearn 创建线性回归图?