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

基于Hyperopt与Gekko的超参数搜索空间定义问题求助

超参数优化搜索空间定义问题:Hyperopt+Gekko得到全0解的修复

已知优化问题的最优解为[0,4050,2100,2100,1200,0,0,450,150],但使用Hyperopt结合Gekko进行超参数优化时,两种搜索空间定义方式均得到全0解,以下是问题分析和修复方案:

原代码问题分析

1. 搜索空间定义错误

  • 第一种方式:hp.choice('x1', IV[0])是从IV[0]的27个0/1元素中选单个值,但每个x1应该是长度为27的0-1向量(对应每个电容型号的选择),这种定义完全不符合需求,Hyperopt每次只传单个0或1,而非向量。
  • 第二种方式:hp.quniform('x1',0,1,Nc)参数错误,quniform的步长参数q是间隔值,0到1之间步长27只会返回0,无法覆盖有效候选值。

2. 目标函数逻辑错误

在objective函数中,先创建Gekko的二维变量数组x,随后直接将x1-x9赋值为params的数值,完全覆盖了Gekko的优化变量,导致Gekko实际求解的是固定参数下的问题,而非利用Hyperopt搜索最优参数组合。

修复方案

核心思路

每个节点最多选择一个电容型号(或不选),因此可以将每个节点的选择简化为整数索引:0代表不安装电容,127对应选择`Qc`中第026个型号。Hyperopt搜索每个节点的索引值,再在目标函数中转换为对应的电容容量,结合Gekko处理约束并计算目标值。

修正后的代码

from gekko import GEKKO
import numpy as np
from hyperopt import fmin, tpe, hp
from hyperopt import STATUS_OK, STATUS_FAIL

# 原始数据
P = [13105.11598923, 11261.13968067, 10103.92043191, 8199.51950018,
     6411.29606705, 4753.51971915, 3897.77624628, 2659.30922847,
     1639.99999999]
Q = [0., 4434.40470446, 3808.26080152, 3262.6022579, 1256.88696212, 0.,
     0., 352.26399841, 200.00000001]
V = [22836.72949, 22709.57526, 22158.26541, 21804.24667, 21094.79492,
     20864.73522, 20445.8738, 19749.82457, 19262.43063]
R = [1.2330e-04, 1.4000e-05, 7.4630e-04, 6.9840e-04, 1.9831e-03,
     9.0530e-04, 2.0552e-03, 4.7953e-03, 5.3434e-03]
Kc = [0.5, 0.35, 0.253, 0.22, 0.276, 0.183, 0.228, 0.17, 0.207, 0.201,
      0.193, 0.187, 0.211, 0.176, 0.179, 0.170, 0.189, 0.187, 0.183, 0.180,
      0.195, 0.174, 0.188, 0.170, 0.183, 0.182, 0.179]
Qc = [150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, 1650, 1800,
      1950, 2100, 2250, 2400, 2550, 2700, 2850, 3000, 3150, 3300, 3450, 3600,
      3750, 3900, 4050]
Ke = 168
T = 24 * 365
N = len(Q)
Nc = len(Qc)

# 定义搜索空间:每个节点选择0(不装)或1~27(对应Qc的索引+1)
space = {
    f'x{i+1}': hp.choice(f'x{i+1}', list(range(Nc + 1)))
    for i in range(N)
}

def objective(params):
    m = GEKKO(remote=False)
    # 每个节点的电容选择:0代表不装,否则取对应Qc的值
    qc_selected = [Qc[idx-1] if idx !=0 else 0 for idx in params.values()]
    
    # 约束:总电容容量不超过总Q的和
    total_qc = m.sum(qc_selected)
    m.Equation(total_qc <= m.sum(Q))
    
    # 目标函数计算
    obj = 0
    for i in range(N):
        q_i = Q[i] - qc_selected[i]
        loss_term = R[i] * T * Ke * (1 / V[i]**2) * (P[i]**2 + q_i**2)
        cost_term = Kc[params[f'x{i+1}']-1] * qc_selected[i] if params[f'x{i+1}'] !=0 else 0
        obj += loss_term + cost_term
    
    m.Minimize(obj)
    m.solver_options = [
        'minlp_gap_tol 1e-5',
        'minlp_maximum_iterations 10000',
        'minlp_max_iter_with_int_sol 2000'
    ]
    m.options.SOLVER = 1
    try:
        m.solve(disp=False, debug=False)
        obj_val = m.options.objfcnval
        status = STATUS_OK
    except Exception as e:
        obj_val = np.inf
        status = STATUS_FAIL
    m.cleanup()
    
    return {'loss': obj_val, 'status': status, 'qc_selected': qc_selected}

# 运行Hyperopt搜索
best = fmin(objective, space, algo=tpe.suggest, max_evals=100)
sol = objective(best)

# 转换最优解为对应Qc值
best_qc = []
for i in range(N):
    idx = best[f'x{i+1}']
    best_qc.append(Qc[idx-1] if idx !=0 else 0)

print(f"解状态: {sol['status']}")
print(f"目标函数值: {sol['loss']:.2f}")
print(f"最优电容配置: {best_qc}")

关键修正点

  1. 搜索空间:每个节点的搜索范围改为027的整数,0对应不装电容,127对应Qc的具体型号索引。
  2. 目标函数逻辑:不再覆盖Gekko变量,而是将Hyperopt传入的索引转换为实际电容容量,结合Gekko处理约束并计算目标值。
  3. 约束简化:直接利用选择的电容容量总和进行约束,避免复杂的二维0-1变量数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:18:18