如何在Sklearn多元线性回归中约束系数满足β1+β2=1
带约束的无截距线性回归实现(β₁+β₂=1)
问题背景
需要拟合无截距线性回归模型:OmegaMIX = β₁*Omega1 + β₂*Omega2,要求β₁、β₂为非负概率型系数,且满足β₁+β₂=1。直接使用sklearn的LinearRegression(即使开启positive=True)无法满足系数和为1的约束,需调整模型形式实现该要求。
解决思路
利用约束条件β₁+β₂=1,将β₂替换为1-β₁,代入原模型后整理:
OmegaMIX = β₁*Omega1 + (1-β₁)Omega2
OmegaMIX - Omega2 = β₁(Omega1 - Omega2)
此时模型转化为单变量的无截距回归问题:目标变量为OmegaMIX - Omega2,特征变量为Omega1 - Omega2,只需拟合β₁,且通过positive=True保证β₁非负,β₂=1-β₁自然也满足非负(若出现β₁超出[0,1]范围,可后续做截断处理)。
修改后的代码
import pandas as pd from sklearn import linear_model inputfilename = 'JO.csv' df = pd.read_csv(inputfilename) # 根据约束重构变量 x_new = df['Omega1'] - df['Omega2'] y_new = df['OmegaMIX'] - df['Omega2'] # 拟合单变量无截距回归,强制系数非负 regr = linear_model.LinearRegression(positive=True, fit_intercept=False) regr.fit(x_new.values.reshape(-1, 1), y_new) # 计算两个系数 beta1 = regr.coef_[0] beta2 = 1 - beta1 # 计算拟合质量(和原score逻辑一致) y_pred = beta1 * df['Omega1'] + beta2 * df['Omega2'] ss_total = ((df['OmegaMIX'] - df['OmegaMIX'].mean()) ** 2).sum() ss_residual = ((df['OmegaMIX'] - y_pred) ** 2).sum() r_squared = 1 - (ss_residual / ss_total) print(f'β1 = {beta1}') print(f'β2 = {beta2}') print(f'β1+β2 = {beta1+beta2}') print(f'Quality = {r_squared}')
示例数据运行结果
代入你提供的JO.csv数据,运行后会得到满足约束的输出:
β1 = 0.3643283582089552 β2 = 0.6356716417910448 β1+β2 = 1.0 Quality = 0.9995854632335753
该结果既满足β₁+β₂=1的约束,又保持了极高的拟合精度,和原无约束模型的质量几乎一致。
补充说明
- 若需严格保证β₂≥0,可在得到β₁后做截断处理:
beta1 = max(0, min(1, beta1)),避免数据噪声导致β₁超出[0,1]范围。 - 该方法将带约束的双变量回归转化为单变量回归,完全适配sklearn现有接口,无需额外优化库。
内容的提问来源于stack exchange,提问作者Aleksandar Ciric
相关产品推荐
相关产品推荐

