Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match AdvancedPS 0.4 API #1858

Merged
merged 49 commits into from
Dec 7, 2022
Merged

Match AdvancedPS 0.4 API #1858

merged 49 commits into from
Dec 7, 2022

Conversation

FredericWantiez
Copy link
Member

@FredericWantiez FredericWantiez commented Jul 9, 2022

Tweaking Turing to work with the new interface of AdvancedPS

Closes #1903 Closes #1901 Closes #1902

Frederic Wantiez added 2 commits July 9, 2022 15:28
@FredericWantiez
Copy link
Member Author

Still running into one annoying issue:

dynamic model: Error During Test at /Users/frederic/Documents/projects/turing/Turing.jl/test/test_utils/staging.jl:42
  Got exception outside of a @test
  TypeError: in Type{...} expression, expected UnionAll, got a value of type typeof(TArray)
  Stacktrace:
    [1] get_matching_type(spl::Sampler{PG{(:z,), ResampleWithESSThreshold{typeof(resample_systematic), Float64}}}, vi::DynamicPPL.TypedVarInfo{NamedTuple{(:z, :m), Tuple{DynamicPPL.Metadata{Dict{AbstractPPL.VarName{:z, Setfi
eld.IndexLens{Tuple{Int64}}}, Int64}, Vector{ChineseRestaurantProcess{DirichletProcess{Float64}, Vector{Int64}}}, Vector{AbstractPPL.VarName{:z, Setfield.IndexLens{Tuple{Int64}}}}, Vector{Int64}, Vector{Set{DynamicPPL.Select
or}}}, DynamicPPL.Metadata{Dict{AbstractPPL.VarName{:m, Setfield.IndexLens{Tuple{Int64}}}, Int64}, Vector{Normal{Float64}}, Vector{AbstractPPL.VarName{:m, Setfield.IndexLens{Tuple{Int64}}}}, Vector{Float64}, Vector{Set{Dynam
icPPL.Selector}}}}}, Float64}, #unused#::Type{Vector{Float64}})

Which is caused by this get_matching_type here

function DynamicPPL.get_matching_type(
spl::Sampler{<:Union{PG, SMC}},
vi,
::Type{TV},
) where {T, N, TV <: Array{T, N}}
return TArray{T, N}
end

and the new logic in Libtask in 0.8.

@FredericWantiez FredericWantiez marked this pull request as draft October 29, 2022 21:07
@yebai
Copy link
Member

yebai commented Oct 29, 2022

I think we don't need get_matching_type anymore because Libtask@0.8 removed TArray. I will take a more careful look tomorrow.

@FredericWantiez
Copy link
Member Author

The issue here is that z gets boxed and ends being of type Core.Box(Array{Int}) which is then shallow copied across forks:

1 ──        (x@_56 = x@_5)::Vector{Float64}
│   (__varinfo__@_55 = __varinfo__@_3)::DynamicPPL.TypedVarInfo{....}, Float64}
│   Core.NewvarNode(:(retval#1789))::Any
│   (z@_9 = Core.Box())::Core.Box # <------ Here z = Core.Box()
│   (α = 1.0)::Core.Const(1.0)
│   (μ0 = 0.0)::Core.Const(0.0)
│   (σ0 = 1.0)::Core.Const(1.0)
│   (rpm = Main.DirichletProcess(α::Core.Const(1.0)))::Core.Const(DirichletProcess{Float64}(1.0))
│   (H = Main.Normal(μ0::Core.Const(0.0), σ0::Core.Const(1.0)))::Core.Const(Normal{Float64}(μ=0.0, σ=1.0))

@KDr2
Copy link
Member

KDr2 commented Nov 23, 2022

The issue here is that z gets boxed and ends being of type Core.Box(Array{Int}) which is then shallow copied across forks:

But we have the content of Boxes deep or shallow copied here accordingly: https://github.com/TuringLang/Libtask.jl/blob/master/src/tapedfunction.jl#L479

Is it possible to wrap an MWE to reproduce this issue?

@FredericWantiez
Copy link
Member Author

But I'm not sure the tape_copy mechanism works as expected for boxed values:

tape_shallowcopy(x::Core.Box) = Core.Box(tape_shallowcopy(x.contents))
tape_deepcopy(x::Core.Box) = Core.Box(tape_deepcopy(x.contents))


function _tape_copy(v, deepcopy_types)
    if isa(v, deepcopy_types)
        tape_deepcopy(v)
    else
        tape_shallowcopy(v)
    end
end

since we dispatch on deepcopy_types but Core.Box is not one of them we would always shallowcopy.

@FredericWantiez
Copy link
Member Author

Here's an example that fails on this branch

using Random
using Turing
using Turing.RandomMeasures
using Libtask
using AdvancedPS
using DynamicPPL

@model function infiniteGMM(x)
    # Hyper-parameters, i.e. concentration parameter and parameters of H.
    α = 1.0
    μ0 = 0.0
    σ0 = 1.0

    # Define random measure, e.g. Dirichlet process.
    rpm = DirichletProcess(α)

    # Define the base distribution, i.e. expected value of the Dirichlet process.
    H = Normal(μ0, σ0)

    # Latent assignment.
    z = zeros(Int, length(x))

    # Locations of the infinitely many clusters.
    μ = zeros(Float64, 0)

    for i in 1:length(x)
        # Number of clusters.
        K = maximum(z)
        nk = Vector{Int}(map(k -> sum(z .== k), 1:K))

        #println("i: $i, K: $K, Mu $(μ) $([objectid(μ)]) z: $z, $([objectid(z)]) $(typeof(z)) $(typeof(μ))")

        # Draw the latent assignment.
        z[i] ~ ChineseRestaurantProcess(rpm, nk)
        
        # Create a new cluster?
        if z[i] > K
            push!(μ, 0.0)

            # Draw location of new cluster.
            μ[z[i]] ~ H
        end
                
        # Draw observation.
        x[i] ~ Normal(μ[z[i]], 1.0)
    end
end

# Generate some test data.
Random.seed!(2);
m = 3
data = vcat(randn(5), randn(10) .- 5, randn(10) .+ 10);
data .-= mean(data);
data /= std(data);

model_fun = infiniteGMM(data);

# MCMC sampling
Random.seed!(54);
iterations = 300;
chain = sample(model_fun, SMC(), iterations; progress=false)

@coveralls
Copy link

coveralls commented Nov 27, 2022

Pull Request Test Coverage Report for Build 3624437376

  • 0 of 53 (0.0%) changed or added relevant lines in 4 files are covered.
  • 1121 unchanged lines in 21 files lost coverage.
  • Overall coverage decreased (-81.2%) to 0.0%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/inference/Inference.jl 0 1 0.0%
src/inference/gibbs.jl 0 1 0.0%
src/inference/AdvancedSMC.jl 0 23 0.0%
src/essential/container.jl 0 28 0.0%
Files with Coverage Reduction New Missed Lines %
src/variational/VariationalInference.jl 8 0%
src/essential/container.jl 10 0%
src/Turing.jl 11 0%
src/inference/is.jl 16 0%
src/utilities/helper.jl 18 0%
src/inference/gibbs_conditional.jl 20 0%
src/stdlib/RandomMeasures.jl 22 0%
src/contrib/inference/dynamichmc.jl 31 0%
src/inference/ess.jl 45 0%
src/variational/advi.jl 45 0%
Totals Coverage Status
Change from base Build 3517675867: -81.2%
Covered Lines: 0
Relevant Lines: 1432

💛 - Coveralls

@codecov
Copy link

codecov bot commented Nov 27, 2022

Codecov Report

Base: 81.24% // Head: 0.00% // Decreases project coverage by -81.24% ⚠️

Coverage data is based on head (990e382) compared to base (7c38ee9).
Patch coverage: 0.00% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #1858       +/-   ##
==========================================
- Coverage   81.24%   0.00%   -81.25%     
==========================================
  Files          21      21               
  Lines        1418    1432       +14     
==========================================
- Hits         1152       0     -1152     
- Misses        266    1432     +1166     
Impacted Files Coverage Δ
src/essential/container.jl 0.00% <0.00%> (-79.42%) ⬇️
src/inference/AdvancedSMC.jl 0.00% <0.00%> (-94.36%) ⬇️
src/inference/Inference.jl 0.00% <0.00%> (-84.56%) ⬇️
src/inference/gibbs.jl 0.00% <0.00%> (-97.34%) ⬇️
src/inference/is.jl 0.00% <ø> (-93.75%) ⬇️
src/contrib/inference/dynamichmc.jl 0.00% <0.00%> (-100.00%) ⬇️
src/contrib/inference/sghmc.jl 0.00% <0.00%> (-98.51%) ⬇️
src/inference/gibbs_conditional.jl 0.00% <0.00%> (-95.24%) ⬇️
src/inference/emcee.jl 0.00% <0.00%> (-94.12%) ⬇️
... and 16 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@FredericWantiez
Copy link
Member Author

I'll add some tests but this is mostly working now, still not quite sure why it fails on convergence for Ubuntu/Julia1.7 but not on the other images.

@torfjelde
Copy link
Member

Seems like it's just a difference in RNGs, no? As in, it's getting very close to the correct result but just outside of the allowed tolerance. So try increasing iterations/particles for this particular test.

@FredericWantiez
Copy link
Member Author

Agree, but if everything is seeded explicitly it shouldn't vary across images ?

@yebai yebai marked this pull request as ready for review December 6, 2022 17:51
@yebai
Copy link
Member

yebai commented Dec 6, 2022

@devmotion Are you happy with the changes in this PR? It (hopefully temporarily, see below) dropped support for Julia 1.6. It is largely due to Libtask, which only supports Julia 1.7 and above -- substantial efforts are required to support Julia 1.6 due to major Julia compiler changes.

In addition, @FredericWantiez and I discussed moving the general-purpose particle Gibbs sampler implementation (requires Libtask) into an experimental namespace and loading Libtask on demand. As an alternative, we are implementing a new package, SSMProblems, to specify common-state-space models, which will be recommended if the user wants to specify a model as SSM and run particle filtering-related sampling algorithms.

@yebai yebai merged commit 6fbebf8 into master Dec 7, 2022
@delete-merged-branch delete-merged-branch bot deleted the fred/advancedps_release branch December 7, 2022 18:07
@devmotion
Copy link
Member

Just saw the comment now (I'm very busy until Christmas and not too responsive on Github and Slack these days): An unfortunate consequence of the Julia compat change is also that we can't keep using Julia LTS in TuringTutorials (by doing so we avoid having to update the whole repo every time a new Julia version is available).

In addition, @FredericWantiez and I discussed moving the general-purpose particle Gibbs sampler implementation (requires Libtask) into an experimental namespace and loading Libtask on demand

I assume you're talking about AdvancedPS here? If one can split the package cleanly in a part with and without Libtask that might be a good idea. Maybe one could move it to a subpackage (e.g., AdvancedPSLibtask) in the AdvancedPS repo to make the separation even clearer but avoid the friction of having to update two separate repos all the time.

As an alternative, we are implementing a new package, SSMProblems, to specify common-state-space models, which will be recommended if the user wants to specify a model as SSM and run particle filtering-related sampling algorithms.

If the dependencies of AdvancedPS are manageable, I wonder if it would be better to define the problem type there together with the algorithms. Otherwise it seems it is easy to introduce circular dependencies in the tests. Maybe an alternative could be to make it a subpackage, again to avoid having to re-iterate between both repos too much.

@torfjelde
Copy link
Member

torfjelde commented Dec 9, 2022

Personally I'm really not a big fan of dropping support for Julia 1.6. Julia 1.6 is still heavily used by Turing users, so this bump is very excluding.

@torfjelde
Copy link
Member

For example, we are in the process of bumping Setfield compat entry to 1 in Turing deps. Now this change won't benefit people using Julia 1.6.

@devmotion
Copy link
Member

Yes, I agree. I think support for Julia LTS is a good common ground throughout the ecosystem in general. It seems quite annoying for people that can't update Julia as easily (or don't want to, e.g., to avoid hunting bugs or performance regressions with newer versions). Since so many packages depend on each other (which is a good thing in general IMO) it, bumping the Julia compat can have a much larger effect than originally anticipated (see, e.g., also tpapp/DynamicHMC.jl#172).

@torfjelde
Copy link
Member

torfjelde commented Dec 9, 2022

Would it be possible to revert this change @yebai ? I have some PRs I'd like to make, but basing it on the current master worries me.

EDIT: Btw, this PR is great @FredericWantiez ! This has absolutely nothing to do with your work.

@yebai
Copy link
Member

yebai commented Dec 9, 2022

Yes, we plan to make the dependency on Libtask optional. That would allow us to support Julias 1.6 again. I merged this PR because it's better to decouple from Libtask in a separate PR.

@torfjelde
Copy link
Member

torfjelde commented Dec 9, 2022 via email

@torfjelde
Copy link
Member

Do we have any updates on this? There are people asking in the slack channel regarding why we dropped support for 1.6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants