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

使用Optim.jl进行函数最小化时无法收敛的问题排查

解决Optim.jl无法收敛到正确解的问题

你从Python移植的图像污染物移除优化代码,函数逻辑已验证正确,但Optim.jl无法收敛到预期结果,核心问题大概率出在优化算法选择、梯度处理或参数配置上,以下是针对性解决方案:

1. 对齐Scipy的优化算法

Scipy默认用L-BFGS-B算法处理这类光滑的平方和残差问题,而Optim.jl的optimize默认算法是Nelder-Mead(更适合非光滑问题),显式指定LBFGS能大幅提升收敛效果:

using Optim
# 显式使用LBFGS算法,搭配更严格的收敛阈值
options = Optim.Options(show_trace=true, g_tol=1e-6, iterations=1000)
result = optimize(residui, s_in, LBFGS(), options)

2. 优化数组操作,提升数值稳定性

原函数里的循环拷贝操作可能引入不必要的数值误差,用Julia的广播特性替代循环,既高效又能保证数值一致性:

function residuals(s, image, source, contaminants, error)
    mean, median, std = ass.stats.sigma_clipped_stats(image)
    sorgente = source .* s[1]
    # 用广播替代循环,避免数组拷贝
    c = contaminants .* reshape(s[2:end], 1, 1, :)
    cont_sommati = dropdims(nansum(c, dims=3), dims=3)
    mod = cont_sommati .+ sorgente
    res = nansum(((mod .- (image .- mean))./error).^2)
    return res
end

3. 提供梯度信息(关键优化点)

Scipy默认会自动处理梯度,但Optim.jl的部分算法需要更精确的梯度输入。用ForwardDiff.jl自动求导,能让优化过程更准确:

using ForwardDiff, Optim
# 同时提供函数值和梯度
fg! = (F, G, s) -> begin
    if G !== nothing
        ForwardDiff.gradient!(G, residui, s)
    end
    if F !== nothing
        return residui(s)
    end
    return nothing
end
result = optimize(Optim.only_fg!(fg!), s_in, LBFGS(), options)

4. 添加参数边界约束

污染物的缩放因子应为非负值(强度不能为负),给参数设置边界能避免优化陷入无意义的区域,这对应Scipy的bounds参数:

# 设置参数下界为0,上界为无穷大
lower = zeros(length(s_in))
upper = fill(Inf, length(s_in))
result = optimize(residui, lower, upper, s_in, Fminbox(LBFGS()), options)

5. 调试优化过程

开启show_trace=true可以查看每一步的残差变化,确认优化是否在推进,或是陷入局部最优:

  • 如果残差停滞不动,说明初始值可能离真实解太远,可以尝试用Scipy得到的最优解作为初始值测试。
  • 如果残差下降缓慢,调整g_tol(梯度容忍度)或iterations(迭代次数)参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 07:57:19