use rustframe::compute::models::linreg::LinReg; use rustframe::matrix::Matrix; /// Two quick linear regression demonstrations. /// /// Example 1 fits a model to predict house price from floor area. /// Example 2 adds number of bedrooms as a second feature. fn main() { example_one_feature(); println!("\n-----\n"); example_two_features(); } /// Price ~ floor area fn example_one_feature() { println!("Example 1: predict price from floor area only"); // Square meters of floor area for a few houses let sizes = vec![50.0, 60.0, 70.0, 80.0, 90.0, 100.0]; // Thousands of dollars in sale price let prices = vec![150.0, 180.0, 210.0, 240.0, 270.0, 300.0]; // Each row is a sample with one feature let x = Matrix::from_vec(sizes.clone(), sizes.len(), 1); let y = Matrix::from_vec(prices.clone(), prices.len(), 1); // Train with a small learning rate let mut model = LinReg::new(1); model.fit(&x, &y, 0.0005, 20000); let preds = model.predict(&x); println!("Size (m^2) -> predicted price (k) vs actual"); for i in 0..x.rows() { println!( "{:>3} -> {:>6.1} | {:>6.1}", sizes[i], preds[(i, 0)], prices[i] ); } let new_house = Matrix::from_vec(vec![120.0], 1, 1); let pred = model.predict(&new_house); println!("Predicted price for 120 m^2: {:.1}k", pred[(0, 0)]); } /// Price ~ floor area + bedrooms fn example_two_features() { println!("Example 2: price from area and bedrooms"); // (size m^2, bedrooms) for each house let raw_x = vec![ 50.0, 2.0, 70.0, 2.0, 90.0, 3.0, 110.0, 3.0, 130.0, 4.0, 150.0, 4.0, ]; let prices = vec![160.0, 195.0, 250.0, 285.0, 320.0, 350.0]; let x = Matrix::from_rows_vec(raw_x, 6, 2); let y = Matrix::from_vec(prices.clone(), prices.len(), 1); let mut model = LinReg::new(2); model.fit(&x, &y, 0.0001, 50000); let preds = model.predict(&x); println!("size, beds -> predicted | actual (k)"); for i in 0..x.rows() { let size = x[(i, 0)]; let beds = x[(i, 1)]; println!( "{:>3} m^2, {:>1} -> {:>6.1} | {:>6.1}", size, beds, preds[(i, 0)], prices[i] ); } let new_home = Matrix::from_rows_vec(vec![120.0, 3.0], 1, 2); let pred = model.predict(&new_home); println!( "Predicted price for 120 m^2 with 3 bedrooms: {:.1}k", pred[(0, 0)] ); } #[test] fn test_linear_regression_one_feature() { let sizes = vec![50.0, 60.0, 70.0, 80.0, 90.0, 100.0]; let prices = vec![150.0, 180.0, 210.0, 240.0, 270.0, 300.0]; let scaled: Vec = sizes.iter().map(|s| s / 100.0).collect(); let x = Matrix::from_vec(scaled, sizes.len(), 1); let y = Matrix::from_vec(prices.clone(), prices.len(), 1); let mut model = LinReg::new(1); model.fit(&x, &y, 0.1, 2000); let preds = model.predict(&x); for i in 0..y.rows() { assert!((preds[(i, 0)] - prices[i]).abs() < 1.0); } } #[test] fn test_linear_regression_two_features() { let raw_x = vec![ 50.0, 2.0, 70.0, 2.0, 90.0, 3.0, 110.0, 3.0, 130.0, 4.0, 150.0, 4.0, ]; let prices = vec![170.0, 210.0, 270.0, 310.0, 370.0, 410.0]; let scaled_x: Vec = raw_x .chunks(2) .flat_map(|pair| vec![pair[0] / 100.0, pair[1]]) .collect(); let x = Matrix::from_rows_vec(scaled_x, 6, 2); let y = Matrix::from_vec(prices.clone(), prices.len(), 1); let mut model = LinReg::new(2); model.fit(&x, &y, 0.01, 50000); let preds = model.predict(&x); for i in 0..y.rows() { assert!((preds[(i, 0)] - prices[i]).abs() < 1.0); } }