This is a simple sketch to digit predictor application built using Streamlit and a Resnet18 model trained on the MNIST dataset using PyTorch. This is mainly intended to showcase an end-to-end machine learning application from training a model, creating an application around it and finally deploying it. It is also intended as a personal working template for working with PyTorch and deploying using Docker.
digit-classifier.ipynb
- This is the model training script that showcases the use of both custom datasets and readily available datasets and turning them into DataLoaders. It also features custom training and test loops that I wrote to my preference with the inclusion of tqdm to show training progress.
- This was initially built to be run locally but I later realised that using Colab was easier to leverage on their GPU capabilities.
sketch-app
- This folder contains
app.py
and the best trained model I currently have. app.py
is a simple Streamlit application that has a drawable canvas to draw digits and predicts the digit using the trained model.
- This folder contains
Dockerfile
- This is the Dockerfile used to build the image which can later be used for deployment to Heroku.
To run and/or work on this app locally, run the following:
pip install -r requirements.txt
cd sketch-app
streamlit run app.py
The app can be viewed at localhost:8501
To build a Docker image of this application and run it, do the following:
The Dockerfile is currently configured to work with a Heroku deployment and hence the $PORT environment variable. If you'd like to follow the remaining steps below, do change these to a desired port or port 8501 in order for the guide below to work
- Install Docker
- Build the image using the following:
docker build -t <NAME> .
- The t flag indicates the name for this image (an optional tag is also possible using the name:tag syntax)
- The . at the end refers that the Dockerfile is in the current directory (ensure that the image is built when in this project directory)
- Run the built image using the following:
docker run -p 8501:8501 <NAME>
- The p flag indicates publishing the exposed port to the host interface.
- 8501:8501 refers to the binding of the host port to the exposed container port.
- With this, once the container has started, the application can be viewed at
localhost:8501
.
Under the References section below, there is an option to deploy the image to Heroku locally using the Heroku CLI. However, I didn't want to build the image since it takes up space. Instead, I applied an alternative method of using GitHub actions to build and deploy the image through a workflow that can be triggered manually and can also theoretically be configured for a more extensive CI/CD. The GitHub actions I referenced here can be found here.
Steps I took to get this workflow working are as follows:
- Create the workflow yml under the folder
.github/workflows
- Create a Heroku app for the project.
- Note down the app name, your Heroku email and get your Heroku API key from your Heroku settings.
- Enter these values under
Settings > Secrets
with the following names:- HEROKU_API_KEY
- HEROKU_APP_NAME
- HEROKU_EMAIL
- Push the deployment file and either let the workflow run if configured for push on master or manually trigger it.
- Note that in order for committing workflows to work, you may need to generate a new Personal Access Token (PAT) with workflows checked.
Lastly, in order for this specific deployment to work, port references in the Dockerfile should be changed to the $PORT environment variable because Heroku assigns a port dynamically.
- Loading a pretrained model and modifying certain layers.
- Using Colab with GitHub
- Expose and publish in Docker.
- Debugging stopped containers.
- https://www.thorsten-hans.com/how-to-run-commands-in-stopped-docker-containers/
- I used this to inspect the file structure of the image because initially, the container wouldn't run properly due to an error in file copying.
- Deploying Docker on Heroku
- GitHub Actions
- GitHub actions quickstart
- Creating a GitHub personal access token (ensure workflows are checked)
- Adding secrets to use in workflows
- What does Checkout actually mean?