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

结合数据库更新使用scipy.optimize.minimize的异常问题咨询

黑箱优化中Scipy.minimize无法更新JSON数据库的问题

我在处理一个黑箱优化问题,由于黑箱特性,无法直接通过编程定义优化向量x,必须将等效的x存入JSON数据库后传递给黑箱。尝试读取数据库内容得到初始x,在优化迭代时更新数据库,但运行scipy.optimize.minimize时,数据库中的x1、x2完全没有变化。

已尝试的排查方案:

  • 修改数据库更新方式
  • 验证写入功能:将x2.tolist()改为[1,2]时,数据库可正常更新
  • 添加回调函数查看x及目标函数值,发现全程无变化
  • 更换Nelder-Mead、Powell等无梯度优化算法,问题依旧

黑箱仅保证连续不保证可微,排除梯度爆炸因素。现寻求可行解决办法,是否需要自定义优化函数?


相关代码片段

import numpy as np
import json
import scipy.optimize as sp

# 假设全局变量:y1_data, y2_data, file_path, some_index, bb, db_param, param1, param2已定义

# 平方差之和计算函数
def sum_ssd(y1, y2):
    ssd_y1 = np.sum((y1-y1_data)**2)
    ssd_y2 = np.sum((y2-y2_data)**2)
    sum_that = ssd_y1 + ssd_y2
    return sum_that

# 目标函数
def objective(x12):
    # 拆分优化输入为黑箱所需的x1、x2
    x1 = x12[:5]
    x2 = x12[5:]
    # 更新数据库中的黑箱输入
    json_obj[some_index]["x1"]=x1.tolist()
    json_obj[some_index]["x2"]=x2.tolist()
    with open(file_path, "w") as json_fp:
        json.dump(json_obj, json_fp, indent = 4)
    # 调用黑箱(假设db_param关联数据库内容)
    y1 = bb(db_param, param1)
    y2 = bb(db_param, param2)
    # 返回平方差之和
    out = sum_ssd(y1, y2)
    return out

# 回调函数
def callback(x):
    print(x)
    print(objective(x))

# 初始化优化初始值
with open(file_path, "r") as json_fp:
    json_obj = json.load(json_fp)
x1 = np.asarray(json_obj[some_index]["x1"])
x2 = np.asarray(json_obj[some_index]["x2"])
x012 = np.append(x1, x2)

# 执行优化
res = sp.optimize.minimize(objective, x012, method='Nelder-Mead', callback=callback, options={'disp':True})

问题分析与解决办法

核心问题

你的代码存在两个关键逻辑漏洞:

  1. 黑箱参数读取未同步:如果黑箱bb是初始化时读取一次数据库参数就复用内存值,后续数据库文件更新不会被黑箱感知,导致每次计算都用初始x,目标函数值不变,优化算法自然不会迭代更新x。
  2. 内存中json_obj复用风险:json_obj是全局变量,在优化初始化阶段读取到内存,objective函数中直接修改内存对象再写入文件,若其他进程/逻辑同时修改数据库,会导致内存与文件内容不一致。

具体修复方案

  1. 强制黑箱每次调用重新读取数据库
    修改黑箱bb的实现,让它每次被调用时都从JSON文件重新加载参数,而不是复用内存缓存:

    def bb(db_param_path, param):
        # 每次调用都重新读取最新数据库内容
        with open(db_param_path, "r") as fp:
            json_obj = json.load(fp)
        current_x1 = np.asarray(json_obj[some_index]["x1"])
        current_x2 = np.asarray(json_obj[some_index]["x2"])
        # 黑箱核心计算逻辑,使用current_x1、current_x2
        ...
    

    同时修改objective中调用黑箱的代码,传入数据库路径而非内存参数:

    y1 = bb(file_path, param1)
    y2 = bb(file_path, param2)
    
  2. 避免全局json_obj复用
    在objective函数内部每次更新数据库前,先读取最新的文件内容,防止内存与文件不一致:

    def objective(x12):
        x1 = x12[:5]
        x2 = x12[5:]
        # 先读取最新数据库内容
        with open(file_path, "r") as json_fp:
            json_obj = json.load(json_fp)
        json_obj[some_index]["x1"] = x1.tolist()
        json_obj[some_index]["x2"] = x2.tolist()
        with open(file_path, "w") as json_fp:
            json.dump(json_obj, json_fp, indent=4)
        # 调用黑箱
        y1 = bb(file_path, param1)
        y2 = bb(file_path, param2)
        return sum_ssd(y1, y2)
    
  3. 调整优化算法终止条件
    若目标函数值变化过小,Nelder-Mead等算法会提前终止。可以调小ftol(函数容忍度)参数:

    res = sp.optimize.minimize(objective, x012, method='Nelder-Mead', 
                               callback=callback, 
                               options={'disp':True, 'ftol':1e-8})
    
  4. 优化回调函数逻辑
    回调函数中无需重复调用objective(x)(minimize已自动迭代调用),避免重复写入数据库:

    def callback(x):
        print(f"当前迭代x值:{x}")
    

是否需要自定义优化函数?

目前不需要,问题根源在于黑箱与数据库的参数同步逻辑,而非优化算法本身。先修复上述同步问题,若仍无法解决,再考虑自定义优化逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:52:39