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

多进程下使用differential_evolution无法更新类属性,如何获取最后迭代参数?

解决scipy differential_evolution多进程下类属性无法更新的问题

问题根源

启用workers=10多进程时,每个worker进程会复制一份你的Model类实例。子进程内对p1、p2的修改只会作用于当前子进程的副本,完全不会同步回主进程的实例,这就是你调用post()时pp为空的原因。

可行解决方案

方案1:利用callback回调函数(推荐)

differential_evolution的callback参数是在主进程中执行的(即使开启多进程),可以通过它捕获每次迭代的最优参数,直接更新主进程的Model实例属性。

示例代码:

from scipy.optimize import differential_evolution
import numpy as np

class Model:
    def __init__(self):
        self.p1 = None
        self.p2 = None
        self.pp = []
    
    def objective(self, x):
        # 你的目标函数逻辑,示例为简单误差计算
        return (x[0] - self.p1)**2 + (x[1] - self.p2)**2 if self.p1 is not None else x[0]**2 + x[1]**2
    
    def post(self):
        print("pp:", self.pp)
        # 这里可以用最后一次的p1、p2做后续计算

# 定义回调函数,在主进程执行
def update_model_callback(x, convergence):
    # x是当前迭代的最优参数数组
    model.p1 = x[0]
    model.p2 = x[1]
    model.pp.append((x[0], x[1]))
    # 返回False表示继续优化,返回True会终止优化
    return False

if __name__ == "__main__":
    model = Model()
    # 定义参数边界
    bounds = [(-5, 5), (-5, 5)]
    # 启动优化,指定callback
    result = differential_evolution(model.objective, bounds, workers=10, callback=update_model_callback)
    # 优化结束后调用post
    model.post()
    # 最后一次迭代的p1、p2也可以直接从result.x获取
    print("最后一次迭代参数:", result.x[0], result.x[1])

方案2:使用多进程共享变量

如果需要在子进程中也能同步访问参数,可以用multiprocessing.Manager创建共享字典,让所有进程共享同一份参数存储:

from scipy.optimize import differential_evolution
import numpy as np
from multiprocessing import Manager

class Model:
    def __init__(self, shared_params):
        self.shared_params = shared_params
        self.pp = []
    
    def objective(self, x):
        # 从共享字典读取参数
        p1 = self.shared_params.get('p1', 0)
        p2 = self.shared_params.get('p2', 0)
        # 计算目标值
        res = (x[0] - p1)**2 + (x[1] - p2)**2
        # 更新共享字典
        self.shared_params['p1'] = x[0]
        self.shared_params['p2'] = x[1]
        return res
    
    def post(self):
        # 从共享字典获取最终参数
        final_p1 = self.shared_params['p1']
        final_p2 = self.shared_params['p2']
        self.pp.append((final_p1, final_p2))
        print("pp:", self.pp)

if __name__ == "__main__":
    with Manager() as manager:
        shared_params = manager.dict()
        model = Model(shared_params)
        bounds = [(-5, 5), (-5, 5)]
        result = differential_evolution(model.objective, bounds, workers=10)
        model.post()

关键注意点

  • 不要在目标函数里直接修改Model的实例属性,因为目标函数运行在子进程,修改的是副本,主进程无法感知。
  • 优先选择callback方案,它更贴合differential_evolution的设计,不需要额外处理多进程共享的复杂问题,且能直接拿到每次迭代的最优解,完美匹配你“每次迭代后更新属性”的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:32:36