Skip to content

Commit 7b261ae

Browse files
authored
Tweak default max_proposals limit (#16)
* tweak default max proposal limit and improve max proposal error msg * fix docs move infos and warnings for `GibbsPolarSlice` to docstring * bump setup-julia action version
1 parent 48059bc commit 7b261ae

File tree

9 files changed

+42
-31
lines changed

9 files changed

+42
-31
lines changed

.github/workflows/CI.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
matrix:
2121
version:
2222
- '1'
23-
- '1.10'
23+
- 'lts'
2424
os:
2525
- ubuntu-latest
2626
- macOS-latest
@@ -29,7 +29,7 @@ jobs:
2929
- x64
3030
steps:
3131
- uses: actions/checkout@v4
32-
- uses: julia-actions/setup-julia@v1
32+
- uses: julia-actions/setup-julia@v2
3333
with:
3434
version: ${{ matrix.version }}
3535
arch: ${{ matrix.arch }}

docs/src/gibbs_polar.md

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ Unlike other slice sampling algorithms, it operates a Gibbs sampler over polar c
88
Due to the involvement of polar coordinates, GPSS only works reliably on more than one dimension.
99
However, unlike ESS, GPSS is applicable to any target distribution.
1010

11-
1211
## Description
1312
For a $$d$$-dimensional target distribution $$\pi$$, GPSS utilizes the following augmented target distribution:
1413
```math
@@ -34,26 +33,19 @@ The Gibbs steps on $$\theta$$ and $$r$$ are implemented through specialized shri
3433

3534
The only tunable parameter of the algorithm is the size of the search interval (window) of the shrinkage sampler for the radius variable $$r$$.
3635

36+
!!! warning
37+
A limitation of the current implementation of GPSS is that the acceptance rate exhibits a heavy tail. That is, occasionally, a single transition might take an excessive amount of time.
38+
3739
!!! info
3840
The kernel corresponding to this sampler is defined on an **augmented state space** and cannot directly perform a transition on $$x$$.
3941
This also means that the corresponding kernel is not reversible with respect to $$x$$.
4042

4143
## Interface
4244

43-
!!! info
44-
By the nature of polar coordinates, GPSS only works reliably for targets with dimension at least $$d \geq 2$$.
45-
4645
```@docs
4746
GibbsPolarSlice
4847
```
4948

50-
!!! warning
51-
When initializing the chain (*e.g.* the `initial_params` keyword arguments in `AbstractMCMC.sample`), it is necessary to inialize from a point $$x_0$$ that has a sensible norm $$\lVert x_0 \rVert > 0$$, otherwise, the chain will start from a pathologic point in polar coordinates. This might even result in the sampler getting stuck in an infinite loop. (This can be prevented by setting `max_proposals`.) If $$\lVert x_0 \rVert \leq 10^{-5}$$, the current implementation will display a warning.
52-
53-
!!! info
54-
For Turing users: `Turing` might change `initial_params` to match the support of the posterior. This might lead to $$\lVert x_0 \rVert$$ being small, even though the vector you passed to`initial_params` has a sufficiently large norm. If this is suspected, simply try a different initialization value.
55-
56-
5749
## Demonstration
5850
As illustrated in the original paper, GPSS shows good performance on heavy-tailed targets despite being a multivariate slice sampler.
5951
Consider a 10-dimensional Student-$$t$$ target with 1-degree of freedom (this corresponds to a multivariate Cauchy):

src/SliceSampling.jl

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export sample, MCMCThreads, MCMCDistributed, MCMCSerial
2020
# Interfaces
2121
abstract type AbstractSliceSampling <: AbstractMCMC.AbstractSampler end
2222

23+
const DEFAULT_MAX_PROPOSALS = 10_000
24+
2325
"""
2426
struct Transition
2527
@@ -52,10 +54,9 @@ Return the initial sample for the `model` using the random number generator `rng
5254
"""
5355
function initial_sample(::Random.AbstractRNG, ::Any)
5456
error(
55-
"`initial_sample` is not implemented but an initialization wasn't provided. " *
57+
"`initial_sample` is not implemented but an initialization wasn't provided. ",
5658
"Consider supplying an initialization to `initial_params`."
5759
)
58-
println("fuck!!!")
5960
end
6061

6162
# If target is from `LogDensityProblemsAD`, unwrap target before calling `initial_sample`.
@@ -66,10 +67,16 @@ initial_sample(
6667
) = initial_sample(rng, parent(wrap))
6768

6869
function exceeded_max_prop(max_prop::Int)
69-
error("Exceeded maximum number of proposal $(max_prop).\n",
70-
"Here are possible causes:\n",
71-
"- The model might be broken or pathologic.\n",
72-
"- There might be a bug in the sampler.")
70+
error("Exceeded maximum number of proposal $(max_prop), ",
71+
"which indicates an acceptance rate less than $(1/max_prop*100)%. ",
72+
"A quick fix is to increase `max_prop`, ",
73+
"but an acceptance rate that is too low often indicates that there is a problem. ",
74+
"Here are some possible causes:\n",
75+
"- The model might be broken or degenerate (most likely cause).\n",
76+
"- The tunable parameters of the sampler are suboptimal.\n",
77+
"- The initialization is pathologic. (try supplying a (different) `initial_params`)\n",
78+
"- There might be a bug in the sampler. (if this is suspected, file an issue to `SliceSampling`)\n"
79+
)
7380
end
7481

7582
## Univariate Slice Sampling Algorithms

src/multivariate/gibbspolar.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,26 @@ Gibbsian polar slice sampling algorithm by P. Schär, M. Habeck, and D. Rudolf [
99
1010
# Keyword Arguments
1111
- `w::Real`: Initial window size for the radius shrinkage procedure
12-
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `typemax(Int)`).
12+
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `$(DEFAULT_MAX_PROPOSALS)`).
13+
14+
!!! info
15+
By the nature of polar coordinates, GPSS only works reliably for targets with dimension at least \$\$d \\geq 2\$\$.
16+
17+
!!! info
18+
The initial window size `w` must be set at least an order of magnitude larger than what is sensible for other slice samplers. Otherwise, a large number of rejections might be experienced.
19+
20+
!!! warning
21+
When initializing the chain (*e.g.* the `initial_params` keyword arguments in `AbstractMCMC.sample`), it is necessary to inialize from a point \$\$x_0\$\$ that has a sensible norm \$\$\\lVert x_0 \\rVert > 0\$\$, otherwise, the chain will start from a pathologic point in polar coordinates. This might even result in the sampler getting stuck in an infinite loop. (This can be prevented by setting `max_proposals`.) If \$\$\\lVert x_0 \\rVert \\leq 10^{-5}\$\$, the current implementation will display a warning.
22+
23+
!!! info
24+
For Turing users: `Turing` might change `initial_params` to match the support of the posterior. This might lead to \$\$\\lVert x_0 \\rVert\$\$ being small, even though the vector you passed to`initial_params` has a sufficiently large norm. If this is suspected, simply try a different initialization value.
1325
"""
1426
struct GibbsPolarSlice{W <: Real} <: AbstractMultivariateSliceSampling
1527
w::W
1628
max_proposals::Int
1729
end
1830

19-
GibbsPolarSlice(w::Real; max_proposals::Int = typemax(Int)) = GibbsPolarSlice(w, max_proposals)
31+
GibbsPolarSlice(w::Real; max_proposals::Int = DEFAULT_MAX_PROPOSALS) = GibbsPolarSlice(w, max_proposals)
2032

2133
struct GibbsPolarSliceState{T <: Transition, R <: Real, D <: AbstractVector}
2234
"Current [`Transition`](@ref)."

src/multivariate/latent.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ Latent slice sampling algorithm by Li and Walker[^LW2023].
88
- `beta::Real`: Beta parameter of the Gamma distribution of the auxiliary variables.
99
1010
# Keyword Arguments
11-
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `typemax(Int)`).
11+
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `$(DEFAULT_MAX_PROPOSALS)`).
1212
"""
1313
struct LatentSlice{B <: Real} <: AbstractMultivariateSliceSampling
1414
beta ::B
1515
max_proposals::Int
1616
end
1717

18-
function LatentSlice(beta::Real; max_proposals::Int = typemax(Int))
18+
function LatentSlice(beta::Real; max_proposals::Int = DEFAULT_MAX_PROPOSALS)
1919
@assert beta > 0 "Beta must be strictly positive"
2020
LatentSlice(beta, max_proposals)
2121
end

src/univariate/doublingout.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Univariate slice sampling by automatically adapting the initial interval through
99
1010
# Keyword Arguments
1111
- `max_doubling_out`: Maximum number of "doubling outs" (default: 8).
12-
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `typemax(Int)`).
12+
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `$(DEFAULT_MAX_PROPOSALS)`).
1313
"""
1414
struct SliceDoublingOut{W <: Real} <: AbstractUnivariateSliceSampling
1515
window ::W
@@ -20,7 +20,7 @@ end
2020
function SliceDoublingOut(
2121
window ::Real;
2222
max_doubling_out::Int = 8,
23-
max_proposals ::Int = typemax(Int),
23+
max_proposals ::Int = DEFAULT_MAX_PROPOSALS,
2424
)
2525
@assert window > 0
2626
SliceDoublingOut(window, max_doubling_out, max_proposals)

