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

Turing.jl模型采样参数类型变更问题求助

问题与解决方案

错误现象

使用Turing.jl构建混合多项Logit模型时,运行代码出现两个错误:

  1. MethodError: no method matching float(::Type{Any}):根源是采样语句Beta[:, r] ~ MvNormal(Theta * Z[:, r], Sigma)将Beta[:, r]的类型变更为Vector{Any},导致后续运算类型不兼容。
  2. 手动转换Beta[:,r]为Float64后,出现TypeError: in typeassert, expected Float64, got a value of type ForwardDiff.Dual{Nothing, Float64, 12}:破坏了Turing依赖的自动微分功能,因为ForwardDiff需要保留Dual类型计算梯度。

错误原因

  1. 预先用zeros(K, R)初始化Beta为Float64类型,当对Beta[:,r]执行采样时,Turing会注入自动微分所需的ForwardDiff.Dual类型值,导致数组元素类型混杂,最终被提升为Any,引发类型错误。
  2. 强制转换Beta[:,r]为Float64会丢弃Dual类型,导致自动微分无法进行,触发类型断言错误。

修正后的完整代码

using LinearAlgebra, Distributions, StatsBase
using Turing, FillArrays, DynamicHMC, LabelledArrays
using NNlib, GLM
using CSV, DataFrames

function generate_hmnl_data(R::Int=100, S::Int=30, C::Int=3,
    Theta::Array{Float64, 2}=ones(2, 4),
    Sigma::Array{Float64, 2}=Matrix(Diagonal(fill(0.1, 4))))
    K = size(Theta, 2)
    G = size(Theta, 1)
    Y = Array{Int64}(undef, R, S)
    X = randn(R, S, C, K)
    Z = Array{Float64}(undef, G, R)
    Z[1, :] .= 1
    if G > 1
        # 修复维度匹配问题
        Z[2:G, :] = reshape(randn(R * (G-1)), G-1, R)
    end
    Beta = Array{Float64}(undef, K, R)
    for r in 1:R
        Beta[:, r] = rand(MvNormal(Theta' * Z[:, r], Sigma))
        for s in 1:S
            Y[r, s] = sample(1:C, Weights(exp.(X[r, s, :, :] * Beta[:, r])))
        end
    end
    return (R=R, S=S, C=C, K=K, G=G, Y=Y, X=X, Z=Z,
    beta_true=Beta, Theta_true=Theta, Sigma_true=Sigma)
end
d1 = generate_hmnl_data()

@model function hmnl(G::Int, Y::Matrix{Int64}, X::Array{Float64}, Z::Matrix{Float64})
    R, S, C, K = size(X)
    # 用filldist简化Theta采样,保证类型稳定
    Theta ~ filldist(Normal(0, 10), K, G)
    Sigma ~ InverseWishart(K, diagm(ones(K)))
    
    # 基于Theta的类型初始化Beta,兼容自动微分的Dual类型
    Beta = Matrix{eltype(Theta)}(undef, K, R)
    for r in 1:R
        Beta[:, r] ~ MvNormal(Theta * Z[:, r], Sigma)
        for s in 1:S
            # 无需手动转换类型,直接使用Beta[:,r]
            ut_rs = X[r, s, :, :] * Beta[:, r]
            v = softmax(ut_rs)
            Y[r, s] ~ Categorical(v)
        end
    end
end

sampler = HMC(.05, 10)
test_mod = hmnl(d1.G, d1.Y, d1.X, d1.Z)
chains = sample(test_mod, sampler, 1_000)

关键修正点

  1. 修复生成数据函数的维度问题:将Z[2:G, :] = randn(R * (G-1))改为reshape(randn(R*(G-1)), G-1, R),确保数组维度匹配,避免赋值错误。
  2. 简化Theta的采样方式:用filldist(Normal(0,10), K, G)替代双重循环,代码更简洁且类型稳定性更好。
  3. 正确初始化Beta:基于Theta的类型(自动微分时为Dual类型,采样时为Float64)初始化Beta,避免类型提升为Any,同时兼容自动微分需求。
  4. 移除手动类型转换:直接使用Beta[:,r]参与运算,保留Turing自动微分所需的类型,避免破坏梯度计算。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:05:18