@@ -12,9 +12,13 @@ This package is useful for efficient sampling from log-concave univariate densit
1212## Examples
1313
1414``` julia
15- using AdaptiveRejectionSampling: Objective, ARSampler, sample!, eval_hull, abscissae
15+ # Import packages and setup
16+ using AdaptiveRejectionSampling: Objective, ARSampler, sample!, eval_hull, abscissae, hullplot!
1617using SpecialFunctions: gamma
1718using CairoMakie
19+ using Chairmarks
20+
21+ set_theme! (theme_minimal ())
1822```
1923
2024### Sampling from a shifted normal distribution
@@ -31,18 +35,18 @@ function bench()
3135 # Build the sampler and simulate 10,000 samples
3236 obj = Objective (f)
3337 sampler = ARSampler (obj, support)
34- b = @be deepcopy (sampler) sample! (_, 10000 , true , 10 );
38+ b = @be deepcopy (sampler) sample! (_, 10000 , max_segments = 10 );
3539return sampler, b
3640end
3741s, b = bench ();
3842b
3943```
4044
41- Benchmark: 126 samples with 1 evaluation
42- min 616.951 μs (17 allocs: 80.523 KiB)
43- median 641.532 μs (17 allocs: 80.523 KiB)
44- mean 749.812 μs (17.10 allocs: 80.625 KiB, 0.75% gc time )
45- max 13.744 ms (20 allocs: 83.711 KiB, 94.06% gc time )
45+ Benchmark: 166 samples with 1 evaluation
46+ min 535.050 μs (3 allocs: 78.195 KiB)
47+ median 565.130 μs (6 allocs: 81.852 KiB)
48+ mean 571.223 μs (5.73 allocs: 81.521 KiB)
49+ max 740.072 μs (6 allocs: 81.852 KiB)
4650
4751Let's verify the result
4852
@@ -55,15 +59,10 @@ envelop = eval_hull.(s.upper_hull, x)
5559target = f .(x)
5660samples = sample! (s, 10000 , max_segments = 5 )
5761
58- fig, ax, p = hist (samples, bins= 25 , normalization = :pdf , label = " Samples" );
59- lines! (ax, - 10 .. 10 , x -> exp (f (x)), label = " Target" , color = :orange )
60- lines! (ax, x, exp .(envelop), label = " Envelop" , color = :black , alpha = 0.8 )
61- absc = ARS. abscissae (s. upper_hull)
62- scatter! (ax, absc, exp .(eval_hull .(s. upper_hull, absc)), label = " Abscissae" , color = :red )
62+ fig, ax, p = hist (samples, bins= 25 , color = :grey , normalization = :pdf , label = " Samples" );
63+ hullplot! (ax, - 10 .. 10 , s, target = true )
6364axislegend (ax)
6465fig
65- # histogram(sim, normalize = true, label = "Histogram")
66- # plot!(x, [target envelop], width = 2, label = ["Normal(μ, σ)" "Envelop"])
6766```
6867
6968
@@ -80,25 +79,16 @@ support = (0.0, Inf)
8079
8180obj = Objective (x -> log (f (x)))
8281sam = ARSampler (obj, support)
83- @time sim = sample! (sam, 10000 , max_segments = 5 )
82+ sim = sample! (sam, 10000 , max_segments = 5 )
8483
8584# Verify result
86- x = range (0.0 , 8.0 , length= 100 )
87- envelop = eval_hull .(sam. upper_hull, x)
88- target = f .(x)
8985mx = maximum (sim)
90- fig, ax, p = hist (sim, bins= 50 , normalization = :pdf , label = " Samples" );
91- lines! (ax, 0 .. mx, y -> f (y), label = " Target" , color = :orange )
92- lines! (ax, 0 .. mx, y -> exp (eval_hull (sam. upper_hull, y)), label = " Envelop" , color = :black , alpha = 0.8 )
93- absc = abscissae (sam. upper_hull)
94- scatter! (ax, absc, exp .(eval_hull .(sam. upper_hull, absc)), label = " Abscissae" , color = :red )
86+ fig, ax, p = hist (sim, bins= 50 , color = :grey , normalization = :pdf , label = " Samples" );
87+ hullplot! (ax, 0 .. mx, sam, target = true )
9588axislegend (ax)
9689fig
9790```
9891
99- 0.000772 seconds (100 allocations: 85.211 KiB)
100-
101-
10292![ ] ( img/example2.svg )
10393
10494### Truncated distributions and unknown normalization constant
@@ -111,23 +101,18 @@ We don't to provide an exact density--it will sample up to proportionality--and
111101f (x) = β^ α * x^ (α- 1 ) * exp (- β* x) / gamma (α)
112102support = (1.0 , 3.5 )
113103
114- # Build the sampler and simulate 10,000 samples
115- sampler = RejectionSampler (f , support)
116- @time sim = run_sampler! (sampler , 10000 )
104+ obj = Objective (x -> log ( f (x)))
105+ sam = ARSampler (obj , support)
106+ sim = sample! (sam , 10000 , max_segments = 10 )
117107
118108# Plot the results and compare to target distribution
119- x = range (0.01 , 8.0 , length= 100 )
120- envelop = [eval_envelop (sampler. envelop, xi) for xi in x]
121- target = [f (xi) for xi in x]
122-
123- histogram (sim, normalize = true , label = " histogram" )
124- plot! (x, [target envelop], width = 2 , label = [" target density" " envelop" ])
109+ fig, ax, p = hist (sim, bins= 50 , color = :grey , normalization = :pdf , label = " Samples" );
110+ hullplot! (ax, 0.01 .. 8.0 , sam, target = true )
111+ axislegend (ax)
112+ fig
125113```
126114
127- 0.007766 seconds (181.82 k allocations: 3.024 MiB)
128-
129-
130- ![ ] ( img/example3.png )
115+ ![ ] ( img/example3.svg )
131116
132117### Elastic Net Distribution
133118
@@ -140,40 +125,22 @@ function f(x, μ, λ1, λ2)
140125 nl = λ1 * abs (δ) + λ2 * δ^ 2
141126 return exp (- nl)
142127end
143- support = (- Inf , Inf )
144128
145- # Build the sampler and simulate 10,000 samples
146- μ, λ1, λ2 = 0.0 , 2.0 , 1.0
147- sampler = RejectionSampler (x -> f (x, μ, λ1, λ2), support, max_segments = 5 )
148- @time sim = run_sampler! (sampler, 10000 );
149-
150- # Plot the results and compare to target distribution
151- x = range (- 2.3 , 2.3 , length= 100 )
152- envelop = [eval_envelop (sampler. envelop, xi) for xi in x]
153- target = [f (xi, μ, λ1, λ2) for xi in x]
129+ support = (- Inf , Inf )
130+ mu, L1, L2 = 0.0 , 2.0 , 1.0
131+ obj = Objective (x -> log (f (x, mu, L1, L2)))
132+ sam = ARSampler (obj, support)
133+ sim = sample! (sam, 10000 , max_segments = 10 )
154134
155- histogram (sim, normalize = true , label = " histogram" )
156- plot! (x, [target envelop], width = 2 , label = [" target density" " envelop" ])
135+ fig, ax, p = hist (sim, bins= 50 , color = :grey , normalization = :pdf , label = " Samples" );
136+ hullplot! (ax, - 3 .. 3 , sam, target = true )
137+ axislegend (ax)
138+ fig
157139```
158140
159- ![ ] ( img/example4.png )
160-
161- ### Tips for numerical stability, use of logdensity
162-
163- Here are some tips:
141+ ![ ] ( img/example4.svg )
164142
165- - Make sure the logdensity is numerically stable in the domain and avoid logdensity values > 25 (since
166- the evaluation of the envelop requires exponentials);
167- - Use log densities instead of densities using the keyword ` logdensity=true ` ;
168- - Specify a ` min_slope ` and ` max_slope ` to find better initial points. The default is 1e-6 and 1e6, respectively.
169- The ` min_slope ` is the minimum slope of the logdensity in the initial points of the envelop in absolute value. In general,
170- it is a good idea to leave ` min_slope ` with the default and try ` max_slope=10.0 ` or a smaller number.
171- - Try setting ` δ ` to a smaller value in the search_grid. The default is 0.5.
172-
173-
174- ⚠️ * Warning* ⚠️: Using ` logdensity=true ` will be the default in v1.0.
175-
176- Here is an example
143+ #### Example of more complicated density
177144
178145``` julia
179146import StatsFuns: logsumexp
@@ -185,36 +152,28 @@ theta = 1.0
185152
186153# a complicated logdensity
187154logf (v) = n * v - (n - k * alpha) * logsumexp ([v, log (tau)]) - theta / alpha * ( (tau + exp (v) )^ alpha )
155+ f (x) = exp (logf (x))
188156
189157# run sampler
190158δ = 0.1
191159support = (- Inf , Inf )
192160search = (0.0 , 10.0 )
193- sampler = RejectionSampler (logf, support, δ, max_segments = 10 , logdensity = true , search_range = search, max_slope = 10.0 )
194- @time sim = run_sampler! (sampler, 10000 )
195- ```
161+ obj = Objective (logf)
162+ sam = ARSampler (obj, support, search )
163+ sim = sample! (sam, 10000 , max_segments = 10 )
196164
197- ```
198- [ Info: initial points found at 1.08, 5.43 with grads 9.94522619043481, -9.98968199019509
199- 0.016296 seconds (371.21 k allocations: 6.850 MiB)
200- ```
201-
202-
203- ``` julia
204165x = range (0 , 10 , length= 200 )
205166normconst = sum (f .(x)) * (x[2 ] - x[1 ])
206- envelop = [eval_envelop (sampler. envelop, xi) for xi in x] ./ normconst
207- target = [f (xi) for xi in x] ./ normconst
208-
209- # make two plots of logf and f
210- p1 = plot (logf, - 20 , 20 , label = " logf" )
211- p2 = histogram (sim, normalize= true , label= " histogram" )
212- plot! (p2, x, [target envelop], width= 2 , label= [" target density" " envelop" ])
213167
214- plot (p1, p2, layout = (1 , 2 ))
168+ fig, ax, p = lines (- 20 .. 20 , logf);
169+ ax2 = Axis (fig[1 ,2 ])
170+ hist! (ax2, sim, bins= 50 , color = :grey , normalization = :pdf , label = " Samples" )
171+ hullplot! (ax2, 0 .. 10 , sam, target = true , normconst = 1 / normconst)
172+ axislegend (ax2)
173+ fig
215174```
216175
217- ![ ] ( img/example5.png )
176+ ![ ] ( img/example5.svg )
218177
219178## Citation
220179
@@ -223,7 +182,7 @@ plot(p1, p2, layout = (1, 2))
223182``` bibtex
224183@manual{tec2018ars,
225184 title = {AdaptiveRejectionSampling.jl},
226- author = {Mauricio Tec},
185+ author = {Mauricio Tec, Elias Sjölin },
227186 year = {2018},
228187 url = {https://github.com/mauriciogtec/AdaptiveRejectionSampling.jl}
229188}
0 commit comments