pub struct LinearRegression {
pub weights: Vec<f64>,
pub intercept: f64,
}
impl LinearRegression {
pub fn new() -> LinearRegression {
LinearRegression {
weights: Vec::new(),
intercept: 0.0,
}
}
pub fn fit(&mut self, x_train: &Vec<Vec<f64>>, y_train: &Vec<f64>, lr: f64, n_iter: i32) {
let n_samples = x_train.len();
let n_features = x_train[0].len();
self.weights = vec![1.0; n_features];
if n_samples != y_train.len() {
panic!("Number of samples in training data does not match the number of samples in target values");
}
for _ in 0..n_iter {
let mut y_pred = vec![0.0; n_samples];
for i in 0..n_samples {
for j in 0..n_features {
y_pred[i] += self.weights[j] * x_train[i][j];
}
y_pred[i] += self.intercept;
}
let mut dw = vec![0.0; n_features];
let mut di = 0.0;
for i in 0..n_samples {
for j in 0..n_features {
dw[j] += (y_pred[i] - y_train[i]) * x_train[i][j];
}
di += y_pred[i] - y_train[i];
}
self.intercept -= lr * di / n_samples as f64;
for i in 0..n_features {
self.weights[i] -= lr * dw[i] / n_samples as f64;
}
}
}
pub fn predict(&self, x_test: &Vec<Vec<f64>>) -> Vec<f64> {
let n_samples = x_test.len();
let n_features = x_test[0].len();
if n_features != self.weights.len() {
panic!("Number of features in test data does not match the number of features in training data");
}
let mut y_pred = vec![0.0; n_samples];
for i in 0..n_samples {
for j in 0..n_features {
y_pred[i] += self.weights[j] * x_test[i][j];
}
y_pred[i] += self.intercept;
}
y_pred
}
}