With the 2024 summer Olympics recently concluded and a lull in the early weeks of the fall semester, I decided to use a free weekend to act on a question I've been wondering: what would be the ideal Olympic event for my body?
What I wanted was to train a machine learning model to take in some basic biometrics, such as height and weight, and output an Olympic sport best for that person. Additionally, I wanted this project to be published online and easily accessible via a custom domain. Why? This project tackles a question I've been curious about, yes, but really I just wanted to practice doing something I've never done before: integrating a custom-trained machine learning model into a React web-app and hosting the model on an online server.
To train the model, I used this pre-compiled dataset from kaggle with basic bio data on Olympian athletes from the past 120 years. Using the tensorflow library, I defined a simple feedforward neural network that I trained using the dataset and exported the final model. The model itself during training wasn't the most accurate, especially because I chose the output feature to be specific events instead of sport categories (e.g. Men's 1500m instead of just "track and field"). However, the model is fine for my use case because even if the prediction isn’t perfect, it's likely still assigning a person to an event that fits someone with a similar body type or demographic. The model's predictions are more of a fun or exploratory tool rather than something life-changing or mission-critical, so it's more of a starting point for further exploration, not a final answer.
Once the ML model was done, I needed to figure out how to design an appropriate UI and integrate my custom model. Thankfully, tensorflow has a standard method for exporting a trained model as an h5 file. After putting together a simple React web-app, I was able to use Flask for my backend to handle POST requests from my frontend and generate predictions using the exported model. It turns out that training the model and getting my interface to work on local was the easy part!
I opted for a simple and clean UI using pre-built components from MUI and easly styling with Tailwind CSS.
I also made sure to foolproof my UI, including loading indicators for if the model is slow and plenty of input feedback to ensure correct usage.
What a doozy... I've never hosted a website anywhere except github pages before, let alone an actual backend server. On top of that, I wanted to stick with free hosting since this wasn't a project worth paying money for, so that limited my options. Below are some of the problems I encountered and how I tackled them.
Heroku used to be the go-to recommended spot for free hosting, but I unfortunately learned that as of 2022 they ended their free tier, so I had to look elsewhere.
Vercel was the next most frequently recommended service for hosting a server, by friends and the internet, so I attempted here next. However, I had to spend a long time banging my head against Vercel before I finally figured out that Vercel's free tier simply had too small a file-size limit for deployment. Apparently using the tensorflow library cost around 1gb of storage, and even after I switched to the lighter tensorflow-cpu it still required nearly 400mb. This exceeded Vercel's 300mb file size limit. I was forced to look elsewhere.
Render was my next stop, and it ended up being my final destination. Render had its own set of drawbacks, including auto-sleep servers on the free tier after 15 minutes of inactivity (so if users tried accessing my web-app while it was sleeping, responses could take upwards of 60 seconds) and a memory limit of 512mb. I had to spend a while figuring out the memory issue due to the resource requirements of my tensorflow model, but I ended up getting around that by converting my trained model to a tensorflow lite model to generate predictions more efficiently. I also addressed the auto-sleep problem by setting up a cron job to automatically ping the server every 10 minutes and keep it awake.
The final product is now freely accessible at nathanjli.com/olympian, and I'd love for you to try it out! I had a fun time putting together in a single weekend and sharing the final product with friends and family.
The final tech stack I used was GitHub Pages to host my frontend in React, Render to host my backend in Flask, and Tensorflow for training and exporting the machine learning model.
I've thoroughly enjoyed this exercise, and I feel more confident in my abilities to build legit projects from scratch now. Next on my wishlist of projects will be to build a new webapp that also uses an actual database hosted in a server online so I can feel as though I've truly built and hosted a full-stack project from scratch. Stay tuned!