如何约束三次回归模型经过指定点?(statsmodels/sklearn实现)
带约束的三次多项式拟合实现方法
方法一:使用statsmodels的约束回归
原三次模型为:
y = β₀ + β₁x + β₂x² + β₃x³ + ε
根据约束条件 f(0)=10 和 f(8)=60,可转化为两个线性约束:
β₀ = 10β₀ + 8β₁ + 64β₂ + 512β₃ = 60
借助statsmodels的OLS类结合fit_constrained方法即可实现带约束的拟合:
import statsmodels.api as sm import random import pandas as pd # 生成可复现的测试数据 random.seed(42) df = pd.DataFrame({ 'y': [x**2 + random.gauss(0, 2) for x in range(10)], 'x': [x for x in range(10)] }) # 构造包含截距项、x、x²、x³的自变量矩阵 X = sm.add_constant(pd.DataFrame({ 'x': df['x'], 'x2': df['x']**2, 'x3': df['x']**3 })) # 定义约束条件字符串 constraints = [ 'const = 10', 'const + 8*x + 64*x2 + 512*x3 = 60' ] # 拟合带约束的模型 model = sm.OLS(df['y'], X).fit_constrained(constraints) # 生成预测值并可视化 df['pred'] = model.predict(X) df.set_index('x').plot()
方法二:重构变量后使用sklearn线性回归
通过变量替换将约束逻辑融入模型,转化为无约束回归问题:
- 由
f(0)=10,令y' = y - 10,模型简化为y' = β₁x + β₂x² + β₃x³ + ε - 由
f(8)=60代入得10 + 8β₁ + 64β₂ + 512β₃ = 60,进一步推导得β₁ = 6.25 - 8β₂ - 64β₃ - 将β₁代入y'的模型,整理得到无约束的二元线性模型:
y' - 6.25x = β₂(x² - 8x) + β₃(x³ - 64x) + ε
使用sklearn拟合该模型后,再还原原三次模型的系数:
from sklearn.linear_model import LinearRegression import random import pandas as pd random.seed(42) df = pd.DataFrame({ 'y': [x**2 + random.gauss(0, 2) for x in range(10)], 'x': [x for x in range(10)] }) # 构造转换后的因变量和自变量 df['y_transform'] = df['y'] - 10 - 6.25 * df['x'] df['x2_transform'] = df['x']**2 - 8 * df['x'] df['x3_transform'] = df['x']**3 - 64 * df['x'] # 拟合无约束线性模型 X = df[['x2_transform', 'x3_transform']] y = df['y_transform'] lr = LinearRegression(fit_intercept=False) lr.fit(X, y) # 还原原三次模型的系数 beta2 = lr.coef_[0] beta3 = lr.coef_[1] beta1 = 6.25 - 8*beta2 - 64*beta3 beta0 = 10 # 定义预测函数并生成预测值 def predict_f(x): return beta0 + beta1*x + beta2*x**2 + beta3*x**3 df['pred'] = df['x'].apply(predict_f) df.set_index('x').plot()
两种方法均能保证拟合的模型严格满足f(0)=10和f(8)=60的约束,同时尽可能贴合原始数据。
内容的提问来源于stack exchange,提问作者ℕʘʘḆḽḘ
相关产品推荐
相关产品推荐

