Skip to content

Added documentation and made clippy a lot more annoying. #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Install egui dependencies
run: sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libspeechd-dev libxkbcommon-dev libssl-dev
run: sudo apt-get install -y libclang-dev libgtk-3-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev
- name: Build
run: cargo build --release --verbose --all-features
- name: Run tests
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ Cargo.lock
.idea/
/examples/*.aml
/examples/*.yaml
/examples/*.sc
/examples/*.sc
.vscode
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "automl"
version = "0.2.7"
version = "0.3.0"
authors = ["Chris McComb <[email protected]>"]
description = "Automated machine learning for classification and regression"
edition = "2021"
Expand Down
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,35 @@
[![docs.rs](https://img.shields.io/docsrs/automl/latest?logo=rust)](https://docs.rs/automl)

# AutoML with SmartCore

AutoML is _Automated Machine Learning_, referring to processes and methods to make machine learning more accessible for
a general audience. This crate builds on top of the [smartcore](https://docs.rs/smartcore/) machine learning framework,
and provides some utilities to quickly train and compare models.

# Install

To use the latest released version of `AutoML`, add this to your `Cargo.toml`:
```toml
automl = "0.2.7"
automl = "0.3.0"
```
To use the bleeding edge instead, add this:
```toml
automl = { git = "https://github.com/cmccomb/rust-automl" }
```

# Usage

Running the following:

```rust
let dataset = smartcore::dataset::breast_cancer::load_dataset();
let settings = automl::Settings::default_classification();
let mut classifier = automl::SupervisedModel::new(dataset, settings);
classifier.train();
```

will perform a comparison of classifier models using cross-validation. Printing the classifier object will yield:

```text
┌────────────────────────────────┬─────────────────────┬───────────────────┬──────────────────┐
│ Model │ Time │ Training Accuracy │ Testing Accuracy │
Expand All @@ -45,17 +51,20 @@ will perform a comparison of classifier models using cross-validation. Printing
│ Support Vector Classifier │ 4s 187ms 61us 708ns │ 0.57 │ 0.57 │
└────────────────────────────────┴─────────────────────┴───────────────────┴──────────────────┘
```

You can then perform inference using the best model with the `predict` method.

## Features
This crate has several features that add some additional methods

| Feature | Description |
|:----------|:----------------------------------------------------------------------------------------------------------|
| `nd` | Adds methods for predicting/reading data using [`ndarray`](https://crates.io/crates/ndarray). |
| `csv` | Adds methods for predicting/reading data from a .csv using [`polars`](https://crates.io/crates/polars). |
This crate has several features that add some additional methods.

| Feature | Description |
| :------ | :------------------------------------------------------------------------------------------------------ |
| `nd` | Adds methods for predicting/reading data using [`ndarray`](https://crates.io/crates/ndarray). |
| `csv` | Adds methods for predicting/reading data from a .csv using [`polars`](https://crates.io/crates/polars). |

## Capabilities

- Feature Engineering
- PCA
- SVD
Expand Down
2 changes: 1 addition & 1 deletion examples/classification_save_best.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fn main() {

// Load that model for use directly in SmartCore
let mut buf: Vec<u8> = Vec::new();
std::fs::File::open(&file_name)
std::fs::File::open(file_name)
.and_then(|mut f| f.read_to_end(&mut buf))
.expect("Cannot load model from file.");
let model: LogisticRegression<f32, DenseMatrix<f32>> =
Expand Down
19 changes: 13 additions & 6 deletions src/algorithms/categorical_naive_bayes_classifier.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
use smartcore::linalg::naive::dense_matrix::DenseMatrix;
use smartcore::model_selection::cross_validate;
use smartcore::naive_bayes::categorical::CategoricalNB;
//! Categorical Naive Bayes Classifier.

use smartcore::{
linalg::naive::dense_matrix::DenseMatrix,
model_selection::{cross_validate, CrossValidationResult},
naive_bayes::categorical::CategoricalNB,
};

use crate::{Algorithm, Settings};
use smartcore::model_selection::CrossValidationResult;

pub(crate) struct CategoricalNaiveBayesClassifierWrapper {}
/// The Categorical Naive Bayes Classifier.
///
/// See [scikit-learn's user guide](https://scikit-learn.org/stable/modules/naive_bayes.html#categorical-naive-bayes)
/// for a more in-depth description of the algorithm.
pub struct CategoricalNaiveBayesClassifierWrapper {}

impl super::ModelWrapper for CategoricalNaiveBayesClassifierWrapper {
fn cv(
Expand Down Expand Up @@ -41,7 +48,7 @@ impl super::ModelWrapper for CategoricalNaiveBayesClassifierWrapper {

fn predict(x: &DenseMatrix<f32>, final_model: &Vec<u8>, _settings: &Settings) -> Vec<f32> {
let model: CategoricalNB<f32, DenseMatrix<f32>> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
}
10 changes: 8 additions & 2 deletions src/algorithms/decision_tree_classifier.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Decision Tree Classifier.

use smartcore::{
linalg::naive::dense_matrix::DenseMatrix,
model_selection::{cross_validate, CrossValidationResult},
Expand All @@ -6,7 +8,11 @@ use smartcore::{

use crate::{Algorithm, Settings};

pub(crate) struct DecisionTreeClassifierWrapper {}
/// The Decision Tree Classifier.
///
/// See [scikit-learn's user guide](https://scikit-learn.org/stable/modules/tree.html#classification)
/// for a more in-depth description of the algorithm.
pub struct DecisionTreeClassifierWrapper {}

impl super::ModelWrapper for DecisionTreeClassifierWrapper {
fn cv(
Expand Down Expand Up @@ -49,7 +55,7 @@ impl super::ModelWrapper for DecisionTreeClassifierWrapper {
}

fn predict(x: &DenseMatrix<f32>, final_model: &Vec<u8>, _settings: &Settings) -> Vec<f32> {
let model: DecisionTreeClassifier<f32> = bincode::deserialize(&*final_model).unwrap();
let model: DecisionTreeClassifier<f32> = bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
}
10 changes: 8 additions & 2 deletions src/algorithms/decision_tree_regressor.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Decision Tree Regressor.

use smartcore::{
linalg::naive::dense_matrix::DenseMatrix,
model_selection::{cross_validate, CrossValidationResult},
Expand All @@ -6,7 +8,11 @@ use smartcore::{

use crate::{Algorithm, Settings};

pub(crate) struct DecisionTreeRegressorWrapper {}
/// The Decision Tree Regressor.
///
/// See [scikit-learn's user guide](https://scikit-learn.org/stable/modules/tree.html#regression)
/// for a more in-depth description of the algorithm.
pub struct DecisionTreeRegressorWrapper {}

impl super::ModelWrapper for DecisionTreeRegressorWrapper {
fn cv(
Expand Down Expand Up @@ -49,7 +55,7 @@ impl super::ModelWrapper for DecisionTreeRegressorWrapper {
}

fn predict(x: &DenseMatrix<f32>, final_model: &Vec<u8>, _settings: &Settings) -> Vec<f32> {
let model: DecisionTreeRegressor<f32> = bincode::deserialize(&*final_model).unwrap();
let model: DecisionTreeRegressor<f32> = bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
}
10 changes: 8 additions & 2 deletions src/algorithms/elastic_net_regressor.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
//! Elastic Net Regressor.

use smartcore::{
linalg::naive::dense_matrix::DenseMatrix, linear::elastic_net::ElasticNet,
model_selection::cross_validate, model_selection::CrossValidationResult,
};

use crate::{Algorithm, Settings};

pub(crate) struct ElasticNetRegressorWrapper {}
/// The Elastic Net Regressor.
///
/// See [scikit-learn's user guide](https://scikit-learn.org/stable/modules/linear_model.html#elastic-net)
/// for a more in-depth description of the algorithm.
pub struct ElasticNetRegressorWrapper {}

impl super::ModelWrapper for ElasticNetRegressorWrapper {
fn cv(
Expand Down Expand Up @@ -40,7 +46,7 @@ impl super::ModelWrapper for ElasticNetRegressorWrapper {
}

fn predict(x: &DenseMatrix<f32>, final_model: &Vec<u8>, _settings: &Settings) -> Vec<f32> {
let model: ElasticNet<f32, DenseMatrix<f32>> = bincode::deserialize(&*final_model).unwrap();
let model: ElasticNet<f32, DenseMatrix<f32>> = bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
}
15 changes: 11 additions & 4 deletions src/algorithms/gaussian_naive_bayes_classifier.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
//! Gaussian Naive Bayes Classifier

use smartcore::{
linalg::naive::dense_matrix::DenseMatrix, model_selection::cross_validate,
model_selection::CrossValidationResult, naive_bayes::gaussian::GaussianNB,
linalg::naive::dense_matrix::DenseMatrix,
model_selection::{cross_validate, CrossValidationResult},
naive_bayes::gaussian::GaussianNB,
};

use crate::{Algorithm, Settings};

pub(crate) struct GaussianNaiveBayesClassifierWrapper {}
/// The Gaussian Naive Bayes Classifier.
///
/// See [scikit-learn's user guide](https://scikit-learn.org/stable/modules/naive_bayes.html#gaussian-naive-bayes)
/// for a more in-depth description of the algorithm.
pub struct GaussianNaiveBayesClassifierWrapper {}

impl super::ModelWrapper for GaussianNaiveBayesClassifierWrapper {
fn cv(
Expand Down Expand Up @@ -40,7 +47,7 @@ impl super::ModelWrapper for GaussianNaiveBayesClassifierWrapper {
}

fn predict(x: &DenseMatrix<f32>, final_model: &Vec<u8>, _settings: &Settings) -> Vec<f32> {
let model: GaussianNB<f32, DenseMatrix<f32>> = bincode::deserialize(&*final_model).unwrap();
let model: GaussianNB<f32, DenseMatrix<f32>> = bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
}
22 changes: 13 additions & 9 deletions src/algorithms/knn_classifier.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
//! KNN Classifier

use smartcore::{
linalg::naive::dense_matrix::DenseMatrix,
math::distance::{
euclidian::Euclidian, hamming::Hamming, mahalanobis::Mahalanobis, manhattan::Manhattan,
minkowski::Minkowski, Distances,
},
model_selection::cross_validate,
model_selection::{cross_validate, CrossValidationResult},
neighbors::knn_classifier::{
KNNClassifier, KNNClassifierParameters as SmartcoreKNNClassifierParameters,
},
};

use crate::{Algorithm, Distance, Settings};
use smartcore::model_selection::CrossValidationResult;

pub(crate) struct KNNClassifierWrapper {}
/// The KNN Classifier.
///
/// See [scikit-learn's user guide](https://scikit-learn.org/stable/modules/neighbors.html#classification)
/// for a more in-depth description of the algorithm.
pub struct KNNClassifierWrapper {}

impl super::ModelWrapper for KNNClassifierWrapper {
fn cv(
Expand Down Expand Up @@ -281,27 +286,26 @@ impl super::ModelWrapper for KNNClassifierWrapper {
match settings.knn_classifier_settings.as_ref().unwrap().distance {
Distance::Euclidean => {
let model: KNNClassifier<f32, Euclidian> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
Distance::Manhattan => {
let model: KNNClassifier<f32, Manhattan> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
Distance::Minkowski(_) => {
let model: KNNClassifier<f32, Minkowski> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
Distance::Mahalanobis => {
let model: KNNClassifier<f32, Mahalanobis<f32, DenseMatrix<f32>>> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
Distance::Hamming => {
let model: KNNClassifier<f32, Hamming> =
bincode::deserialize(&*final_model).unwrap();
let model: KNNClassifier<f32, Hamming> = bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
}
Expand Down
19 changes: 12 additions & 7 deletions src/algorithms/knn_regressor.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! KNN Regressor

use smartcore::{
linalg::naive::dense_matrix::DenseMatrix,
math::distance::{
Expand All @@ -13,7 +15,11 @@ use smartcore::{

use crate::{Algorithm, Distance, Settings};

pub(crate) struct KNNRegressorWrapper {}
/// The KNN Regressor.
///
/// See [scikit-learn's user guide](https://scikit-learn.org/stable/modules/neighbors.html#regression)
/// for a more in-depth description of the algorithm.
pub struct KNNRegressorWrapper {}

impl super::ModelWrapper for KNNRegressorWrapper {
fn cv(
Expand Down Expand Up @@ -288,27 +294,26 @@ impl super::ModelWrapper for KNNRegressorWrapper {
match settings.knn_regressor_settings.as_ref().unwrap().distance {
Distance::Euclidean => {
let model: KNNRegressor<f32, Euclidian> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
Distance::Manhattan => {
let model: KNNRegressor<f32, Manhattan> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
Distance::Minkowski(_) => {
let model: KNNRegressor<f32, Minkowski> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
Distance::Mahalanobis => {
let model: KNNRegressor<f32, Mahalanobis<f32, DenseMatrix<f32>>> =
bincode::deserialize(&*final_model).unwrap();
bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
Distance::Hamming => {
let model: KNNRegressor<f32, Hamming> =
bincode::deserialize(&*final_model).unwrap();
let model: KNNRegressor<f32, Hamming> = bincode::deserialize(final_model).unwrap();
model.predict(x).unwrap()
}
}
Expand Down
10 changes: 8 additions & 2 deletions src/algorithms/lasso_regressor.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
//! LASSO regression algorithm.

use smartcore::{
linalg::naive::dense_matrix::DenseMatrix, linear::lasso::Lasso,
model_selection::cross_validate, model_selection::CrossValidationResult,
};

use crate::{Algorithm, Settings};

pub(crate) struct LassoRegressorWrapper {}
/// The LASSO regression algorithm.
///
/// See [scikit-learn's user guide](https://scikit-learn.org/stable/modules/linear_model.html#lasso)
/// for a more in-depth description of the algorithm.
pub struct LassoRegressorWrapper {}

impl super::ModelWrapper for LassoRegressorWrapper {
fn cv(
Expand Down Expand Up @@ -49,7 +55,7 @@ impl super::ModelWrapper for LassoRegressorWrapper {

fn predict(x: &DenseMatrix<f32>, final_model: &Vec<u8>, _settings: &Settings) -> Vec<f32> {
let model: Lasso<f32, DenseMatrix<f32>> =
bincode::deserialize(&*final_model).expect("Cannot deserialize trained model.");
bincode::deserialize(final_model).expect("Cannot deserialize trained model.");
model.predict(x).expect("Error during inference.")
}
}
Loading