Skip to content

Commit

Permalink
Merge branch 'master' into save_gradient
Browse files Browse the repository at this point in the history
  • Loading branch information
yebai authored Nov 1, 2024
2 parents 5436cc6 + 5d56902 commit 912c25b
Show file tree
Hide file tree
Showing 26 changed files with 464 additions and 163 deletions.
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/" # Location of package manifests
schedule:
interval: "monthly"
37 changes: 18 additions & 19 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,41 @@ on:
- master
pull_request:

concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

jobs:
test:
# needed to allow julia-actions/cache to delete old caches that it has created
permissions:
actions: write
contents: read
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.version == 'nightly' }}
continue-on-error: ${{ matrix.version == 'pre' }}
strategy:
matrix:
version:
- '1.6'
- 'min'
- '1'
- 'nightly'
- 'pre'
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x86
- x64
exclude:
- os: ubuntu-latest
arch: x86
- os: macOS-latest
arch: x86
- os: windows-latest
arch: x86
# GitHub Action seems to have issue of running julia-nightly with windows-latest
# TODO Revisit in the future
- version: 'nightly'
os: windows-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- name: Run tests
uses: julia-actions/julia-runtest@latest
uses: julia-actions/julia-runtest@v1
env:
AHMC_TEST_GROUP: AdvancedHMC
49 changes: 49 additions & 0 deletions .github/workflows/DocsNav.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Add Navbar

on:
page_build: # Triggers the workflow on push events to gh-pages branch
workflow_dispatch: # Allows manual triggering
schedule:
- cron: '0 0 * * 0' # Runs every week on Sunday at midnight (UTC)

jobs:
add-navbar:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout gh-pages
uses: actions/checkout@v4
with:
ref: gh-pages
fetch-depth: 0

- name: Download insert_navbar.sh
run: |
curl -O https://raw.githubusercontent.com/TuringLang/turinglang.github.io/main/assets/scripts/insert_navbar.sh
chmod +x insert_navbar.sh
- name: Update Navbar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config user.name github-actions[bot]
git config user.email github-actions[bot]@users.noreply.github.com
# Define the URL of the navbar to be used
NAVBAR_URL="https://raw.githubusercontent.com/TuringLang/turinglang.github.io/main/assets/scripts/TuringNavbar.html"
# Update all HTML files in the current directory (gh-pages root)
./insert_navbar.sh . $NAVBAR_URL
# Remove the insert_navbar.sh file
rm insert_navbar.sh
# Check if there are any changes
if [[ -n $(git status -s) ]]; then
git add .
git commit -m "Added navbar and removed insert_navbar.sh"
git push "https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" gh-pages
else
echo "No changes to commit"
fi
27 changes: 15 additions & 12 deletions .github/workflows/ExperimentalTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@ on:
- master
pull_request:

concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

jobs:
test:
# needed to allow julia-actions/cache to delete old caches that it has created
permissions:
actions: write
contents: read
runs-on: ${{ matrix.os }}
strategy:
matrix:
Expand All @@ -18,23 +28,16 @@ jobs:
- macOS-latest
- windows-latest
arch:
- x86
- x64
exclude:
- os: ubuntu-latest
arch: x86
- os: macOS-latest
arch: x86
- os: windows-latest
arch: x86
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- name: Run integration tests
uses: julia-actions/julia-runtest@latest
uses: julia-actions/julia-runtest@v1
env:
AHMC_TEST_GROUP: Experimental
5 changes: 2 additions & 3 deletions .github/workflows/Format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ on:
push:
branches:
- master
- main

concurrency:
# Skip intermediate builds: always.
Expand All @@ -17,8 +16,8 @@ jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: 1
- name: Format code
Expand Down
27 changes: 15 additions & 12 deletions .github/workflows/IntegrationTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@ on:
- master
pull_request:

concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

jobs:
test:
# needed to allow julia-actions/cache to delete old caches that it has created
permissions:
actions: write
contents: read
runs-on: ${{ matrix.os }}
strategy:
matrix:
Expand All @@ -18,23 +28,16 @@ jobs:
- macOS-latest
- windows-latest
arch:
- x86
- x64
exclude:
- os: ubuntu-latest
arch: x86
- os: macOS-latest
arch: x86
- os: windows-latest
arch: x86
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- name: Run integration tests
uses: julia-actions/julia-runtest@latest
uses: julia-actions/julia-runtest@v1
env:
AHMC_TEST_GROUP: Downstream
9 changes: 5 additions & 4 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ on:

jobs:
build:
permissions:
statuses: write # Used to report documentation build statuses
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: '1.7'
version: '1'
- name: Install dependencies
run: julia --project=docs/ -e '
using Pkg;
Expand All @@ -24,4 +26,3 @@ jobs:
env:
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # If authenticating with SSH deploy key
run: julia --project=docs/ docs/make.jl

