cscherrer / Soss.jl

Probabilistic programming via source rewriting
https://cscherrer.github.io/Soss.jl/stable/
MIT License
414 stars 30 forks source link

Empty model in predict #314

Closed jtrakk closed 2 years ago

jtrakk commented 2 years ago

I'm hitting this error in predict(::ConditionalModel).

ArgumentError: reducing over an empty collection is not allowed
Stacktrace:
  [1] _empty_reduce_error()
    @ Base ./reduce.jl:301
  [2] reduce_empty(op::Function, #unused#::Type{Any})
    @ Base ./reduce.jl:311
  [3] reduce_empty(op::Base.BottomRF{typeof(merge)}, #unused#::Type{Any})
    @ Base ./reduce.jl:330
  [4] reduce_empty_iter
    @ ./reduce.jl:357 [inlined]
  [5] reduce_empty_iter
    @ ./reduce.jl:356 [inlined]
  [6] foldl_impl
    @ ./reduce.jl:49 [inlined]
  [7] mapfoldl_impl(f::typeof(identity), op::typeof(merge), nt::Base._InitialValue, itr::Vector{Any})
    @ Base ./reduce.jl:44
  [8] mapfoldl(f::Function, op::Function, itr::Vector{Any}; init::Base._InitialValue)
    @ Base ./reduce.jl:162
  [9] mapfoldl
    @ ./reduce.jl:162 [inlined]
 [10] #foldl#245
    @ ./reduce.jl:180 [inlined]
 [11] foldl(op::Function, itr::Vector{Any})
    @ Base ./reduce.jl:180
 [12] Soss.Model(theModule::Module, expr::Expr)
    @ Soss ~/.julia/packages/Soss/b4pBv/src/core/models/model.jl:69
 [13] Soss.Model(theModule::Module, args::Vector{Symbol}, expr::Expr)
    @ Soss ~/.julia/packages/Soss/b4pBv/src/core/models/model.jl:93
 [14] type2model(#unused#::Type{Soss.Model{NamedTuple{()}, GeneralizedGenerated.NGG.TypeLevel{Expr, "Buf{23}()"}, GeneralizedGenerated.NGG.TypeLevel{Module, "Buf{17}()"}}})
    @ Soss ~/.julia/packages/Soss/b4pBv/src/core/models/model.jl:30
 [15] macro expansion
    @ ~/.julia/packages/Soss/b4pBv/src/primitives/rand.jl:60 [inlined]
 [16] #s65#45
    @ ~/.julia/packages/GeneralizedGenerated/PV9u7/src/closure_conv.jl:132 [inlined]
 [17] var"#s65#45"(::Any, M::Any, _m::Any, _args::Any)
    @ Soss ./none:0
 [18] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any})
    @ Core ./boot.jl:580
cscherrer commented 2 years ago

Can you give me code to replicate the error?

jtrakk commented 2 years ago

This reproduces ArgumentError: reducing over an empty collection is not allowed.

Is it clear what I'm doing wrong?

using Soss, SampleChainsDynamicHMC, TypedTables, Random, MeasureTheory

m = @model (d) begin
    β1 ~ Normal(μ=0., σ=0.05)
    rs = rows(d)
    y ~ let rs = rs
            For(rs) do r
                v = β1 * r.x1
                p = logistic(v)
                Bernoulli(p)
        end
    end
end

pred = predictive(m)
n = 100
tbl = Table(x1 = rand(1:10, n), res=rand(Bool, n))
condmod =  m(d=collect(tbl)) | (; y=tbl.res)
multichain = Soss.sample(Random.GLOBAL_RNG, condmod, dynamichmc(), 10, 1)
mapped = map(θ->pred(;d=tbl,), multichain);
simulate.(mapped)
cscherrer commented 2 years ago
julia> predictive(m)
@model begin
    end

Do you mean to say

julia> predictive(m, :β1)
@model (d, β1) begin
        rs = rows(d)
        y ~ let rs = rs
                For(rs) do r
                    v = β1 * r.x1
                    p = logistic(v)
                    Bernoulli(p)
                end
            end
    end

Then maybe

mapped = map(multichain) do sample
    rand(pred(d=d, β1=sample.β1))
end
jtrakk commented 2 years ago

Thanks, that fixes my issue for simulate and rand. Still getting that error for predict though, and the non-broadcasted version hangs:

using Soss, SampleChainsDynamicHMC, TypedTables, Random, MeasureTheory, DataFrames

m = @model (d) begin
    β1 ~ Normal(μ=0., σ=0.05)
    rs = rows(d)
    y ~  For(rs) do r
            v = β1 * r.x1
            p = logistic(v)
            Bernoulli(p)
    end
end

n = 100
tbl = DataFrame(x1 = rand(Float64.(1:10), n), res=rand(Bool, n))
condmod =  m(d=tbl) | (; y=tbl.res)
multichain = Soss.sample(Random.GLOBAL_RNG, condmod, dynamichmc(), 10, 1)
pred = predictive(m, :β1)
mapped = [pred(;d=tbl,β1=θ.β1) for θ in multichain];
simulate.(mapped)
rand.(mapped)
predict.(mapped) # ArgumentError: reducing over an empty collection is not allowed
predict(mapped) # hangs
cscherrer commented 2 years ago

It's the same problem. predictive makes a new model using the names of variables you'd like to turn into arguments. predict is basically predictive followed by rand. The code for it is pretty short, and may be the easiest way to see what it does: https://github.com/cscherrer/Soss.jl/blob/master/src/transforms/predict.jl

jtrakk commented 2 years ago

Got it, thanks!