https://github.com/topipa/iwmm
iwmm: an R package for adaptive importance sampling
https://github.com/topipa/iwmm
bayesian bayesian-data-analysis bayesian-methods r r-package stan
Last synced: 10 months ago
JSON representation
iwmm: an R package for adaptive importance sampling
- Host: GitHub
- URL: https://github.com/topipa/iwmm
- Owner: topipa
- Created: 2020-12-01T11:28:17.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2024-09-08T15:52:37.000Z (over 1 year ago)
- Last Synced: 2024-09-09T14:12:37.849Z (over 1 year ago)
- Topics: bayesian, bayesian-data-analysis, bayesian-methods, r, r-package, stan
- Language: R
- Homepage:
- Size: 505 KB
- Stars: 4
- Watchers: 1
- Forks: 2
- Open Issues: 4
-
Metadata Files:
- Readme: README.Rmd
- Contributing: .github/CONTRIBUTING.md
Awesome Lists containing this project
README
---
output: github_document
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```

# iwmm
[](https://www.tidyverse.org/lifecycle/#experimental)
[](https://CRAN.R-project.org/package=iwmm)
[](https://github.com/topipa/iwmm/actions/workflows/R-CMD-check.yaml)
[](https://github.com/topipa/iwmm/actions/workflows/test-coverage.yaml)
## Overview
**IWMM** is an R package for adaptive importance sampling. The package implements the
importance weighted moment matching (IWMM) algorithm.
Given draws from a probability distribution, IWMM adapts the draws based on a given target distribution and an optional
expectation function. The draws can, but do not have to be from the distribution over which the expectation is defined.
The method is described in detail in the [Implicitly Adaptive Importance Sampling](https://doi.org/10.1007/s11222-020-09982-2) paper.
## Installation
You can install the the development version from [GitHub](https://github.com/) with:
```{r, eval = F}
install.packages("remotes")
remotes::install_github("topipa/iwmm")
```
## Usage
IWMM takes a sample of draws, and functions that define the proposal and target distributions, as well as an optional
expectation function. Without an expectation function, the draws are adapted to match the proposal distribution.
If an expectation function is given, the expectation is computed after adapting the draws specifically for this expectation.
IWMM can also work with models fitted with [rstan](https://github.com/stan-dev/rstan) or [cmdstanr](https://github.com/stan-dev/cmdstanr)
where the fitted model posterior is treated as the proposal distribution.
### Example
Consider a simple univariate normal model (available
via `example_iwmm_model("normal_model")`):
```{stan, eval = F, output.var = "stanmod"}
data {
int N;
vector[N] x;
}
parameters {
real mu;
real log_sigma;
}
transformed parameters {
real sigma = exp(log_sigma);
}
model {
target += normal_lpdf(x | mu, sigma);
}
```
We first fit the model using Stan:
```{r, eval = T, cache=T, results='hide'}
library("iwmm")
normal_model <- example_iwmm_model("normal_model")
fit <- rstan::stan(
model_code = normal_model$model_code,
data = normal_model$data,
refresh = FALSE,
seed = 1234
)
```
After fitting the model, let us define an expectation function that we are interested in,
and compute the expectation:
```{r, eval = T}
expectation_fun_first_moment <- function(draws, ...) {
draws
}
first_moment <- moment_match(
fit,
expectation_fun = expectation_fun_first_moment
)
```
We can check that the expectation matches the posterior mean
```{r, eval = T}
first_moment$expectation
colMeans(as.matrix(fit))[c("mu", "log_sigma")]
```
The package can also compute expectations over distributions
that are different than the one where the draws are from.
Let us try to evaluate the posterior mean when the last observation is removed.
We achieve this by defining a `target_observation_weights`
which we can use to indicate the target distribution as a vector of weights
for each observation in the data used to fit the model.
A vector of ones means using the existing data.
A zero value for some observation means that
the target distribution is the posterior without that specific observation.
```{r, eval = T}
first_moment_loo <- moment_match(
fit,
target_observation_weights = append(rep(1, 9), 0),
expectation_fun = expectation_fun_first_moment
)
```
Let us compare this to the posterior mean we get by actually fitting the model again without
the last observation.
```{r, eval = T, cache=T, results='hide'}
loo_data <- normal_model$data
loo_data$x <- loo_data$x[-loo_data$N]
loo_data$N <- loo_data$N - 1
fit_loo <- rstan::stan(
model_code = normal_model$model_code,
data = loo_data,
refresh = FALSE,
seed = 1234
)
```
```{r, eval = T}
first_moment_loo$expectation
colMeans(as.matrix(fit_loo))[c("mu", "log_sigma")]
```
## References
Paananen, T., Piironen, J., Bürkner, P.-C., and Vehtari, A.
Implicitly Adaptive Importance Sampling. _Stat Comput_ **31**, 16 (2021).
([paper](https://doi.org/10.1007/s11222-020-09982-2))([code](https://github.com/topipa/iter-mm-paper))