Hi, I’m fairly new to Julia so my apologies if this is an obvious question. I’m trying to create a model to sample from the below log-likelihood function. The C matrix is a constant and Δ follows a Dirichlet distribution. For reasons that don’t particularly matter here j
is always either 3 or 9 and i
can be any integer > 1.
I built this model using Stan by simply incrementing the log density directly.
data {
int<lower=0> i;
int<lower=0> j;
vector[j] alpha;
matrix[i, j] C;
}
model {
Delta ~ dirichlet(alpha);
target += log(C * Delta);
}
Now I’m trying to convert this model to use Turing.jl and it looks like the best way to go about doing that is to create a custom likelihood distribution. I’m trying to follow along with the guide here: https://turing.ml/stable/docs/using-turing/advanced and this previous response Custom likelihood with Turing.jl - #3 by Christopher_Fisher. But seem to be failing at some point.
C = [0.089398 0.0267295 0.007992; 0.0 0.000164962 4.31057e-5; 0.0170703 0.00223028 0.000291394; 0.0 0.0 0.00431887]
struct Δ_dist{c, δ} <: ContinuousMultivariateDistribution
C::c
Δ::δ
end
Broadcast.broadcastable(x::Δ_dist) = Ref(x)
Δ_dist(;C, Δ) = Δ_dist(C, Δ)
function rand(dist::Δ_dist)
@unpack C, Δ = dist
return @. rand(rng, Dirichlet(size(C)[2], 1/size(C)[2]))
end
rand(dist::Δ_dist, N::Int) = [rand(dist) for i in 1:N]
function logpdf(d::T) where {T<:Δ_dist}
@unpack C, Δ = d
LL = 0.0
LL += sum(log.(C * Δ))
return LL
end
logpdf(d::Δ_dist, data::Tuple) = logpdf(d, data...)
@model dyadRel(C) = begin
nCrosses = size(C)[2]
d ~ Dirichlet(nCrosses, 1 / nCrosses)
Δ ~ Δ_dist(C, d)
end
sample(dyadRel(C), NUTS(0.5), 100)
julia> sample(dyadRel(C), NUTS(0.5), 100)
ERROR: MethodError: no method matching length(::Δ_dist{Array{Float64,2},Array{Float64,1}})
Closest candidates are:
length(::Sampleable{Multivariate,S} where S<:ValueSupport) at C:\Users\jdsel\.julia\packages\Distributions\RAeyY\src\common.jl:39
length(::Sampleable) at C:\Users\jdsel\.julia\packages\Distributions\RAeyY\src\common.jl:37
length(::Core.SimpleVector) at essentials.jl:596
...
Stacktrace:
[1] length(::Δ_dist{Array{Float64,2},Array{Float64,1}}) at C:\Users\jdsel\.julia\packages\Distributions\RAeyY\src\common.jl:39
[2] rand(::Random._GLOBAL_RNG, ::Δ_dist{Array{Float64,2},Array{Float64,1}}) at C:\Users\jdsel\.julia\packages\Distributions\RAeyY\src\multivariates.jl:76
[3] init(::Random._GLOBAL_RNG, ::Δ_dist{Array{Float64,2},Array{Float64,1}}, ::DynamicPPL.SampleFromPrior) at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\sampler.jl:10
[4] assume(::Random._GLOBAL_RNG, ::DynamicPPL.SampleFromPrior, ::Δ_dist{Array{Float64,2},Array{Float64,1}}, ::DynamicPPL.VarName{:Δ,Tuple{}}, ::DynamicPPL.ThreadSafeVarInfo{DynamicPPL.VarInfo{DynamicPPL.Metadata{Dict{DynamicPPL.VarName,Int64},Array{Distribution,1},Array{DynamicPPL.VarName,1},Array{Real,1},Array{Set{DynamicPPL.Selector},1}},Float64},Array{Base.RefValue{Float64},1}}) at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\context_implementations.jl:138
[5] _tilde at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\context_implementations.jl:59 [inlined]
[6] tilde at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\context_implementations.jl:23 [inlined]
[7] tilde_assume(::Random._GLOBAL_RNG, ::DynamicPPL.DefaultContext, ::DynamicPPL.SampleFromPrior, ::Δ_dist{Array{Float64,2},Array{Float64,1}}, ::DynamicPPL.VarName{:Δ,Tuple{}}, ::Tuple{}, ::DynamicPPL.ThreadSafeVarInfo{DynamicPPL.VarInfo{DynamicPPL.Metadata{Dict{DynamicPPL.VarName,Int64},Array{Distribution,1},Array{DynamicPPL.VarName,1},Array{Real,1},Array{Set{DynamicPPL.Selector},1}},Float64},Array{Base.RefValue{Float64},1}}) at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\context_implementations.jl:52
[8] macro expansion at .\REPL[375]:4 [inlined]
[9] ##evaluator#498(::Random._GLOBAL_RNG, ::DynamicPPL.Model{var"###evaluator#498",(:C,),Tuple{Array{Float64,2}},(),DynamicPPL.ModelGen{var"###generator#499",(:C,),(),Tuple{}}}, ::DynamicPPL.ThreadSafeVarInfo{DynamicPPL.VarInfo{DynamicPPL.Metadata{Dict{DynamicPPL.VarName,Int64},Array{Distribution,1},Array{DynamicPPL.VarName,1},Array{Real,1},Array{Set{DynamicPPL.Selector},1}},Float64},Array{Base.RefValue{Float64},1}}, ::DynamicPPL.SampleFromPrior, ::DynamicPPL.DefaultContext) at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\compiler.jl:356
[10] evaluate_threadsafe(::Random._GLOBAL_RNG, ::DynamicPPL.Model{var"###evaluator#498",(:C,),Tuple{Array{Float64,2}},(),DynamicPPL.ModelGen{var"###generator#499",(:C,),(),Tuple{}}}, ::DynamicPPL.VarInfo{DynamicPPL.Metadata{Dict{DynamicPPL.VarName,Int64},Array{Distribution,1},Array{DynamicPPL.VarName,1},Array{Real,1},Array{Set{DynamicPPL.Selector},1}},Float64}, ::DynamicPPL.SampleFromPrior, ::DynamicPPL.DefaultContext) at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\model.jl:177
[11] Model at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\model.jl:138 [inlined]
[12] Model at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\model.jl:126 [inlined]
[13] VarInfo at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\varinfo.jl:110 [inlined]
[14] VarInfo at C:\Users\jdsel\.julia\packages\DynamicPPL\MRwtL\src\varinfo.jl:109 [inlined]
[15] DynamicPPL.Sampler(::NUTS{Turing.Core.ForwardDiffAD{40},(),AdvancedHMC.DiagEuclideanMetric}, ::DynamicPPL.Model{var"###evaluator#498",(:C,),Tuple{Array{Float64,2}},(),DynamicPPL.ModelGen{var"###generator#499",(:C,),(),Tuple{}}}, ::DynamicPPL.Selector) at C:\Users\jdsel\.julia\packages\Turing\GMBTf\src\inference\hmc.jl:378
[16] Sampler at C:\Users\jdsel\.julia\packages\Turing\GMBTf\src\inference\hmc.jl:376 [inlined]
[17] sample(::Random._GLOBAL_RNG, ::DynamicPPL.Model{var"###evaluator#498",(:C,),Tuple{Array{Float64,2}},(),DynamicPPL.ModelGen{var"###generator#499",(:C,),(),Tuple{}}}, ::NUTS{Turing.Core.ForwardDiffAD{40},(),AdvancedHMC.DiagEuclideanMetric}, ::Int64; kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at C:\Users\jdsel\.julia\packages\Turing\GMBTf\src\inference\Inference.jl:163
[18] sample at C:\Users\jdsel\.julia\packages\Turing\GMBTf\src\inference\Inference.jl:163 [inlined]
[19] #sample#1 at C:\Users\jdsel\.julia\packages\Turing\GMBTf\src\inference\Inference.jl:153 [inlined]
[20] sample(::DynamicPPL.Model{var"###evaluator#498",(:C,),Tuple{Array{Float64,2}},(),DynamicPPL.ModelGen{var"###generator#499",(:C,),(),Tuple{}}}, ::NUTS{Turing.Core.ForwardDiffAD{40},(),AdvancedHMC.DiagEuclideanMetric}, ::Int64) at C:\Users\jdsel\.julia\packages\Turing\GMBTf\src\inference\Inference.jl:153
[21] top-level scope at REPL[376]:100:
Am I going about trying to implement this likelihood function in the right way? Any help would be hugely appreciated!
Thank you!