You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyomo调优SARIMAX超参数时约束不满足的问题求助

SARIMAX超参数调优Pyomo约束失效问题

我正在开发一款SARIMAX(带外生回归项的季节性自回归积分滑动平均)模型超参数调优求解器,核心目标是确保模型训练集与测试集R²均≥0.8,同时最大化两者的R²之和。目前使用Pyomo构建优化模型,尝试了glpk、ipopt、cbc等求解器,求解器均返回成功,但最终得到的参数始终违反R²≥0.8的约束条件。

已尝试的排查方向:

  • 重新评估超参数的取值边界
  • 检查目标函数的计算公式
  • 调整约束条件的实现方式

期望得到满足训练集与测试集精度阈值的稳健SARIMAX模型。

复现代码

import numpy as np
import pandas as pd
from pyomo.environ import *
from statsmodels.tsa.statespace.sarimax import SARIMAX
from sklearn.metrics import r2_score

# Step 1: Create a synthetic time series dataset
np.random.seed(42)
n = 120  # Length of time series data

# Generate a seasonal pattern with trend and noise
time = np.arange(n)
seasonal_pattern = 10 * np.sin(2 * np.pi * time / 12)
trend = 0.1 * time
noise = np.random.normal(0, 1, n)
data = 20 + trend + seasonal_pattern + noise

# Create a DataFrame
df = pd.DataFrame(data, columns=["value"])
df['date'] = pd.date_range(start="2010-01-01", periods=n, freq="D")
df.set_index("date", inplace=True)

# Step 2: Split into train and test sets
train_size = int(len(df) * 0.8)
train, test = df.iloc[:train_size], df.iloc[train_size:]

# Step 3: Define the Pyomo model
model = ConcreteModel()

# Define integer variables for SARIMA parameters
model.p = Var(within=NonNegativeIntegers, bounds=(0, 10), initialize=1)
model.d = Var(within=NonNegativeIntegers, bounds=(0, 10), initialize=1)
model.q = Var(within=NonNegativeIntegers, bounds=(0, 10), initialize=1)
model.P = Var(within=NonNegativeIntegers, bounds=(0, 10), initialize=1)
model.D = Var(within=NonNegativeIntegers, bounds=(0, 10), initialize=1)
model.Q = Var(within=NonNegativeIntegers, bounds=(0, 10), initialize=1)
model.seasonality = Var(within=NonNegativeIntegers, bounds=(2, 12), initialize=2)
print("Displaying P value ",model.p.display())

# Define parameters to store R² scores
model.train_r2 = Var(within=NonNegativeReals)
model.test_r2 = Var(within=NonNegativeReals)
model.test_train_sum = Var(within=NonNegativeReals)


# Step 4: Define a function to fit SARIMAX and calculate R² values
def sarima_r2_model(p, d, q, P, D, Q, seasonality):
    try:
        # Fit SARIMAX model with the given parameters
        model = SARIMAX(
            train['value'],
            order=(p, d, q),
            seasonal_order=(P, D, Q, seasonality),
            enforce_stationarity=False,
            enforce_invertibility=False
        )
        results = model.fit(disp=False)

        # Calculate R² on both train and test sets
        train_pred = results.predict(start=train.index[0], end=train.index[-1])
        test_pred = results.predict(start=test.index[0], end=test.index[-1])
        train_r2_value = r2_score(train['value'], train_pred)
        test_r2_value = r2_score(test['value'], test_pred)
        return train_r2_value, test_r2_value
    except:
        print("========== If model fitting fails, return low R² values")
        return -10, -10

# Define objective to maximize sum of R² scores
def objective_rule(m):
    p = int(m.p.value)
    d = int(m.d.value)
    q = int(m.q.value)
    P = int(m.P.value)
    D = int(m.D.value)
    Q = int(m.Q.value)
    seasonality = int(m.seasonality.value)
    m.train_r2.value, m.test_r2.value = sarima_r2_model(p, d, q, P, D, Q, seasonality)
    
    # Store R² values in model variables for constraints

    print("train_r2_value ==========",m.train_r2.value)
    print("test_r2_value ==========",m.test_r2.value)
    model.test_train_sum = m.train_r2.value + m.test_r2.value 
    return model.test_train_sum


# Set objective function
model.objective = Objective(rule=objective_rule, sense=maximize)



# Step 5: Add constraints for minimum R² threshold
r2_threshold = 0.8
model.train_r2_constraint = Constraint(expr=model.train_r2 >= r2_threshold)
model.test_r2_constraint = Constraint(expr=model.test_r2>=r2_threshold)


# Step 6: Solve the optimization problem with a suitable solver
solver = SolverFactory('cbc',executable="/usr/bin/cbc")  # Choose solver like 'cbc' or 'glpk' if available


results = solver.solve(model, tee=True)
print(results.write())
print(results.solver.status)
print("optimal",results.solver.termination_condition)

print("# will show you the evaluation of the OBJ function")
model.objective.display()  
print(model.objective.expr()) 

# Step 7: Retrieve the best parameters
best_params = {
    'p': int(model.p.value),
    'd': int(model.d.value),
    'q': int(model.q.value),
    'P': int(model.P.value),
    'D': int(model.D.value),
    'Q': int(model.Q.value),
    'seasonality': int(model.seasonality.value)
}
print("Optimized parameters:", best_params)

# Step 8: Train the final model with optimized parameters
best_model = SARIMAX(
    train['value'],
    order=(best_params['p'], best_params['d'], best_params['q']),
    seasonal_order=(best_params['P'], best_params['D'], best_params['Q'], best_params['seasonality']),
    enforce_stationarity=False,
    enforce_invertibility=False
)
best_results = best_model.fit(disp=False)

# Step 9: Final evaluation on train and test sets
train_pred = best_results.predict(start=train.index[0], end=train.index[-1])
test_pred = best_results.predict(start=test.index[0], end=test.index[-1])

print("Final Train R²:", r2_score(train['value'], train_pred))
print("Final Test R²:", r2_score(test['value'], test_pred))

核心问题

求解器返回成功,但最终参数对应的训练集/测试集R²无法达到预设的0.8阈值,约束条件未被实际生效。


内容的提问来源于stack exchange,提问作者Chrs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 22:15:54