src/univariate/fixedinterval.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Univariate slice sampling with a fixed initial interval (Scheme 2 by Neal[^N2003
88
- `window::Real`: Proposal window.
99
1010
# Keyword Arguments
11-
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `typemax(Int)`).
11+
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `$(DEFAULT_MAX_PROPOSALS)`).
1212
"""
1313
struct Slice{W <: Real} <: AbstractUnivariateSliceSampling
1414
window ::W
@@ -17,7 +17,7 @@ end
1717

1818
function Slice(
1919
window ::Real;
20-
max_proposals::Int = typemax(Int),
20+
max_proposals::Int = DEFAULT_MAX_PROPOSALS,
2121
)
2222
@assert window > 0
2323
Slice(window, max_proposals)

src/univariate/steppingout.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Univariate slice sampling by automatically adapting the initial interval through
99
1010
# Keyword Arguments
1111
- `max_stepping_out::Int`: Maximum number of "stepping outs" (default: 32).
12-
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `typemax(Int)`).
12+
- `max_proposals::Int`: Maximum number of proposals allowed until throwing an error (default: `$(DEFAULT_MAX_PROPOSALS)`).
1313
"""
1414
struct SliceSteppingOut{W <: Real} <: AbstractUnivariateSliceSampling
1515
window ::W
@@ -20,7 +20,7 @@ end
2020
function SliceSteppingOut(
2121
window ::Real;
2222
max_stepping_out::Int = 32,
23-
max_proposals ::Int = typemax(Int),
23+
max_proposals ::Int = DEFAULT_MAX_PROPOSALS,
2424
)
2525
@assert window > 0
2626
SliceSteppingOut(window, max_stepping_out, max_proposals)

test/multivariate.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ end
7878
LatentSlice(5),
7979

8080
# Gibbsian polar slice sampling
81-
GibbsPolarSlice(10),
81+
GibbsPolarSlice(100),
8282
]
8383
@testset "initial_params" begin
8484
model = MultiModel(1.0, 1.0, [0.0])
@@ -87,7 +87,7 @@ end
8787

8888
θ0 = [1.0, 0.1]
8989
chain = sample(
90-
model,
90+
model,
9191
sampler,
9292
10;
9393
initial_params=θ0,

0 commit comments

Comments
 (0)