diff --git a/src/lib.rs b/src/lib.rs index 6822702..cc550a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,9 @@ #![warn(missing_doc_code_examples)] //! # SmartCore -//! -//! Welcome to SmartCore library, the most complete machine learning library for Rust! -//! +//! +//! Welcome to SmartCore library, the most complete machine learning library for Rust! +//! //! In SmartCore you will find implementation of these ML algorithms: //! * Regression: Linear Regression (OLS), Decision Tree Regressor, Random Forest Regressor //! * Classification: Logistic Regressor, Decision Tree Classifier, Random Forest Classifier, Unsupervised Nearest Neighbors (KNN) @@ -12,33 +12,33 @@ //! * Matrix decomposition: PCA, LU, QR, SVD, EVD //! * Distance Metrics: Euclidian, Minkowski, Manhattan, Hamming, Mahalanobis //! * Evaluation Metrics: Accuracy, AUC, Recall, Precision, F1, Mean Absolute Error, Mean Squared Error, R2 -//! +//! //! Most of algorithms implemented in SmartCore operate on n-dimentional arrays. While you can use Rust vectors with all functions defined in this library //! we do recommend to go with one of the popular linear algebra libraries available in Rust. At this moment we support these packages: //! * [ndarray](https://docs.rs/ndarray) //! * [nalgebra](https://docs.rs/nalgebra/) -//! +//! //! ## Getting Started -//! +//! //! To start using SmartCore simply add the following to your Cargo.toml file: //! ```ignore //! [dependencies] //! smartcore = "0.1.0" //! ``` -//! +//! //! All ML algorithms in SmartCore are grouped into these generic categories: -//! * [Clustering](cluster/index.html), unsupervised clustering of unlabeled data. -//! * [Martix Decomposition](decomposition/index.html), various methods for matrix decomposition. +//! * [Clustering](cluster/index.html), unsupervised clustering of unlabeled data. +//! * [Martix Decomposition](decomposition/index.html), various methods for matrix decomposition. //! * [Linear Models](linear/index.html), regression and classification methods where output is assumed to have linear relation to explanatory variables //! * [Ensemble Models](ensemble/index.html), variety of regression and classification ensemble models //! * [Tree-based Models](tree/index.html), classification and regression trees //! * [Nearest Neighbors](neighbors/index.html), K Nearest Neighbors for classification and regression -//! -//! Each category is assigned to a separate module. -//! +//! +//! Each category is assigned to a separate module. +//! //! For example, KNN classifier is defined in [smartcore::neighbors::knn](neighbors/knn/index.html). To train and run it using standard Rust vectors you will //! run this code: -//! +//! //! ``` //! // DenseMatrix defenition //! use smartcore::linalg::naive::dense_matrix::*; @@ -46,20 +46,20 @@ //! use smartcore::neighbors::knn::*; //! // Various distance metrics //! use smartcore::math::distance::*; -//! +//! //! // Turn Rust vectors with samples into a matrix //! let x = DenseMatrix::from_array(&[ -//! &[1., 2.], -//! &[3., 4.], -//! &[5., 6.], -//! &[7., 8.], +//! &[1., 2.], +//! &[3., 4.], +//! &[5., 6.], +//! &[7., 8.], //! &[9., 10.]]); //! // Our classes are defined as a Vector //! let y = vec![2., 2., 2., 3., 3.]; -//! +//! //! // Train classifier //! let knn = KNNClassifier::fit(&x, &y, Distances::euclidian(), Default::default()); -//! +//! //! // Predict classes //! let y_hat = knn.predict(&x); //! ``` diff --git a/src/linear/linear_regression.rs b/src/linear/linear_regression.rs index fdbaa16..c4d4417 100644 --- a/src/linear/linear_regression.rs +++ b/src/linear/linear_regression.rs @@ -12,7 +12,7 @@ pub enum LinearRegressionSolverName { } #[derive(Serialize, Deserialize, Debug)] -pub struct LinearRegressionParameters { +pub struct LinearRegressionParameters { solver: LinearRegressionSolverName, } @@ -25,8 +25,8 @@ pub struct LinearRegression> { impl Default for LinearRegressionParameters { fn default() -> Self { - LinearRegressionParameters { - solver: LinearRegressionSolverName::SVD + LinearRegressionParameters { + solver: LinearRegressionSolverName::SVD, } } } @@ -39,7 +39,11 @@ impl> PartialEq for LinearRegression { } impl> LinearRegression { - pub fn fit(x: &M, y: &M::RowVector, parameters: LinearRegressionParameters) -> LinearRegression { + pub fn fit( + x: &M, + y: &M::RowVector, + parameters: LinearRegressionParameters, + ) -> LinearRegression { let y_m = M::from_row_vector(y.clone()); let b = y_m.transpose(); let (x_nrows, num_attributes) = x.shape(); @@ -103,7 +107,14 @@ mod tests { 114.2, 115.7, 116.9, ]); - let y_hat_qr = LinearRegression::fit(&x, &y, LinearRegressionParameters{solver: LinearRegressionSolverName::QR}).predict(&x); + let y_hat_qr = LinearRegression::fit( + &x, + &y, + LinearRegressionParameters { + solver: LinearRegressionSolverName::QR, + }, + ) + .predict(&x); let y_hat_svd = LinearRegression::fit(&x, &y, Default::default()).predict(&x); @@ -143,7 +154,14 @@ mod tests { 114.2, 115.7, 116.9, ]; - let y_hat_qr = LinearRegression::fit(&x, &y, LinearRegressionParameters{solver: LinearRegressionSolverName::QR}).predict(&x); + let y_hat_qr = LinearRegression::fit( + &x, + &y, + LinearRegressionParameters { + solver: LinearRegressionSolverName::QR, + }, + ) + .predict(&x); let y_hat_svd = LinearRegression::fit(&x, &y, Default::default()).predict(&x); diff --git a/src/neighbors/knn.rs b/src/neighbors/knn.rs index 9af48f0..8cbdd70 100644 --- a/src/neighbors/knn.rs +++ b/src/neighbors/knn.rs @@ -13,9 +13,9 @@ pub enum KNNAlgorithmName { } #[derive(Serialize, Deserialize, Debug)] -pub struct KNNClassifierParameters { +pub struct KNNClassifierParameters { pub algorithm: KNNAlgorithmName, - pub k: usize + pub k: usize, } #[derive(Serialize, Deserialize, Debug)] @@ -34,9 +34,9 @@ enum KNNAlgorithm, T>> { impl Default for KNNClassifierParameters { fn default() -> Self { - KNNClassifierParameters { + KNNClassifierParameters { algorithm: KNNAlgorithmName::CoverTree, - k: 3 + k: 3, } } } @@ -93,7 +93,7 @@ impl, T>> KNNClassifier { x: &M, y: &M::RowVector, distance: D, - parameters: KNNClassifierParameters + parameters: KNNClassifierParameters, ) -> KNNClassifier { let y_m = M::from_row_vector(y.clone()); @@ -118,7 +118,10 @@ impl, T>> KNNClassifier { ) ); - assert!(parameters.k > 1, format!("k should be > 1, k=[{}]", parameters.k)); + assert!( + parameters.k > 1, + format!("k should be > 1, k=[{}]", parameters.k) + ); KNNClassifier { classes: classes, @@ -169,7 +172,10 @@ mod tests { &x, &y, Distances::euclidian(), - KNNClassifierParameters{k: 3, algorithm: KNNAlgorithmName::LinearSearch} + KNNClassifierParameters { + k: 3, + algorithm: KNNAlgorithmName::LinearSearch, + }, ); let r = knn.predict(&x); assert_eq!(5, Vec::len(&r)); @@ -181,12 +187,7 @@ mod tests { let x = DenseMatrix::from_array(&[&[1., 2.], &[3., 4.], &[5., 6.], &[7., 8.], &[9., 10.]]); let y = vec![2., 2., 2., 3., 3.]; - let knn = KNNClassifier::fit( - &x, - &y, - Distances::euclidian(), - Default::default() - ); + let knn = KNNClassifier::fit(&x, &y, Distances::euclidian(), Default::default()); let deserialized_knn = bincode::deserialize(&bincode::serialize(&knn).unwrap()).unwrap(); diff --git a/src/optimization/mod.rs b/src/optimization/mod.rs index feb0322..e5e58d1 100644 --- a/src/optimization/mod.rs +++ b/src/optimization/mod.rs @@ -5,7 +5,7 @@ pub type F<'a, T, X> = dyn for<'b> Fn(&'b X) -> T + 'a; pub type DF<'a, X> = dyn for<'b> Fn(&'b mut X, &'b X) + 'a; #[derive(Debug, PartialEq)] -pub enum FunctionOrder { +pub enum FunctionOrder { SECOND, THIRD, }