能否在Turing模型中嵌入JuMP优化问题?报错求助
能否在Turing模型中使用JuMP优化问题?
你的问题核心是Turing的自动微分(ForwardDiff)与JuMP求解器的类型不兼容:Turing在采样时会将参数θ转换为ForwardDiff的Dual类型以计算梯度,但JuMP的Ipopt求解器只能处理标准Float64类型,导致类型转换错误。
下面提供两种可行的解决方案:
方案一:用解析解替代JuMP优化(最简单,适合你的示例)
你的优化问题是二次函数最大化,可直接推导解析解,完全避免调用JuMP:
using Turing # 替换原find_u函数为解析解 function find_u(θ) # 最大化θ*u - u²的解析解:u = θ/2 return θ / 2 end @model function turing_model(y) σ = 1e-3 θ ~ Uniform(0, 2) for i in 1:length(y) y[i] ~ Normal(find_u(θ), σ) end end # 模拟数据 θs = 1 y = [find_u(θs) + rand(Normal(0, 1e-3)) for _ in 1:10] # 推理 numberofsamples = 500 m_train = turing_model(y); posterior_chain = sample(m_train, NUTS(100, 0.65), numberofsamples)
这个方案完全规避了类型问题,运行不会报错,且效率更高。
方案二:兼容自动微分的JuMP优化(适用于复杂无法解析的问题)
如果你的实际问题无法用解析解表达,需要保留JuMP优化,可以通过以下方式让函数兼容ForwardDiff的Dual类型:
方法1:改用支持自动微分的优化器(如Optim.jl)
Optim.jl的求解器原生支持ForwardDiff的Dual类型,可替代JuMP+Ipopt:
using Turing using Optim function find_u(θ) # 将最大化问题转为最小化(Optim默认求最小) f(u) = -(θ * u - u^2) # 用L-BFGS求解带边界的优化问题 res = optimize(f, 0.0, 10.0, LBFGS()) return Optim.minimizer(res) end @model function turing_model(y) σ = 1e-3 θ ~ Uniform(0, 2) for i in 1:length(y) y[i] ~ Normal(find_u(θ), σ) end end # 模拟数据与推理部分同方案一 θs = 1 y = [find_u(θs) + rand(Normal(0, 1e-3)) for _ in 1:10] numberofsamples = 500 m_train = turing_model(y); posterior_chain = sample(m_train, NUTS(100, 0.65), numberofsamples)
方法2:用ImplicitDifferentiation.jl实现隐式微分
对于必须使用JuMP的场景,可借助ImplicitDifferentiation.jl通过KKT条件隐式计算优化问题对参数θ的导数,无需让JuMP直接处理Dual类型:
using Turing using JuMP import Ipopt using ImplicitDifferentiation # 原JuMP优化函数 function find_u(θ) model = Model(optimizer_with_attributes(Ipopt.Optimizer)) set_silent(model) @variables(model, begin 0 <= u <= 10 end) @NLobjective(model, Max, θ * u - u^2) optimize!(model) return value(u) end # 定义优化问题的KKT条件(用于隐式微分) function kkt(θ, u) # 一阶最优条件:d/du(θu - u²) = 0 → θ - 2u = 0 # 因θ∈(0,2)时u=θ/2∈(0,1),边界约束无绑定,互补松弛项为0 return [θ - 2u] end # 创建支持自动微分的隐式函数 implicit_find_u = ImplicitFunction(find_u, kkt) @model function turing_model(y) σ = 1e-3 θ ~ Uniform(0, 2) for i in 1:length(y) y[i] ~ Normal(implicit_find_u(θ), σ) end end # 模拟数据与推理部分同方案一 θs = 1 y = [find_u(θs) + rand(Normal(0, 1e-3)) for _ in 1:10] numberofsamples = 500 m_train = turing_model(y); posterior_chain = sample(m_train, NUTS(100, 0.65), numberofsamples)
内容的提问来源于stack exchange,提问作者Marco Tulio Angulo
相关产品推荐
相关产品推荐

