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

Scipy全局优化结合Jacobian信息的实现难题与替代方案问询

全局优化中结合Jacobian加速的解决方案

问题背景

当前处理一个全局优化问题,目标函数具备可微性,计划用PyTorch自动微分提供Jacobian信息加速局部优化。现有局部优化代码通过Scipy的minimize配合jac=True,让函数同时返回目标值和Jacobian,示例代码如下:

import numpy
import scipy.optimize
import torch


def minim(obs, f, p0):
    """Fit function f to observations "obs" starting at p0"""
    
    def fitfn(pars):
        pars = torch.tensor(pars, requires_grad=True)
        y = f(pars)
        # 最小二乘损失
        res = ((obs - y)**2).sum()
        res.backward()
        return res.data.cpu().numpy(), pars.grad.data.cpu().numpy()

    res = scipy.optimize.minimize(
        fitfn,
        p0,
        method="BFGS",
        jac=True  # 告知优化器函数返回包含Jacobian
    )
    return res

# 观测点
X = torch.arange(100)

def exfn(p):
    y = torch.sin(p[0]*X) + torch.cos(p[1]*X)
    return y

# 生成观测数据
yp = exfn(torch.tensor([0.3, 0]))

# 局部优化测试
minim(yp, exfn, numpy.array([0.34, 0.01]))

但使用Scipy全局优化器(如dual_annealing)时,无法直接复用这种返回Jacobian的函数模式:

dual_annealing(f, bounds, args=(x,y0), minimizer_kwargs={'jac':True})

minimizer_kwargs仅对内部调用的局部优化器生效,外层全局优化器本身不需要Jacobian,因此传入返回值+Jacobian的函数会报错。

解决办法

1. 适配Scipy全局优化的函数拆分

Scipy全局优化器(如dual_annealing)只要求目标函数返回标量损失值,局部优化阶段的Jacobian需求仅在内部minimize调用中处理。因此可以拆分函数:

  • 给全局优化器的函数:仅计算并返回损失值
  • 给局部优化器的函数:同时返回损失值和Jacobian

修改后的代码示例:

import numpy
import scipy.optimize
import torch

# 全局优化用的损失函数(仅返回值)
def global_loss_fn(pars, obs, f):
    pars = torch.tensor(pars)
    y = f(pars)
    return ((obs - y)**2).sum().cpu().numpy()

# 局部优化用的带Jacobian的函数
def local_fitfn(pars, obs, f):
    pars = torch.tensor(pars, requires_grad=True)
    y = f(pars)
    res = ((obs - y)**2).sum()
    res.backward()
    return res.data.cpu().numpy(), pars.grad.data.cpu().numpy()

# 全局优化+局部Jacobian加速
def global_minim(obs, f, bounds):
    res = scipy.optimize.dual_annealing(
        global_loss_fn,
        bounds=bounds,
        args=(obs, f),
        minimizer_kwargs={
            'method': 'BFGS',
            'jac': True,
            'args': (obs, f),
            'fun': local_fitfn  # 指定局部优化用带Jacobian的函数
        }
    )
    return res

# 测试
X = torch.arange(100)
def exfn(p):
    return torch.sin(p[0]*X) + torch.cos(p[1]*X)

yp = exfn(torch.tensor([0.3, 0]))
# 参数边界:比如p0∈[0,1], p1∈[-0.5,0.5]
bounds = [(0, 1), (-0.5, 0.5)]
global_minim(yp, exfn, bounds)

这样外层全局搜索只用标量损失,内部局部精炼时用带Jacobian的函数加速,完美适配Scipy的接口。

2. 替代框架选择

如果不想拆分函数,也可以选择原生支持全局优化+自动微分的框架:

  • Nevergrad:支持全局优化算法,可直接兼容PyTorch张量,自动利用梯度信息加速局部优化,无需手动处理Jacobian返回格式
  • Optuna:虽然主打超参数调优,但也支持连续参数的全局优化,可集成PyTorch自动微分实现梯度加速的局部搜索
  • PyTorch Lightning Bolts:提供部分优化工具,可结合PyTorch的自动微分能力实现全局+局部优化的结合

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:53:12