-
Notifications
You must be signed in to change notification settings - Fork 228
Description
This was discovered by @owensnick in https://discourse.julialang.org/t/avoiding-loops-in-turing/59830.
n = 200
configs = [-820:180:-100, 280:180:1000]
class = rand(1:2, n);
pos = rand(1:5, n);
x = [rand(Normal(configs[c][p], 5)) for (c, p) in zip(class, pos)];
The following model works as expected, producing something looks reasonable:
@model function modelloop(x, configs, σ, ::Type{TV} = Vector{Int}) where {TV}
n = length(x)
w = [0.5, 0.5]
p = ones(5)/5
class = TV(undef, n)
pos = TV(undef, n)
for i = 1:n
class[i] ~ Categorical(w)
pos[i] ~ Categorical(p)
x[i] ~ Normal(configs[class[i]][pos[i]], σ)
end
end
ml = modelloop(x, configs, 5)
chain_loop = sample(ml, PG(5), 100);
In contrast, the following "vectorized" version of the model results in samples from what looks/likely is the prior:
@model function modelvec(x, configs, σ)
n = length(x)
w = [0.5, 0.5]
p = ones(5)/5
class ~ filldist(Categorical(w), n)
pos ~ filldist(Categorical(p), n)
x ~ arraydist(map((c, l) -> Normal(configs[c][l], σ), class, pos))
end
mv = modelvec(x, configs, 5);
chain_vec = sample(mv, PG(5), 100);
And, to me, even stranger, if you write out the observation in a for loop, i.e.
for i = 1:n
x[i] ~ Normal(configs[class[i]][pos[i]], σ)
end
in the vectorized model, you end up with something that looks reasonable only for i = 1.
I don't have time to look more deeply into it right now, but figured I'd put this here to hold us accountable.
@devmotion seemed to have some intuition of at least what's going wrong (from slack):
PG and SMC are based on propagation at every observe statement
So I guess the problem might be that we can't tell if the vectorized statement is a single observation or a set of observations