In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import multivariate_normal
from sklearn.preprocessing import PolynomialFeatures
import bayesnet as bn

np.random.seed(1234)

In [2]:
x_train = np.random.uniform(-1, 1, 3)
y_train = 0.5 * x_train - 0.3 + np.random.normal(scale=0.1, size=x_train.shape)
X_train = PolynomialFeatures(degree=1).fit_transform(x_train[:, None])

plt.scatter(x_train, y_train)
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.gca().set_aspect("equal", adjustable="box")



In [3]:
class AnalyticalBayesianRegressor(object):
    
    def __init__(self, alpha=1.0, beta=1.0):
        self.alpha = alpha
        self.beta = beta
        
    def fit(self, X, y):
        self.w_cov = np.linalg.inv(self.alpha * np.eye(X.shape[1]) + self.beta * X.T @ X)
        self.w_mean = self.beta * self.w_cov @ X.T @ y
        
    def predict(self, X):
        y_mean = X @ self.w_mean
        y_var = 1 / self.beta + np.sum(X @ self.w_cov * X, axis=-1)
        return y_mean, y_var

In [4]:
analytical_model = AnalyticalBayesianRegressor(alpha=1., beta=100.)
analytical_model.fit(X_train, y_train)

In [5]:
class BayesianRegressor(bn.Network):
    
    def __init__(self, w=np.zeros(2)):
        super().__init__(w=w)

    def __call__(self, x, y=None):
        self.pw = bn.random.MultivariateGaussian(np.zeros(2), np.eye(2), data=self.w)
        self.py = bn.random.MultivariateGaussian((x * self.w).sum(axis=-1), 0.01 * np.eye(len(x)), data=y)
        if y is None:
            return self.py.mu.value

In [6]:
model = BayesianRegressor()
optimizer = bn.optimizer.Adam(model, 0.1)
optimizer.set_decay(0.9, 100)
for _ in range(1000):
    model.clear()
    model(X_train, y_train)
    log_posterior = model.log_pdf()
    log_posterior.backward()
    optimizer.update()

In [7]:
sample = bn.sampler.metropolis(
    BayesianRegressor(model.w.value),
    (X_train, y_train),
    1000,
    downsample=10,
    w=bn.random.Gaussian(np.zeros(2), 0.1)
)

In [8]:
w0, w1 = np.meshgrid(np.linspace(-1, 1, 100), np.linspace(-1, 1, 100))
w_grid = np.array([w0, w1]).transpose(1, 2, 0)
plt.contour(w0, w1, multivariate_normal.pdf(w_grid, mean=analytical_model.w_mean, cov=analytical_model.w_cov))
w_sample = np.asarray(sample["w"])
plt.scatter(w_sample[:, 0], w_sample[:, 1], c="steelblue", s=1)
plt.xlabel("w0")
plt.ylabel("w1")
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.gca().set_aspect("equal")



In [9]:
sample = bn.sampler.hmc(
    BayesianRegressor(model.w.value),
    (X_train, y_train),
    sample_size=1000,
    step_size=1e-2,
    n_step=10
)

In [10]:
w0, w1 = np.meshgrid(np.linspace(-1, 1, 100), np.linspace(-1, 1, 100))
w_grid = np.array([w0, w1]).transpose(1, 2, 0)
plt.contour(w0, w1, multivariate_normal.pdf(w_grid, mean=analytical_model.w_mean, cov=analytical_model.w_cov))
w_sample = np.asarray(sample["w"])
plt.scatter(w_sample[:, 0], w_sample[:, 1], c="steelblue", s=1)
plt.xlabel("w0")
plt.ylabel("w1")
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.gca().set_aspect("equal")



In [ ]: