如何在线性回归中强制权重为非负数

数据挖掘 Python scikit-学习 线性回归
2021-09-20 20:40:00

我在 python 中使用 scikit-learn 使用标准线性回归。但是,我想强制每个特征的权重都是非负的。有什么办法可以做到吗?我正在查看文档,但找不到完成此操作的方法。

4个回答

您正在寻找的是非负最小二乘回归这是二次规划中的一个简单优化问题,您的约束是所有系数(又名权重)都应该是正数。

话虽如此,Scikit-Learn 中没有非负最小二乘的标准实现。拉取请求仍处于打开状态

但是,看起来Scipy 已经实现了相同的.

PS:我还没有尝试过 scipy 版本。我只是通过谷歌搜索找到的。

我在 Scikit Learn 上使用 Lasso 的解决方法(这绝对不是最好的做事方式,但效果很好)。Lasso 有一个参数positive,可以设置True并强制系数为正。此外,将正则化系数设置alpha为接近 0 会使 Lasso 模拟没有正则化的线性回归。这是代码:

from sklearn.linear_model import Lasso
lin = Lasso(alpha=0.0001,precompute=True,max_iter=1000,
            positive=True, random_state=9999, selection='random')
lin.fit(X,y)

从 0.24 版开始,scikit-learnLinearRegression包含一个参数positive,它就是这样做的;来自文档

正:布尔,默认=假

当设置为 时True,强制系数为正。此选项仅支持密集阵列。

0.24 版中的新功能。

有一个受约束的最小二乘法scipy.optimize.lsq_linear另一种选择是使用Python 的优化求解器这是我维护的选项之一(Gekko),其中包括系数约束。

# Constrained Multiple Linear Regression
import numpy as np
nd = 100 # number of data sets
nc = 5   # number of inputs
x = np.random.rand(nd,nc)
y = np.random.rand(nd)

from gekko import GEKKO
m = GEKKO(remote=False); m.options.IMODE=2
c  = m.Array(m.FV,nc+1)
for ci in c:
    ci.STATUS=1
    ci.LOWER=0
xd = m.Array(m.Param,nc)
for i in range(nc):
    xd[i].value = x[:,i]
yd = m.Param(y); yp = m.Var()
s =  m.sum([c[i]*xd[i] for i in range(nc)])
m.Equation(yp==s+c[-1])
m.Minimize((yd-yp)**2)
m.solve(disp=True)
a = [c[i].value[0] for i in range(nc+1)]
print('Solve time: ' + str(m.options.SOLVETIME))
print('Coefficients: ' + str(a))

它使用非线性求解器IPOPT来解决问题。对于不太大的问题,这是一个不错的选择,因为在计算可能的非线性函数的精确一阶和二阶导数时需要进行一些计算工作。APOPT对于具有 的求解器的较大问题,它可能会更快m.options.SOLVER=1