# Latent Variables

I am struggling with this error for modeling latent variables using Turing

MethodError: no method matching Normal(::Array{Float64,1}, ::Float64)

My data generation code is

using Distributions
using Statistics, LinearAlgebra
using Turing, TuringModels

function SEM_b(N_ID, NY)
ld2 = [1 .71 .69 0 0 0;
0 0 0 1 .35 1.5]

cov2 = Matrix(1.0I,2,2)

eta2 = MvNormal([0; 0],cov2)
eta2b = rand(eta2, N_ID) #2*N matrix

eps2 = MvNormal(fill(0, NY),diagm(ones(NY)))

eps2b = rand(eps2, N_ID) #NY*N_ID matrix

Y2 = transpose(eta2b)*ld2 + transpose(eps2b)

transpose(eta2b), transpose(eps2b), Y2

end

and my Turing code is

@model MM_SEM(Y, N_eta) = begin

ll,rr = size(Y)
μ = Array{Float64,2}(undef,ll,rr)

λ ~ filldist(Normal(0,5),4)
η_σ ~ filldist(truncated(Normal(0,5),0,Inf),N_eta)

σ ~ filldist(truncated(Normal(0,5),0,Inf),rr)

η_ρ ~ LKJ(N_eta,1.)

L = η_σ .* η_ρ .* η_σ'

L = (L' + L)/2

eta ~ filldist(MvNormal(fill(0,N_eta), L),ll)

μ[:,1] = eta[1,:]
μ[:,2] = λ[1]*eta[1,:]
μ[:,3] = λ[2]*eta[1,:]

μ[:,4] = eta[2,:]
μ[:,5] = λ[3]*eta[2,:]
μ[:,6] = λ[4]*eta[2,:]

for j in 1:rr
Y[:,j] ~ Normal(μ[:,j],σ[j])
end
#for i ∈ 1:ll

#μ[i,1] = eta[1,i]
#μ[i,2] = λ[1]*eta[1,i]
#μ[i,3] = λ[2]*eta[1,i]

#μ[i,4] = eta[2,i]
#μ[i,5] = λ[3]*eta[2,i]
#μ[i,6] = λ[4]*eta[2,i]

#for j in 1:rr
#    Y[i,j] ~ Normal(μ[i,j],σ[j])
#end

#end
end

and

chain = sample(MM_SEM(a[3],2), NUTS(0.95), 1000);

Here you calling Normal with an array as the first argument, and it seems there is no such method, only Normal with two scalars.

1 Like

Thank you very much for your reply. Sorry, I am a bit confused at this moment. If I change it to

for i ∈ 1:ll

μ[i,1] = eta[1,i]
μ[i,2] = λ[1]*eta[1,i]
μ[i,3] = λ[2]*eta[1,i]

μ[i,4] = eta[2,i]
μ[i,5] = λ[3]*eta[2,i]
μ[i,6] = λ[4]*eta[2,i]

for j in 1:rr
Y[i,j] ~ Normal(μ[i,j],σ[j])
end

end

I end up with this error also

TypeError: in typeassert, expected Float64, got a value of type ForwardDiff.Dual{Nothing,Float64,10}
in top-level scope at test.jl:78
in sample at Turing\RzDvB\src\inference\Inference.jl:154
in #sample#1 at Turing\RzDvB\src\inference\Inference.jl:154
in sample at Turing\RzDvB\src\inference\Inference.jl:164
in #sample#2 at Turing\RzDvB\src\inference\Inference.jl:164
in Sampler at Turing\RzDvB\src\inference\hmc.jl:376
in DynamicPPL.Sampler at Turing\RzDvB\src\inference\hmc.jl:384
in Turing.Inference.HMCState at Turing\RzDvB\src\inference\hmc.jl:605
in #HMCState#58 at Turing\RzDvB\src\inference\hmc.jl:624
in ∂logπ∂θ at Turing\RzDvB\src\inference\hmc.jl:474
in Model at DynamicPPL\uRBQJ\src\model.jl:84
in Model at DynamicPPL\uRBQJ\src\model.jl:96
in _evaluate at DynamicPPL\uRBQJ\src\model.jl:145
in macro expansion at DynamicPPL\uRBQJ\src\model.jl
in  at base\none
in #11 at test.jl:62
in setindex! at base\array.jl:849

(Googling the error message helps many times)

1 Like

Can you provide a MWE? I don’t know how to get a from your code.

Besides, it seems like you are adapting code from:

So do you try to write code like original form: wait .~ Normal.(mu , sigma) instead of an explicit looping?

Yes. I did adapt the part about using the LKJ correlation matrix and covariance matrix from the Julia version of Statistical Rethinking.
Sorry

a = SEM_b(300,6)

This is my first program in Julia, so I am not good at expressing my code in a condensed form.

Just to add, I am finally able to get it to work even though it is not efficient

@model function MM_SEM(Y, N_eta, ::Type{T} = Matrix{Float64}) where T

ll,rr = size(Y)

μ = T(undef, ll, rr)

λ ~ filldist(Normal(0,5),4)
η_σ ~ filldist(truncated(Normal(0,5),0,Inf),N_eta)

σ ~ filldist(truncated(Normal(0,5),0,Inf),rr)

η_ρ ~ LKJ(N_eta,1.)

L = η_σ .* η_ρ .* η_σ'

L = (L' + L)/2

eta ~ filldist(MvNormal(fill(0,N_eta), L),ll)

for i = 1:ll

μ[i,1] = eta[1,i]
μ[i,2] = λ[1]*eta[1,i]
μ[i,3] = λ[2]*eta[1,i]

μ[i,4] = eta[2,i]
μ[i,5] = λ[3]*eta[2,i]
μ[i,6] = λ[4]*eta[2,i]

for j = 1:rr
Y[i,j] ~ Normal(μ[i,j],σ[j])
end

end

return λ, σ, η_σ, η_ρ
end

#need to check on the LKJ corr
chain = sample(MM_SEM(a[3],2), NUTS(0.95), 1000);
1 Like