{"id":21294914,"url":"https://github.com/vaquierm/mnist_classification","last_synced_at":"2025-07-14T17:34:00.851Z","repository":{"id":67006533,"uuid":"222731212","full_name":"vaquierm/MNIST_Classification","owner":"vaquierm","description":"🖼 A supervised classification model, which predicts the labels of a Modified MNIST dataset. 1st place in Kaggle competition","archived":false,"fork":false,"pushed_at":"2019-11-13T01:52:02.000Z","size":6515,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-15T17:12:47.892Z","etag":null,"topics":["classification","cnn","mnist","opencv","resnet"],"latest_commit_sha":null,"homepage":"https://www.kaggle.com/c/modified-mnist/overview","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vaquierm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-19T15:42:55.000Z","updated_at":"2020-03-06T22:33:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"c9695a6b-aa51-466c-a907-08603781f661","html_url":"https://github.com/vaquierm/MNIST_Classification","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vaquierm/MNIST_Classification","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaquierm%2FMNIST_Classification","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaquierm%2FMNIST_Classification/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaquierm%2FMNIST_Classification/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaquierm%2FMNIST_Classification/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vaquierm","download_url":"https://codeload.github.com/vaquierm/MNIST_Classification/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaquierm%2FMNIST_Classification/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265324715,"owners_count":23747138,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["classification","cnn","mnist","opencv","resnet"],"created_at":"2024-11-21T14:00:46.963Z","updated_at":"2025-07-14T17:34:00.831Z","avatar_url":"https://github.com/vaquierm.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# MNIST_Classification\nThis repository implements a supervised classification model, which predicts the labels of the Modified MNIST dataset. This model was used in a [Kaggle competition](https://www.kaggle.com/c/modified-mnist/overview). \n## The Dataset\nThe Modified MNIST dataset consists of images with a dark background and three handwritten digits from 0 through 9. The digits  were taken from the [MNIST dataset](https://en.wikipedia.org/wiki/MNIST_database). The associated label for each image is the digit with the greatest numerical value. The Modified MNIST dataset can be found [here](https://www.kaggle.com/c/modified-mnist/data).\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/arcaulfield/MNIST_Classification/blob/master/img/MNISTExample.png\" width=\"400\"/\u003e\n\u003c/p\u003e\n\n## The Optimal Strategy\nThe model with the highest classification accuracy used a Residual Network. The architecture for this model is a modified verison of one that was developped by [John Olafenwa](https://towardsdatascience.com/understanding-residual-networks-9add4b664b03). These modifications included:\n* increasing the kernel size of the last average pooling layer, so that it acts as a global average pooling layer\n* increasing the depth of the network\u003cbr /\u003e\n\nIn order to augment the data, an _ImageDataGenerator_ from the _Keras_ library was used. Images from the training set were randomly rotated between -10 and 10 degrees, translated by up to 10% of the image width and height, as well as zoomed in or out by up to 10%. \u003cbr /\u003e\n\nFive models were trained using five different splits of the training data. Ensembling the predictions made from each model, using majority vote, achieved a Kaggle leaderboard accuracy of __99.133%__. The confusion matrix of this strategy is as follows:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/arcaulfield/MNIST_Classification/blob/master/results/UNPROCESSED_fold2_ResNet_confusion.png\" width=\"400\"/\u003e\n\u003c/p\u003e\n\nThe accuracy and loss of the training and test datasets over 50 epochs are as follows:\n\n\u003cp float=\"left\"\u003e\n\u003cimg src=\"https://github.com/arcaulfield/MNIST_Classification/blob/master/results/UNPROCESSED_fold4_ResNet_loss.png\" width=\"400\"/\u003e\n\u003cimg src=\"https://github.com/arcaulfield/MNIST_Classification/blob/master/results/UNPROCESSED_fold4_ResNet_acc.png\" width=\"400\"/\u003e\n\u003c/p\u003e\n\n## How to Run the Program\n1. Download the training data and the test data from [Kaggle](https://www.kaggle.com/c/modified-mnist/data), and place them in the `data/` folder\n2. Open the `src/config.py` file and do the following:\n    * While they shouldn't require modification, double check that all filepaths are ok. \n    * Select the model you would like to run. This could be `CNN`, for a convolutional neural netowrk, or `ResNet`, for a residual network. Update the `MODEL` variable accordingly. Note that the optimal strategy uses `ResNet`.\n    * If you would like to retrain the model, let `retrain_models = True`.\n    * If you would like to perform transfer learning, let `transfer_learning = True`.\n    * Indicate the fold number you would like to run, by adjusting `FOLD_NUMBER` accordingly. \n3. Run the `unprocessed_predictions.py` script.\n### How to Ensemble Predictions\n1. Place all predictions to be ensembled in the `results/ensemble/` folder.\n2. Run the `ensemble.py` script. \n\n## Directory Structure\n```\n.\n├── data\n│   \n├── models\n│\n├── results\n│   └── ensemble\n│\n└── src\n    ├── config.py\n    |\n    ├── unprocessed_predictions.py\n    ├── isolated_prediction.py\n    ├── triplet_predictions.py\n    |\n    ├── ensemble.py\n    |\n    ├── data_analysis.ipynb\n    ├── results_analysis.ipynb\n    |\n    ├── data_processing\n    │   ├── data_loader.py\n    │   └── number_extraction.py\n    |\n    ├── models\n    │   ├── max_mnist_predictor.py\n    │   └── models.py\n    |\n    └── utils\n        └── fileio.py\n```\nThe `data/` folder holds the training and testing data, in the form of .csv files. \u003cbr /\u003e\n\nAny results are placed automatically in the `results/` folder. These results include confusion matrices, loss and accuracy graphs, as well as .csv files with predictions that can be submitted to Kaggle. \u003cbr /\u003e\n\n* `results/ensemble/` contains all predictions, in the form of .csv files, to be ensembled. \n\nThe `models/` folder contains models that have been trained. Newly trained models are automatically stored here, where they can then be used to make predictions or perform transfer learning. \u003cbr /\u003e\n\nFiles in `src/`:\n* `config.py` defines which models are to be run, and allows for specific configurations. \n* `models/models.py` contains the implementations of both a convolutional neural network and a residual network.\n* `unprocessed_predictions.py` has the scripts to train a model, using the unprocessed Modified MNIST dataset, and produce predictions in the form of Kaggle results. \n* `isolated_prediction.py` has the scripts to train a model, using the original MNIST dataset, and make predictions on the individual digits of each image. \n* `triplet_predictions.py` has the scripts to train a model and make predictions, using a modified version of the Modified MNIST dataset, where each image is the concatenation of the three isolated digits.\n* `util/fileio.py` defines the functionalities needed for reading from and writing to files.\n* `ensemble.py` includes the implementation of an ensemble method, which takes all predictions that are stored in the `results/ensemble/` folder and outputs a prediction in the form of a .csv file, which is placed in the `results/` folder. \n* `data_processing/` has the scripts necessary for different data processing strategies. \n* `data_analysis.ipynb` is a jupyter notebook that analyzes the dataset for this classification task.\n* `results_analysis.ipynb` is a jupyter notebook that analyzes the types of errors made by the model. \n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaquierm%2Fmnist_classification","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvaquierm%2Fmnist_classification","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaquierm%2Fmnist_classification/lists"}