Files
mikoto10032--deeplearning/books/PRML/PRML-master-Python/prml/linear/variational_linear_regression.py
T
2026-07-13 13:30:25 +08:00

94 lines
2.8 KiB
Python
Executable File

import numpy as np
from prml.linear.regression import Regression
class VariationalLinearRegression(Regression):
"""
variational bayesian estimation of linear regression model
p(w,alpha|X,t)
~ q(w)q(alpha)
= N(w|w_mean, w_var)Gamma(alpha|a,b)
Attributes
----------
a : float
a parameter of variational posterior gamma distribution
b : float
another parameter of variational posterior gamma distribution
w_mean : (n_features,) ndarray
mean of variational posterior gaussian distribution
w_var : (n_features, n_feautures) ndarray
variance of variational posterior gaussian distribution
n_iter : int
number of iterations performed
"""
def __init__(self, beta:float=1., a0:float=1., b0:float=1.):
"""
construct variational linear regressor
Parameters
----------
beta : float
precision of observation noise
a0 : float
a parameter of prior gamma distribution
Gamma(alpha|a0,b0)
b0 : float
another parameter of prior gamma distribution
Gamma(alpha|a0,b0)
"""
self.beta = beta
self.a0 = a0
self.b0 = b0
def fit(self, X:np.ndarray, t:np.ndarray, iter_max:int=100):
"""
variational bayesian estimation of parameter
Parameters
----------
X : (N, D) np.ndarray
training independent variable
t : (N,) np.ndarray
training dependent variable
iter_max : int, optional
maximum number of iteration (the default is 100)
"""
D = np.size(X, 1)
self.a = self.a0 + 0.5 * D
self.b = self.b0
I = np.eye(D)
for _ in range(iter_max):
param = self.b
self.w_var = np.linalg.inv(self.a * I / self.b + self.beta * X.T @ X)
self.w_mean = self.beta * self.w_var @ X.T @ t
self.b = self.b0 + 0.5 * (np.sum(self.w_mean ** 2) + np.trace(self.w_var))
if np.allclose(self.b, param):
break
def predict(self, X:np.ndarray, return_std:bool=False):
"""
make prediction of input
Parameters
----------
X : (N, D) np.ndarray
independent variable
return_std : bool, optional
return standard deviation of predictive distribution if True
(the default is False)
Returns
-------
y : (N,) np.ndarray
mean of predictive distribution
y_std : (N,) np.ndarray
standard deviation of predictive distribution
"""
y = X @ self.w_mean
if return_std:
y_var = 1 / self.beta + np.sum(X @ self.w_var * X, axis=1)
y_std = np.sqrt(y_var)
return y, y_std
return y