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

如何在不重复计算目标函数的情况下跟踪differential_evolution的优化进度

如何在不重复计算目标函数的情况下跟踪differential_evolution的优化进度

你遇到的这个问题真的很戳痛点——scipy的differential_evolution回调设计确实有点“抠门”,只给当前最优解xk,却不附带已经算过的目标函数值,逼得你不得不重复调用opt(xk),要是目标函数计算成本高,那速度下降可不是一星半点。

其实我们可以换个思路:让目标函数自己“记住”最近计算出的最优结果,这样回调函数直接读取这个“记忆”就行,完全不用重复计算。下面是具体的实现方案,直接替换你的代码即可:

import numpy as np
from scipy.optimize import differential_evolution, LinearConstraint

# 先假设你的目标函数opt是这样的(示例)
def opt(xk):
    # 这里是你的目标函数逻辑,比如简单的求和
    return sum(xk)

def de_optimise():
    # 创建一个共享缓存,用来存储当前最优的目标值和对应的解
    progress_cache = {'best_obj': float('inf'), 'best_xk': None}

    # 包装原始目标函数,添加缓存逻辑
    def cached_opt(xk):
        obj_val = opt(xk)
        # 只有当当前结果比缓存的最优值更好时,才更新缓存
        if obj_val < progress_cache['best_obj']:
            progress_cache['best_obj'] = obj_val
            progress_cache['best_xk'] = xk.copy()
        return obj_val

    def build_show_de(progress_f):
        def fn(xk, convergence):
            # 直接从缓存拿已经计算好的目标值,不用再跑opt(xk)
            current_best_obj = progress_cache['best_obj']
            if current_best_obj < progress_f[-1]:
                print("DE", [round(x, 2) for x in xk], current_best_obj)
                progress_f.append(current_best_obj)
            # 不需要提前终止的话返回False/None即可
            return False
        return fn

    bounds = [(0,1)]*3
    # 定义线性约束
    A = [[-1, 1, 0], [0, -1, 1]]
    lb = [0.3, 0.4]
    ub = [np.inf, np.inf]
    constraints = LinearConstraint(A, lb, ub)

    # 初始值设为无穷大,确保第一个有效最优值能被记录
    progress_f = [float('inf')]
    c = build_show_de(progress_f)

    print("Optimizing using differential evolution")
    res = differential_evolution(
        cached_opt,  # 使用带缓存的目标函数替代原始opt
        bounds=bounds,
        constraints=constraints,
        callback=c,
        disp=True
    )

    # 打印时去掉初始的inf值
    print(f"external way of keeping track of MINF: {progress_f[1:]}")

de_optimise()

方案说明

  1. 缓存包装函数:我们给原始目标函数opt套了一层cached_opt,每次计算目标值后,会检查是否是当前最优结果,如果是就更新progress_cache。这样算法每次算出新的最优解时,缓存里已经存好了对应的目标值。
  2. 回调直接读缓存:回调函数fn现在不需要再调用opt(xk),直接从progress_cache里取结果就行,彻底避免了重复计算。
  3. 初始值处理:把progress_f的初始值设为无穷大,确保第一个有效的最优值肯定能被加入跟踪列表。

如果你的问题是最大化目标函数,只需要把缓存更新的条件改成if obj_val > progress_cache['best_obj'],同时progress_f的初始值设为负无穷即可。

这个方法几乎没有额外性能开销,只是在目标函数计算后多了一次简单的比较和赋值,完全不会拖慢优化进程。

备注:内容来源于stack exchange,提问作者Simd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 10:28:10