31 changes: 17 additions & 14 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "AdvancedHMC"
uuid = "0bf59076-c3b1-5ca4-86bd-e02cd72cde3d"
version = "0.5.5"
version = "0.6.3"

[deps]
AbstractMCMC = "80f14c24-f653-4e6a-9b94-39d6b0f70001"
Expand All @@ -19,10 +19,20 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"

[weakdeps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"

[extensions]
AdvancedHMCCUDAExt = "CUDA"
AdvancedHMCMCMCChainsExt = "MCMCChains"
AdvancedHMCOrdinaryDiffEqExt = "OrdinaryDiffEq"

[compat]
AbstractMCMC = "4.2"
AbstractMCMC = "5.6"
ArgCheck = "1, 2"
CUDA = "3, 4"
CUDA = "3, 4, 5"
DocStringExtensions = "0.8, 0.9"
InplaceOps = "0.3"
LogDensityProblems = "2"
Expand All @@ -33,21 +43,14 @@ ProgressMeter = "1"
Requires = "0.5, 1"
Setfield = "0.7, 0.8, 1"
SimpleUnPack = "1.1"
Statistics = "1.6"
StatsBase = "0.31, 0.32, 0.33, 0.34"
StatsFuns = "0.8, 0.9, 1"
julia = "1.6"

[extensions]
AdvancedHMCCUDAExt = "CUDA"
AdvancedHMCMCMCChainsExt = "MCMCChains"
AdvancedHMCOrdinaryDiffEqExt = "OrdinaryDiffEq"
LinearAlgebra = "1.6"
Random = "1.6"
julia = "1.6.7"

[extras]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"

[weakdeps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
34 changes: 14 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,11 @@ If you are interested in using AdvancedHMC.jl through a probabilistic programmin

This section demonstrates a minimal example of sampling from a multivariate Gaussian (10-dimensional) using the no U-turn sampler (NUTS). Below we describe the major components of the Hamiltonian system which are essential to sample using this approach:

- **Metric**: In many sampling problems the sample space is usually associated with a metric that allows us to measure the distance between any two points, and other similar quantities. In the example in this section, we use a special metric called the **Euclidean Metric**, represented with a `D × D` matrix from which we can compute distances.
<details>
<summary>Further details about the Metric component</summary>
The Euclidean metric is also known as the mass matrix in the physical perspective. For available metrics refer <a href="#hamiltonian-mass-matrix-metric">Hamiltonian mass matrix</a>.
</details>

- **Leapfrog integration**: Leapfrog integration is a second-order numerical method for integrating differential equations (In this case they are equations of motion for the relative position of one particle with respect to the other). The order of this integration signifies its rate of convergence. Any algorithm with a finite time step size will have numerical errors, and the order is related to this error. For a second-order algorithm, this error scales as the second power of the time step, hence, the name second-order. High-order integrators are usually complex to code and have a limited region of convergence; hence they do not allow arbitrarily large time steps. A second-order integrator is suitable for our purpose. Hence we opt for the leapfrog integrator. It is called `leapfrog` due to the ways this algorithm is written, where the positions and velocities of particles `leap over` each other.
<details>
<summary>About the leapfrog integration scheme</summary>
Suppose ${\bf x}$ and ${\bf v}$ are the position and velocity of an individual particle respectively; $i$ and $i+1$ are the indices for time values $t_i$ and $t_{i+1}$ respectively; $dt = t_{i+1} - t_i$ is the time step size (constant and regularly spaced intervals), and ${\bf a}$ is the acceleration induced on a particle by the forces of all other particles. Furthermore, suppose positions are defined at times $t_i, t_{i+1}, t_{i+2}, \dots $, spaced at constant intervals $dt$, the velocities are defined at halfway times in between, denoted by $t_{i-1/2}, t_{i+1/2}, t_{i+3/2}, \dots $, where $t_{i+1} - t_{i + 1/2} = t_{i + 1/2} - t_i = dt / 2$, and the accelerations ${\bf a}$ are defined only on integer times, just like the positions. Then the leapfrog integration scheme is given as: $x_{i} = x_{i-1} + v_{i-1/2} dt; \quad v_{i+1/2} = v_{i-1/2} + a_i dt$. For available integrators refer <a href="#integrator-integrator">Integrator</a>.
</details>

- **Kernel for trajectories (static or dynamic)**: Different kernels, which may be static or dynamic, can be used. At each iteration of any variant of the HMC algorithm, there are two main steps - the first step changes the momentum and the second step may change both the position and the momentum of a particle.
<details>
<summary>More about the kernels</summary>
In the classical HMC approach, during the first step, new values for the momentum variables are randomly drawn from their Gaussian distribution, independently of the current values of the position variables. A Metropolis update is performed during the second step, using Hamiltonian dynamics to provide a new state. For available kernels refer <a href="#kernel-kernel">kernel</a>.
</details>
- **Metric**: In many sampling problems the sample space is associated with a metric that allows us to measure the distance between any two points, and other similar quantities. In the example in this section, we use a special metric called the **Euclidean Metric**, represented with a `D × D` matrix from which we can compute distances.[^1]

- **Leapfrog integration**: Leapfrog integration is a second-order numerical method for integrating differential equations (In this case they are equations of motion for the relative position of one particle with respect to the other). The order of this integration signifies its rate of convergence. Any algorithm with a finite time step size will have numerical errors, and the order is related to this error. For a second-order algorithm, this error scales as the second power of the time step, hence, the name second-order. High-order integrators are usually complex to code and have a limited region of convergence; hence they do not allow arbitrarily large time steps. A second-order integrator is suitable for our purpose. Hence we opt for the leapfrog integrator. It is called `leapfrog` due to the ways this algorithm is written, where the positions and velocities of particles "leap over" each other.[^2]

- **Kernel for trajectories (static or dynamic)**: Different kernels, which may be static or dynamic, can be used. At each iteration of any variant of the HMC algorithm, there are two main steps - the first step changes the momentum and the second step may change both the position and the momentum of a particle.[^3]

```julia
using AdvancedHMC, ForwardDiff
Expand Down Expand Up @@ -97,7 +85,7 @@ samples, stats = sample(hamiltonian, kernel, initial_θ, n_samples, adaptor, n_a
### Parallel sampling

AdvancedHMC enables parallel sampling (either distributed or multi-thread) via Julia's [parallel computing functions](https://docs.julialang.org/en/v1/manual/parallel-computing/).
It also supports vectorized sampling for static HMC and has been discussed in more detail in the documentation [here](https://turinglang.github.io/AdvancedHMC.jl/stable/#Parallel-sampling).
It also supports vectorized sampling for static HMC.

The below example utilizes the `@threads` macro to sample 4 chains across 4 threads.

Expand Down Expand Up @@ -140,8 +128,8 @@ samples = AbstractMCMC.sample(
model,
sampler,
n_adapts + n_samples;
nadapts = n_adapts,
init_params = initial_θ,
n_adapts = n_adapts,
initial_params = initial_θ,
)
```

Expand Down Expand Up @@ -359,3 +347,9 @@ with the following BibTeX entry:
5. Betancourt, M. (2016). Identifying the optimal integration time in Hamiltonian Monte Carlo. [arXiv preprint arXiv:1601.00225](https://arxiv.org/abs/1601.00225).

6. Hoffman, M. D., & Gelman, A. (2014). The No-U-Turn Sampler: adaptively setting path lengths in Hamiltonian Monte Carlo. Journal of Machine Learning Research, 15(1), 1593-1623. ([arXiv](http://arxiv.org/abs/1111.4246))

## Footnotes

[^1]: The Euclidean metric is also known as the mass matrix in the physical perspective. See [Hamiltonian mass matrix](#Hamiltonian-mass-matrix-(metric)) for available metrics.
[^2]: About the leapfrog integration scheme: Suppose ${\bf x}$ and ${\bf v}$ are the position and velocity of an individual particle respectively; $i$ and $i+1$ are the indices for time values $t_i$ and $t_{i+1}$ respectively; $dt = t_{i+1} - t_i$ is the time step size (constant and regularly spaced intervals), and ${\bf a}$ is the acceleration induced on a particle by the forces of all other particles. Furthermore, suppose positions are defined at times $t_i, t_{i+1}, t_{i+2}, \dots $, spaced at constant intervals $dt$, the velocities are defined at halfway times in between, denoted by $t_{i-1/2}, t_{i+1/2}, t_{i+3/2}, \dots $, where $t_{i+1} - t_{i + 1/2} = t_{i + 1/2} - t_i = dt / 2$, and the accelerations ${\bf a}$ are defined only on integer times, just like the positions. Then the leapfrog integration scheme is given as: $x_{i} = x_{i-1} + v_{i-1/2} dt; \quad v_{i+1/2} = v_{i-1/2} + a_i dt$. For available integrators refer to [Integrator](#Integrator-(integrator)).
[^3]: On kernels: In the classical HMC approach, during the first step, new values for the momentum variables are randomly drawn from their Gaussian distribution, independently of the current values of the position variables. A Metropolis update is performed during the second step, using Hamiltonian dynamics to provide a new state. For available kernels refer to [Kernel](#Kernel-(kernel)).
6 changes: 5 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ using AdvancedHMC

# cp(joinpath(@__DIR__, "../README.md"), joinpath(@__DIR__, "src/index.md"))

makedocs(sitename = "AdvancedHMC", format = Documenter.HTML(), modules = [AdvancedHMC])
makedocs(
sitename = "AdvancedHMC",
format = Documenter.HTML(),
warnonly = [:cross_references],
)

deploydocs(
repo = "github.com/TuringLang/AdvancedHMC.jl.git",
Expand Down
Loading

0 comments on commit 912c25b

Please sign in to comment.