This is a pet project developed by appxpy and brazenoptimist for educational purposes at the Higher School of Economics (HSE) in Moscow. The project aims to build a simple neural network from scratch using C++17.
NNFS includes the header-only core library "NNFS" that allows users to build their custom neural networks for educational purposes. Users can configure layers and activation functions according to their needs.
Getting Started
To get started with NNFS, clone the repository and its submodules:
git clone --recursive https://github.com/appxpy/NNFS.git
Prerequisites
- C++17 compatible compiler (tested with Clang 14 and GCC 12)
- CMake (version 3.14 or higher)
Building
To build the project, navigate to the project directory and create a build folder:
cd NNFS
mkdir build
cd build
And then build with cmake:
Architecture
The NNFS project is organized into the following directories:
include/NNFS
: Contains the header-only core library, which includes layers, activation functions, and loss functions.
tools
: Contains the source code for the built executables for training and interactive paint testing.
tests
: Contains test cases for the core library using the Google Test framework.
external
: Contains submodules for the Eigen and Google Test libraries.
Documentation
The complete documentation for the NNFS project can be found at appxpy.github.io/NNFS.
Dependencies
The NNFS project relies on the following libraries:
- Eigen: A high-level C++ library for linear algebra, which is included as a submodule in the
external/eigen
directory.
- Google Test: A C++ testing framework, which is included as a submodule in the
external/googletest
directory.
Testing
The NNFS project was tested using Clang 14 and GCC 12.
To run the tests, navigate to the build
directory and execute the following commands:
Examples
An example of using the NNFS library to create a custom neural network can be found in the tools
directory.
Training executable
This program demonstrates how to create and train a neural network using the NNFS (Neural Network From Scratch) library. The neural network is trained on the MNIST dataset, which consists of handwritten digit images. It could be found in tools/train.cpp
.
The program performs the following steps:
- Fetches the MNIST dataset and preprocesses it by rounding the pixel values to either 0 or 1.
- Creates a model with an input layer, two hidden layers with ReLU activation, and an output layer.
- Compiles the model by specifying the loss function (cross-entropy softmax) and the optimizer (Adam).
- Trains the model on the training dataset with 20 epochs and a batch size of 128.
- Saves the trained model to a file.
- Loads the model from the file.
- Evaluates the model's accuracy on the test dataset.
- Makes predictions on a subset of the test dataset and compares them with the actual labels.
Steps to Reproduce
To create and train your own neural network using the NNFS library, follow these steps:
- Install the NNFS library into your cmake project.
- Download and preprocess the MNIST dataset (if not already available) using the fetch_mnist function.
- Create the neural network model by adding layers to an instance of
NNFS::NeuralNetwork
class. For example: std::shared_ptr<NNFS::NeuralNetwork> model = std::make_shared<NNFS::NeuralNetwork>();
model->add_layer(std::make_shared<NNFS::Dense>(784, 128));
model->add_layer(std::make_shared<NNFS::ReLU>());
model->add_layer(std::make_shared<NNFS::Dense>(128, 128));
model->add_layer(std::make_shared<NNFS::ReLU>());
model->add_layer(std::make_shared<NNFS::Dense>(128, 10));
- Compile the model by calling the compile method:
- Train the model on the training dataset using the
fit
method. Specify the number of epochs and the batch size. For example: model->fit(x_train, y_train, x_test, y_test, 20, 128);
- Save the trained model to a file using the
save
method: std::string file_path = "path/to/save/model.bin";
model->save(file_path);
- Load the saved model from the file using the
load
method: std::shared_ptr<NNFS::NeuralNetwork> model = std::make_shared<NNFS::NeuralNetwork>();
model->load(file_path);
- Evaluate the model's accuracy on the test dataset using the
accuracy
method: double accuracy;
model->accuracy(accuracy, x_test, y_test);
std::cout << "Test set accuracy: " << accuracy << std::endl;
- Make predictions using the
predict
method. Pass the input data to the method and obtain the predicted outputs: Eigen::MatrixXd predictions = model->predict(input_data);
- Perform any necessary post-processing on the predictions and compare them with the actual labels to evaluate the model's performance.
Please note that this is a simplified explanation of the code. Additional code and configuration may be required depending on the specific implementation and requirements. If you need more information, please, follow the documentation.
Paint application
This interactive paint application allows users to draw on a canvas using a mouse and predicts the digit represented by the user's drawing using a neural network. The application is built using the Qt framework and the project's NNFS library.
Features
- Draw freely on the canvas using the mouse.
- Real-time prediction of the digit based on the user's drawing.
- Display of prediction probabilities for each digit.
- Highlighting of the predicted digit.
Running the application
To run the paint application, follow these steps:
- Ensure that you have CMake (version 3.5 or higher) installed on your system.
- Clone the repository and navigate to the project directory.
- Build the project using CMake:
- Run the application, executable for your OS will be located into
build/tools/paint
folder.
- As you draw, the application will predict the digit based on your drawing in real-time. The predicted digit, along with the prediction probabilities for each digit, will be displayed.
- To clear the canvas and start a new drawing, click the "Restart" button.
Example Usage
Contributing
We welcome contributions from anyone interested in improving the NNFS project. If you find a bug or have an idea for a new feature, please open an issue on the GitHub repository.
If you would like to contribute to the project, please follow these steps:
- Fork the repository and clone it to your local machine.
- Create a new branch for your changes.
- Make your changes and test them thoroughly.
- Commit your changes with a clear and descriptive message.
- Push your changes to your forked repository.
- Open a pull request on the GitHub repository.
Please note that all contributions are subject to review by the project maintainers.
License
This project is licensed under the MIT License. Please see the LICENSE file for more information.
made with ❤️ by appxpy & brazenoptimist