A simple, from-scratch neural network library written in Rust.
This project was created as a learning exercise to better understand how neural networks and deep learning frameworks work internally. It is not intended for production use. The implementation prioritizes readability and educational value over performance, optimization, and memory efficiency.
If you're curious about how neural networks are implemented, feel free to explore the code, run the examples, and experiment with it.
- Architectures & Layers:
Sequentialmodel containerLinear(Fully Connected) layer
- Activation Functions:
ReLUTanhSigmoidSoftmax
- Generalization:
Dropout
- Loss Functions:
- Mean Squared Error (
MSE) CrossEntropyLoss
- Mean Squared Error (
- Data Utilities:
- Matrix-based Dataset and DataLoader abstractions (
MatDataset,MatDataLoader) with shuffling, splitting, and batching support.
- Matrix-based Dataset and DataLoader abstractions (
- Training & Evaluation Utilities:
- Built-in
train_loopandtestfunctions with customizable evaluation metrics and reporting capabilities.
- Built-in
// 1. Prepare data
let labels = vec![
vec![0.0], // List of labels per row
// ...
];
let features = vec![
vec![1.0, 2.0], // List of features per row (assuming 64 features total)
// ...
];
// 2. Initialize datasets and loaders
let (itest_mat, ltest_mat) = (Mat::vec(features).norm(), Mat::vec(labels));
let ds = MatDataset::init(itest_mat, ltest_mat.to_hot_encoded(10));
let (mut train_ds, mut eval_ds) = ds.split(0.9, true /* shuffle */);
let mut train_dl = MatDataLoader::init(&mut train_ds, 64, true /* shuffle */, true /* drop last */);
let mut eval_dl = MatDataLoader::init(&mut eval_ds, 100, false, true);
let mut test_dl = eval_dl.clone(); // Representation of your testing data loader
// 3. Define the Network Architecture
let mut layers: [Box<dyn Module>; 6] = [
Box::new(Linear::init(64, 256)), // 64 input features -> 256 hidden units
Box::new(Dropout::init(0.1)), // 10% dropout rate
Box::new(Tanh::init()),
Box::new(Linear::init(256, 128)),
Box::new(Relu::init()),
Box::new(Linear::init(128, 10)), // 10 output labels
];
let mut model = Sequential::init(&mut layers);
let mut loss_fn = CrossEntropyLoss::init();
const EPOCHS: u32 = 3;
const LR: f64 = 1.0;
// 4. Train and Evaluate
train_loop(
EPOCHS,
&mut model,
&mut loss_fn,
&mut train_dl,
LR,
EvalMetric::ACC,
10, // Report frequency (report every 10 batches)
&mut eval_dl,
);
test(
&mut model,
&mut loss_fn,
&mut test_dl,
TestEvalMetric::ACC,
1,
);
// 5. Save the trained model
model.save("model_file_name").unwrap();You can find working implementations in the ./examples directory:
| Project Name | Run command | Saved Model Filename |
|---|---|---|
| XOR gate | cargo run --example xor_gate |
xor_model_ubyte |
| MNIST | cargo run --example mnist |
mnist_model_ubyte |
After running an example for the first time, it will save the trained weights. Subsequent runs will automatically detect and load the local model file instead of retraining from scratch.
| Name | Description | Default |
|---|---|---|
NUM_WORKERS |
Number of proccessing cores to use for matrix calculations | All available machine cpu cores |
MIT