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

使用SciML优化Lotka-Volterra模型时,优化函数非标量输出报错如何解决?

问题解决:Optimization.jl报错"Output should be scalar; gradients are not defined for output"

错误原因

你的loss函数返回了元组(损失值, sol),但AutoZygote自动微分工具要求损失函数的输出仅为标量损失值——它会尝试对整个返回值求导,而sol是数组类型,无法计算其梯度,因此触发报错。

解决方案

推荐两种可行的修正方式,根据你的需求选择:

方式一:Loss仅返回标量,回调中重新求解sol(逻辑最稳妥)

将loss函数简化为只返回标量损失,在回调函数中通过当前参数重新求解ODE得到sol用于绘图。虽然会多一次ODE求解,但逻辑清晰,避免AD冲突。

修改后的关键代码:

# 简化loss函数,仅返回标量损失
function loss(p)
    sol = solve(prob, Tsit5(), p=p, saveat = tsteps)
    return sum(abs2, sol .- 1)
end

# 调整回调函数,自行求解sol
function callback(p, l)
    sol = solve(prob, Tsit5(), p=p, saveat = tsteps)
    push!(parameters, p.u)
    display(l)
    plt = plot(sol, ylim = (0, 6))
    display(plt)
    return l <= 0.0135
end

# 后续Optimization定义保持不变,注意回调参数不再有第三个值
adtype = Optimization.AutoZygote()
optf = Optimization.OptimizationFunction((x, p) -> loss(x), adtype)
optprob = Optimization.OptimizationProblem(optf, p)
result_ode = Optimization.solve(optprob, PolyOpt(), callback = callback, maxiters = 600)

方式二:用Zygote.@ignore忽略sol的求导(效率更高)

如果不想重复求解ODE,可以用Zygote.@ignore标记sol,让自动微分工具跳过对它的梯度计算,这样loss函数可以保留返回元组,回调也无需修改。

修改后的关键代码:

# 修改loss函数,用@ignore忽略sol的求导
function loss(p)
    sol = solve(prob, Tsit5(), p=p, saveat = tsteps)
    loss_val = sum(abs2, sol .- 1)
    return loss_val, Zygote.@ignore(sol)
end

# 回调函数保持原代码不变
function callback(p, l, pred)
    push!(parameters, p.u)
    display(l)
    plt = plot(pred, ylim = (0, 6))
    display(plt)
    return l <= 0.0135
end

# 后续代码保持不变
adtype = Optimization.AutoZygote()
optf = Optimization.OptimizationFunction((x, p) -> loss(x), adtype)
optprob = Optimization.OptimizationProblem(optf, p)
result_ode = Optimization.solve(optprob, PolyOpt(), callback = callback, maxiters = 600)

注意事项

  • 你之前移除sol后报错,是因为原回调函数依赖第三个参数pred(即sol),此时需要同步调整回调函数的参数列表,方式一已经处理了这个问题。
  • 方式二的Zygote.@ignore仅对Zygote有效,如果你后续更换其他AD工具(如ForwardDiff),需要改用对应工具的忽略方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:14:51