1 unstable release
0.1.0 | Dec 6, 2022 |
---|
23 downloads per month
52KB
1K
SLoC
variational-regression
Regression models trained using variational inference
Motivation
This library provides implementations of Bayesian regression models that learn parameter values by optimizing a variational lower bound on the log likelihood. The benefit of using variational inference is that training is efficient, and we have a well defined objective function to optimize. The Bayesian approach also naturally incorporates regularization into the models.
Linear Regression
The model is specified as follows:
p(y | θ) = ∏ N(yi | θTxi, β-1)
p(θ | α) = ∏ N(θj | 0, αj-1)
p(α) = ∏ Gam(αj | a0, b0)
p(β) = Gam(β | c0, d0)
with the given notation:
y = labels
x = features
θ = model weights
α = weight precision (inverse variance)
β = noise precision (inverse variance)
Logistic Regression
The model is specified as follows:
p(y | θ) = ∏ σ(θTxi)yi {1 - σ(θTxi)}1-yi
p(θ | α) = ∏ N(θj | 0, αj-1)
p(α) = ∏ Gam(αj | a0, b0)
with the given notation:
y = labels
x = features
θ = model weights
α = weight precision (inverse variance)
σ = logistic sigmoid function
Reference
The models implemented here are heavily based on those presented in Chapter 10 of "Pattern Recognition and Machine Learning" (Bishop, 2006). However a key difference is that here, each model weight has its own distribution for precision, as does the noise term for the linear regression model.
Examples
use variational_regression::*;
fn main() -> Result<(), RegressionError> {
// construct features
let features: &[&[f64]] = &[
&[-0.2, -0.9, -0.5, 0.3],
&[0.6, 0.3, 0.3, -0.4],
&[0.9, -0.4, -0.5, -0.6],
&[-0.7, 0.8, 0.3, -0.3],
&[-0.5, -0.7, -0.1, 0.8],
&[0.5, 0.5, 0.0, 0.1],
&[0.1, -0.0, 0.0, -0.2],
&[0.4, 0.0, 0.2, 0.0],
&[-0.2, 0.9, -0.1, -0.9],
&[0.1, 0.4, -0.5, 0.9],
];
// construct labels
let labels: &[f64] = &[-0.4, 0.1, -0.8, 0.5, 0.6, -0.2, 0.0, 0.7, -0.3, 0.2];
// configure and train model
let config = LinearTrainConfig::default();
let model = VariationalLinearRegression::train(features, labels, &config)?;
// inspect model bias
if let Some(bias) = model.bias() {
println!("Bias: {}", bias);
}
// inspect model weights
for (ind, weight) in model.weights().iter().enumerate() {
println!("Weight {}: {}", ind + 1, weight);
}
// inspect noise variance
println!("Noise Variance: {}", 1.0 / model.noise_precision.mean());
// get predictive distribution
let prediction = model.predict(&[0.1, -0.5, 0.3, 0.9])?;
println!("Predictive mean: {}", prediction.mean());
Ok(())
}
use variational_regression::*;
fn main() -> Result<(), RegressionError> {
// construct features
let features: &[&[f64]] = &[
&[-0.2, -0.9, -0.5, 0.3],
&[0.6, 0.3, 0.3, -0.4],
&[0.9, -0.4, -0.5, -0.6],
&[-0.7, 0.8, 0.3, -0.3],
&[-0.5, -0.7, -0.1, 0.8],
&[0.5, 0.5, 0.0, 0.1],
&[0.1, -0.0, 0.0, -0.2],
&[0.4, 0.0, 0.2, 0.0],
&[-0.2, 0.9, -0.1, -0.9],
&[0.1, 0.4, -0.5, 0.9],
];
// construct labels
let labels: &[bool] = &[true, false, true, false, true, false, true, false, true, false];
// configure and train model
let config = LogisticTrainConfig::default();
let model = VariationalLogisticRegression::train(features, labels, &config)?;
// inspect model bias
if let Some(bias) = model.bias() {
println!("Bias: {}", bias);
}
// inspect model weights
for (ind, weight) in model.weights().iter().enumerate() {
println!("Weight {}: {}", ind + 1, weight);
}
// get predictive distribution
let prediction = model.predict(&[0.1, -0.5, 0.3, 0.9])?;
println!("Predictive mean: {}", prediction.mean());
Ok(())
}
Dependencies
~4MB
~80K SLoC