Skip to content

Commit 914f1a0

Browse files
authored
Merge branch 'main' into qqy/sghmc
2 parents 8db6408 + 316e3d9 commit 914f1a0

File tree

14 files changed

+96
-71
lines changed

14 files changed

+96
-71
lines changed

.github/workflows/Docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ concurrency:
1515

1616
permissions:
1717
contents: write
18-
pull-requests: read
18+
pull-requests: write
1919

2020
jobs:
2121
docs:

HISTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# AdvancedHMC Changelog
22

3+
## 0.8.0
4+
5+
- To make an MCMC transtion from phasepoint `z` using trajectory `τ`(or HMCKernel `κ`) under Hamiltonian `h`, use `transition(h, τ, z)` or `transition(rng, h, τ, z)`(if using HMCKernel, use `transition(h, κ, z)` or `transition(rng, h, κ, z)`).
6+
37
## v0.7.1
48

59
- README has been simplified, many docs transfered to docs: https://turinglang.org/AdvancedHMC.jl/dev/.

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "AdvancedHMC"
22
uuid = "0bf59076-c3b1-5ca4-86bd-e02cd72cde3d"
3-
version = "0.7.1"
3+
version = "0.8.0"
44

55
[deps]
66
AbstractMCMC = "80f14c24-f653-4e6a-9b94-39d6b0f70001"

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
44
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
55

66
[compat]
7-
AdvancedHMC = "0.7"
7+
AdvancedHMC = "0.8"
88
Documenter = "1"
99
DocumenterCitations = "1"

research/src/riemannian_hmc_utility.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
using Random, LinearAlgebra, ReverseDiff, ForwardDiff, VecTargets
1+
using Random, LinearAlgebra, ReverseDiff, ForwardDiff, MCMCLogDensityProblems
22

33
# Fisher information metric
44
function gen_∂G∂θ_rev(Vfunc, x; f=identity)
5-
_Hfunc = VecTargets.gen_hess(Vfunc, ReverseDiff.track.(x))
5+
_Hfunc = MCMCLogDensityProblems.gen_hess(Vfunc, ReverseDiff.track.(x))
66
Hfunc = x -> _Hfunc(x)[3]
77
# QUES What's the best output format of this function?
88
return x -> ReverseDiff.jacobian(x -> f(Hfunc(x)), x) # default output shape [∂H∂x₁; ∂H∂x₂; ...]
@@ -37,7 +37,7 @@ end
3737

3838
function prepare_sample_target(hps, θ₀, ℓπ)
3939
Vfunc = x -> -ℓπ(x) # potential energy is the negative log-probability
40-
_Hfunc = VecTargets.gen_hess(Vfunc, θ₀) # x -> (value, gradient, hessian)
40+
_Hfunc = MCMCLogDensityProblems.gen_hess(Vfunc, θ₀) # x -> (value, gradient, hessian)
4141
Hfunc = x -> copy.(_Hfunc(x)) # _Hfunc do in-place computation, copy to avoid bug
4242

4343
fstabilize = H -> H + hps.λ * I
@@ -70,8 +70,8 @@ function prepare_sample(hps; rng=MersenneTwister(1110))
7070

7171
θ₀ = rand(rng, dim(target))
7272

73-
ℓπ = VecTargets.gen_logpdf(target)
74-
∂ℓπ∂θ = VecTargets.gen_logpdf_grad(target, θ₀)
73+
ℓπ = MCMCLogDensityProblems.gen_logpdf(target)
74+
∂ℓπ∂θ = MCMCLogDensityProblems.gen_logpdf_grad(target, θ₀)
7575

7676
_, _, Gfunc, ∂G∂θfunc = prepare_sample_target(hps, θ₀, ℓπ)
7777

research/tests/runtests.jl

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
using Comonicon, ReTest
22

3-
using Pkg;
4-
Pkg.add(; url="https://github.com/xukai92/VecTargets.jl.git");
5-
63
# include the source code for experimental HMC
74
include("../src/relativistic_hmc.jl")
8-
include("../src/riemannian_hmc.jl")
95

106
# include the tests for experimental HMC
117
include("relativistic_hmc.jl")
12-
include("riemannian_hmc.jl")
138

149
Comonicon.@main function runtests(patterns...; dry::Bool=false)
1510
return retest(patterns...; dry=dry, verbose=Inf)
File renamed without changes.

