├── LICENSE ├── load_mnist.h ├── main.cpp ├── README.md ├── NeuralNetwork.h ├── loadcsv.h └── NeuralNetwork.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 muchlakshay 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /load_mnist.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace Eigen; 7 | 8 | int read_int(std::ifstream& stream) { 9 | unsigned char bytes[4]; 10 | stream.read(reinterpret_cast(bytes), 4); 11 | return (int(bytes[0]) << 24) | (int(bytes[1]) << 16) | (int(bytes[2]) << 8) | int(bytes[3]); 12 | } 13 | 14 | MatrixXd load_mnist_images(const std::string& filename, int& num_images, int& rows, int& cols) { 15 | std::ifstream file(filename, std::ios::binary); 16 | if (!file.is_open()) throw std::runtime_error("Cannot open image file!"); 17 | 18 | int magic = read_int(file); 19 | num_images = read_int(file); 20 | rows = read_int(file); 21 | cols = read_int(file); 22 | 23 | MatrixXd images(num_images, rows * cols); 24 | 25 | for (int i = 0; i < num_images; ++i) { 26 | for (int j = 0; j < rows * cols; ++j) { 27 | unsigned char pixel = 0; 28 | file.read(reinterpret_cast(&pixel), 1); 29 | images(i, j) = static_cast(pixel) / 255.0; // normalize 30 | } 31 | } 32 | 33 | return images; 34 | } 35 | 36 | VectorXd load_mnist_labels(const std::string& filename, int& num_labels) { 37 | std::ifstream file(filename, std::ios::binary); 38 | if (!file.is_open()) throw std::runtime_error("Cannot open label file!"); 39 | 40 | int magic = read_int(file); 41 | num_labels = read_int(file); 42 | 43 | VectorXd labels(num_labels); 44 | 45 | for (int i = 0; i < num_labels; ++i) { 46 | unsigned char label = 0; 47 | file.read(reinterpret_cast(&label), 1); 48 | labels(i) = static_cast(label); 49 | } 50 | 51 | return labels; 52 | } 53 | 54 | //one hot encode labels 55 | MatrixXd toOneHot(VectorXd& labels, int num_labels){ 56 | MatrixXd one_hot {MatrixXd::Zero(labels.rows(), num_labels)}; 57 | for (std::size_t i {}; i(labels(i))) = 1.0; 59 | } 60 | return one_hot; 61 | } 62 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "NeuralNetwork.h" 2 | #include "load_mnist.h" 3 | #include "loadcsv.h" 4 | 5 | int main(){ 6 | 7 | //--------------LOAD CSV FILES------------------------ 8 | 9 | // Data data {load_csv("filename.csv", "label_column", 0.8)}; //--> change training data ratio from 10 | // 0.8 to something else if you want 11 | 12 | // MatrixXd X_train {toMatrixXd(data.X_train)}; 13 | // MatrixXd X_test {toMatrixXd(data.X_test)}; 14 | // VectorXd Y_train {toVectorXd(data.Y_train)}; 15 | // VectorXd Y_test {toVectorXd(data.Y_test)}; 16 | 17 | //you can use toOneHot() to one hot encode the labels 18 | 19 | //--------------LOAD MNIST---------------------------- 20 | 21 | int num_images_train, rows_train, cols_train, num_labels_train; 22 | int num_images_test, rows_test, cols_test, num_labels_test; 23 | 24 | //change path to where your MNIST data is 25 | MatrixXd train_images = load_mnist_images("MNIST/train-images.idx3-ubyte", num_images_train, rows_train, cols_train); 26 | MatrixXd test_images = load_mnist_images("MNIST/t10k-images.idx3-ubyte", num_images_test, rows_test, cols_test); 27 | VectorXd train_labels = load_mnist_labels("MNIST/train-labels.idx1-ubyte", num_labels_train); 28 | VectorXd test_labels = load_mnist_labels("MNIST/t10k-labels.idx1-ubyte", num_labels_test); 29 | 30 | MatrixXd train_labels_oh {toOneHot(train_labels, 10)}; 31 | MatrixXd test_labels_oh {toOneHot(test_labels, 10)}; 32 | 33 | NeuralNetwork nn {{784, 16, 16, 10}, {"relu", "relu", "softmax"}}; 34 | nn.learn(train_images, train_labels_oh, 30, 0.01, 32, "cross_entropy_loss", true); 35 | 36 | MatrixXd pred {nn.predict(test_images)}; 37 | 38 | for (int i {}; i