chore: import upstream snapshot with attribution
This commit is contained in:
+12
@@ -0,0 +1,12 @@
|
||||
from prml.sampling.metropolis import metropolis
|
||||
from prml.sampling.metropolis_hastings import metropolis_hastings
|
||||
from prml.sampling.rejection_sampling import rejection_sampling
|
||||
from prml.sampling.sir import sir
|
||||
|
||||
|
||||
__all__ = [
|
||||
"metropolis",
|
||||
"metropolis_hastings",
|
||||
"rejection_sampling",
|
||||
"sir"
|
||||
]
|
||||
@@ -0,0 +1,36 @@
|
||||
import random
|
||||
import numpy as np
|
||||
|
||||
|
||||
def metropolis(func, rv, n, downsample=1):
|
||||
"""
|
||||
Metropolis algorithm
|
||||
|
||||
Parameters
|
||||
----------
|
||||
func : callable
|
||||
(un)normalized distribution to be sampled from
|
||||
rv : RandomVariable
|
||||
proposal distribution which is symmetric at the origin
|
||||
n : int
|
||||
number of samples to draw
|
||||
downsample : int
|
||||
downsampling factor
|
||||
|
||||
Returns
|
||||
-------
|
||||
sample : (n, ndim) ndarray
|
||||
generated sample
|
||||
"""
|
||||
x = np.zeros((1, rv.ndim))
|
||||
sample = []
|
||||
for i in range(n * downsample):
|
||||
x_new = x + rv.draw()
|
||||
accept_proba = func(x_new) / func(x)
|
||||
if random.random() < accept_proba:
|
||||
x = x_new
|
||||
if i % downsample == 0:
|
||||
sample.append(x[0])
|
||||
sample = np.asarray(sample)
|
||||
assert sample.shape == (n, rv.ndim), sample.shape
|
||||
return sample
|
||||
@@ -0,0 +1,36 @@
|
||||
import random
|
||||
import numpy as np
|
||||
|
||||
|
||||
def metropolis_hastings(func, rv, n, downsample=1):
|
||||
"""
|
||||
Metropolis Hastings algorith
|
||||
|
||||
Parameters
|
||||
----------
|
||||
func : callable
|
||||
(un)normalized distribution to be sampled from
|
||||
rv : RandomVariable
|
||||
proposal distribution
|
||||
n : int
|
||||
number of samples to draw
|
||||
downsample : int
|
||||
downsampling factor
|
||||
|
||||
Returns
|
||||
-------
|
||||
sample : (n, ndim) ndarray
|
||||
generated sample
|
||||
"""
|
||||
x = np.zeros((1, rv.ndim))
|
||||
sample = []
|
||||
for i in range(n * downsample):
|
||||
x_new = x + rv.draw()
|
||||
accept_proba = func(x_new) * rv.pdf(x - x_new) / (func(x) * rv.pdf(x_new - x))
|
||||
if random.random() < accept_proba:
|
||||
x = x_new
|
||||
if i % downsample == 0:
|
||||
sample.append(x[0])
|
||||
sample = np.asarray(sample)
|
||||
assert sample.shape == (n, rv.ndim), sample.shape
|
||||
return sample
|
||||
@@ -0,0 +1,34 @@
|
||||
import random
|
||||
import numpy as np
|
||||
|
||||
|
||||
def rejection_sampling(func, rv, k, n):
|
||||
"""
|
||||
perform rejection sampling n times
|
||||
|
||||
Parameters
|
||||
----------
|
||||
func : callable
|
||||
(un)normalized distribution to be sampled from
|
||||
rv : RandomVariable
|
||||
distribution to generate sample
|
||||
k : float
|
||||
constant to be multiplied with the distribution
|
||||
n : int
|
||||
number of samples to draw
|
||||
|
||||
Returns
|
||||
-------
|
||||
sample : (n, ndim) ndarray
|
||||
generated sample
|
||||
"""
|
||||
assert hasattr(rv, "draw"), "the distribution has no method to draw random samples"
|
||||
sample = []
|
||||
while len(sample) < n:
|
||||
sample_candidate = rv.draw()
|
||||
accept_proba = func(sample_candidate) / (k * rv.pdf(sample_candidate))
|
||||
if random.random() < accept_proba:
|
||||
sample.append(sample_candidate[0])
|
||||
sample = np.asarray(sample)
|
||||
assert sample.shape == (n, rv.ndim), sample.shape
|
||||
return sample
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
def sir(func, rv, n):
|
||||
"""
|
||||
sampling-importance-resampling
|
||||
|
||||
Parameters
|
||||
----------
|
||||
func : callable
|
||||
(un)normalized distribution to be sampled from
|
||||
rv : RandomVariable
|
||||
distribution to generate sample
|
||||
n : int
|
||||
number of samples to draw
|
||||
|
||||
Returns
|
||||
-------
|
||||
sample : (n, ndim) ndarray
|
||||
generated sample
|
||||
"""
|
||||
assert hasattr(rv, "draw"), "the distribution has no method to draw random samples"
|
||||
sample_candidate = rv.draw(n * 10)
|
||||
weight = np.squeeze(func(sample_candidate) / rv.pdf(sample_candidate))
|
||||
assert weight.shape == (n * 10,), weight.shape
|
||||
weight /= np.sum(weight)
|
||||
index = np.random.choice(n * 10, n, p=weight)
|
||||
sample = sample_candidate[index]
|
||||
return sample
|
||||
Reference in New Issue
Block a user