src/sampler.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ function transition(
5454
(; refreshment, τ) = κ
5555
@set! τ.integrator = jitter(rng, τ.integrator)
5656
z = refresh(rng, refreshment, h, z)
57-
return transition(rng, τ, h, z)
57+
return transition(rng, h, τ, z)
5858
end
5959

6060
function Adaptation.adapt!(

src/trajectory.jl

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,10 @@ $(SIGNATURES)
244244
245245
Make a MCMC transition from phase point `z` using the trajectory `τ` under Hamiltonian `h`.
246246
247-
NOTE: This is a RNG-implicit fallback function for `transition(Random.default_rng(), τ, h, z)`
247+
NOTE: This is a RNG-implicit fallback function for `transition(Random.default_rng(), h, τ, z)`
248248
"""
249-
function transition(τ::Trajectory, h::Hamiltonian, z::PhasePoint)
250-
return transition(Random.default_rng(), τ, h, z)
249+
function transition(h::Hamiltonian, τ::Trajectory, z::PhasePoint)
250+
return transition(Random.default_rng(), h, τ, z)
251251
end
252252

253253
###
@@ -256,8 +256,8 @@ end
256256

257257
function transition(
258258
rng::Union{AbstractRNG,AbstractVector{<:AbstractRNG}},
259-
τ::Trajectory{TS,I,TC},
260259
h::Hamiltonian,
260+
τ::Trajectory{TS,I,TC},
261261
z::PhasePoint,
262262
) where {TS<:AbstractTrajectorySampler,I,TC<:StaticTerminationCriterion}
263263
H0 = energy(z)
@@ -665,7 +665,7 @@ function build_tree(
665665
end
666666

667667
function transition(
668-
rng::AbstractRNG, τ::Trajectory{TS,I,TC}, h::Hamiltonian, z0::PhasePoint
668+
rng::AbstractRNG, h::Hamiltonian, τ::Trajectory{TS,I,TC}, z0::PhasePoint
669669
) where {
670670
TS<:AbstractTrajectorySampler,I<:AbstractIntegrator,TC<:DynamicTerminationCriterion
671671
}
@@ -746,12 +746,24 @@ function A(h, z, ϵ)
746746
return z′, H′
747747
end
748748

749-
"Find a good initial leap-frog step-size via heuristic search."
749+
"""
750+
find_good_stepsize(h::Hamiltonian, θ::AbstractVector; initial_step_size = 1//10, max_n_iters::Int=100)
751+
find_good_stepsize(rng::AbstractRNG, h::Hamiltonian, θ::AbstractVector; initial_step_size = 1//10, max_n_iters::Int=100)
752+
753+
Find a good initial leap-frog step-size via heuristic search.
754+
755+
- `initial_step_size`: Custom initial step size, default as 1//10
756+
- `max_n_iters`: Maximum number of iteration for searching a good step-size, default as 100
757+
"""
750758
function find_good_stepsize(
751-
rng::AbstractRNG, h::Hamiltonian, θ::AbstractVector{T}; max_n_iters::Int=100
759+
rng::AbstractRNG,
760+
h::Hamiltonian,
761+
θ::AbstractVector{T};
762+
initial_step_size=1//10,
763+
max_n_iters::Int=100,
752764
) where {T<:Real}
753765
# Initialize searching parameters
754-
ϵ′ = ϵ = T(1//10)
766+
ϵ′ = ϵ = T(initial_step_size)
755767
# minimal, crossing, maximal log accept ratio
756768
log_a_min = 2 * T(loghalf)
757769
log_a_cross = T(loghalf)
@@ -815,9 +827,18 @@ function find_good_stepsize(
815827
end
816828

817829
function find_good_stepsize(
818-
h::Hamiltonian, θ::AbstractVector{<:AbstractFloat}; max_n_iters::Int=100
830+
h::Hamiltonian,
831+
θ::AbstractVector{<:AbstractFloat};
832+
initial_step_size=1//10,
833+
max_n_iters::Int=100,
819834
)
820-
return find_good_stepsize(Random.default_rng(), h, θ; max_n_iters=max_n_iters)
835+
return find_good_stepsize(
836+
Random.default_rng(),
837+
h,
838+
θ;
839+
initial_step_size=initial_step_size,
840+
max_n_iters=max_n_iters,
841+
)
821842
end
822843

823844
"Perform MH acceptance based on energy, i.e. negative log probability."

test/CUDA/cuda.jl

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,59 @@ using Pkg
22
Pkg.activate(@__DIR__)
33
Pkg.develop(; path=joinpath(@__DIR__, "..", ".."))
44

5-
include(joinpath(@__DIR__, "..", "common.jl"))
6-
75
using Test
86
using AdvancedHMC
97
using AdvancedHMC: DualValue, PhasePoint
108
using CUDA
9+
using LogDensityProblems
1110

12-
@testset "AdvancedHMC GPU" begin
13-
n_chains = 1000
14-
n_samples = 1000
15-
dim = 5
16-
17-
T = Float32
18-
m, s, θ₀ = zeros(T, dim), ones(T, dim), rand(T, dim, n_chains)
19-
m, s, θ₀ = CuArray(m), CuArray(s), CuArray(θ₀)
20-
21-
target = Gaussian(m, s)
22-
metric = UnitEuclideanMetric(T, size(θ₀))
23-
ℓπ, ∇ℓπ = get_ℓπ(target), get_∇ℓπ(target)
24-
hamiltonian = Hamiltonian(metric, ℓπ, ∇ℓπ)
25-
integrator = Leapfrog(one(T) / 5)
26-
proposal = HMCKernel(Trajectory{EndPointTS}(integrator, FixedNSteps(5)))
11+
include(joinpath(@__DIR__, "..", "common.jl"))
2712

28-
samples, stats = sample(hamiltonian, proposal, θ₀, n_samples)
13+
@testset "AdvancedHMC GPU" begin
14+
if CUDA.functional()
15+
n_chains = 1000
16+
n_samples = 1000
17+
dim = 5
18+
T = Float32
19+
m, s, θ₀ = zeros(T, dim), ones(T, dim), rand(T, dim, n_chains)
20+
m, s, θ₀ = CuArray(m), CuArray(s), CuArray(θ₀)
21+
target = Gaussian(m, s)
22+
metric = UnitEuclideanMetric(T, size(θ₀))
23+
ℓπ, ∇ℓπ = get_ℓπ(target), get_∇ℓπ(target)
24+
hamiltonian = Hamiltonian(metric, ℓπ, ∇ℓπ)
25+
integrator = Leapfrog(one(T) / 5)
26+
proposal = HMCKernel(Trajectory{EndPointTS}(integrator, FixedNSteps(5)))
27+
samples, stats = sample(hamiltonian, proposal, θ₀, n_samples)
28+
else
29+
println("GPU tests are skipped because no CUDA devices are found.")
30+
end
2931
end
3032

3133
@testset "PhasePoint GPU" begin
32-
for T in [Float32, Float64]
33-
function init_z1()
34-
return PhasePoint(
35-
CuArray([T(NaN) T(NaN)]),
36-
CuArray([T(NaN) T(NaN)]),
37-
DualValue(CuArray(zeros(T, 2)), CuArray(zeros(T, 1, 2))),
38-
DualValue(CuArray(zeros(T, 2)), CuArray(zeros(T, 1, 2))),
39-
)
40-
end
41-
function init_z2()
42-
return PhasePoint(
43-
CuArray([T(Inf) T(Inf)]),
44-
CuArray([T(Inf) T(Inf)]),
45-
DualValue(CuArray(zeros(T, 2)), CuArray(zeros(T, 1, 2))),
46-
DualValue(CuArray(zeros(T, 2)), CuArray(zeros(T, 1, 2))),
47-
)
34+
if CUDA.functional()
35+
for T in [Float32, Float64]
36+
function init_z1()
37+
return PhasePoint(
38+
CuArray([T(NaN) T(NaN)]),
39+
CuArray([T(NaN) T(NaN)]),
40+
DualValue(CuArray(zeros(T, 2)), CuArray(zeros(T, 1, 2))),
41+
DualValue(CuArray(zeros(T, 2)), CuArray(zeros(T, 1, 2))),
42+
)
43+
end
44+
function init_z2()
45+
return PhasePoint(
46+
CuArray([T(Inf) T(Inf)]),
47+
CuArray([T(Inf) T(Inf)]),
48+
DualValue(CuArray(zeros(T, 2)), CuArray(zeros(T, 1, 2))),
49+
DualValue(CuArray(zeros(T, 2)), CuArray(zeros(T, 1, 2))),
50+
)
51+
end
52+
z1 = init_z1()
53+
z2 = init_z2()
54+
@test z1.ℓπ.value == z2.ℓπ.value
55+
@test z1.ℓκ.value == z2.ℓκ.value
4856
end
49-
50-
z1 = init_z1()
51-
z2 = init_z2()
52-
53-
@test z1.ℓπ.value == z2.ℓπ.value
54-
@test z1.ℓκ.value == z2.ℓκ.value
57+
else
58+
println("GPU tests are skipped because no CUDA devices are found.")
5559
end
5660
end

0 commit comments

Comments
 (0)