结合数据库更新使用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})
问题分析与解决办法
核心问题
你的代码存在两个关键逻辑漏洞:
- 黑箱参数读取未同步:如果黑箱
bb是初始化时读取一次数据库参数就复用内存值,后续数据库文件更新不会被黑箱感知,导致每次计算都用初始x,目标函数值不变,优化算法自然不会迭代更新x。 - 内存中
json_obj复用风险:json_obj是全局变量,在优化初始化阶段读取到内存,objective函数中直接修改内存对象再写入文件,若其他进程/逻辑同时修改数据库,会导致内存与文件内容不一致。
具体修复方案
强制黑箱每次调用重新读取数据库
修改黑箱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)避免全局
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)调整优化算法终止条件
若目标函数值变化过小,Nelder-Mead等算法会提前终止。可以调小ftol(函数容忍度)参数:res = sp.optimize.minimize(objective, x012, method='Nelder-Mead', callback=callback, options={'disp':True, 'ftol':1e-8})优化回调函数逻辑
回调函数中无需重复调用objective(x)(minimize已自动迭代调用),避免重复写入数据库:def callback(x): print(f"当前迭代x值:{x}")
是否需要自定义优化函数?
目前不需要,问题根源在于黑箱与数据库的参数同步逻辑,而非优化算法本身。先修复上述同步问题,若仍无法解决,再考虑自定义优化逻辑。
内容的提问来源于stack exchange,提问作者kriegersan
相关产品推荐
相关产品推荐

