Machine Learning Web Application Deployment in 5 steps | by Harsh Rana | Towards Data Science

Let me paint you a picture:
You spent 2 months of your life working on a very exciting data science application. It involved advanced data collection, time-consuming data wrangling, hours of training and endless model micro-optimizations. Once you were finished, you had something that you were truly happy with. But today, 3 months since your blockbuster model was completed, it’s just sitting in a GitHub repository with your research notebooks and semi-documented code. You’ve gained 12 stars and 2 forks but wonder, “is this it? Do only 14 people in this entire world care about this awesome thing that I built? Should I have done something differently? If so, what?”
If you’ve had this experience of creating something wonderful, only to have a handful of people interact with it and even fewer give you feedback, you’re not alone. I’ve made this mistake often and I have a lot of friends in data science who’ve also had similar experiences. Now, I don’t want to take away from folks who enjoy working on theoretical problems and thrive in research settings, but I do think there are data scientists out there who need to showcase their work for the world to see. Not only would this help non-technical folks such as recruiters see and understand your work, but it would also open up the door to receiving real-world feedback on projects.
In this article, I’ll share how to deploy a machine learning web application to an Amazon AWS EC2 instance — without Amazon Beanstalk — to keep our deployment entirely free-tiered. You can check out a live demo of our end product here.
While you can use your own models and application to follow along, I’ll be using one of my previous projects where I first built a sentiment analysis classifier and then a flask web application on top of that. You can find all my code for the model in this repository and for my web application in this one. I highly recommend the flask-based development tech stack as it is the easiest to deploy to AWS and should suffice for any basic application.
Let’s be real, Amazon Web services (AWS) can be super intimidating for someone who’s never worked with web technologies and backend services before. Honestly, I’ve worked professionally as a full-stack web developer and I still had a hard time navigating and getting started with AWS, because it just offers so many different services! Do you need an S3 bucket? What about a Load Manager? You have to use Lambda requests right?
Quick note: this guide is NOT meant for production or enterprise-level solutions and should only be used for basic personal projects. If you are interested in a more production-ready deployment guide, feel free to drop a comment, so I (or other Medium readers) can point you in the right direction. In this article, I’m really focusing on a lean application deployment for personal use. We’ll be using an AWS EC2 instance, which is basically a virtual server. It’s part of the free-tier offered by AWS and thus deploying your project through the steps mentioned below will be absolutely free.
With those details out of the way, let's talk about how we’re going to deploy our basic application on a vanilla EC2 instance in 5 simple steps.
At a very high level, our deployment steps can be seen in the chart above. We’ll start out by setting up an EC2 instance on which our application will run. This’ll involve utilizing a few guides but I’ll help you through this and mention common errors to save you time and frustration. Next, we’ll connect to our instance and migrate our code to it. This is where I’ll share the application we’ll be working with today, walk you through our Flask directory setup and API. After that, we’ll install project dependencies, followed by setting up a local Apache server to run on our EC2 instance which will be used to serve our application on the public port provided by the EC2 server. Let’s get started!
Setting up an EC2 instance on AWS is really not super hard and has been covered by numerous different articles on TDS and beyond, so I will not be wasting your time by going through it again. Instead, I’ll point to the guides which helped me the most and walk through some common errors/questions that show up during setup. Remember, the goal of this step is to:
Create an AWS account (if you haven’t already)Start up an EC2 server using the tutorials and guides I’ll point to belowEnsure your instance settings are correct
Create an AWS account (if you haven’t already)
Start up an EC2 server using the tutorials and guides I’ll point to below
Ensure your instance settings are correct
Here’s the great official guide to help you setup your instance: AWS official EC2 instance setup guide. You’ll want to make a few key changes to the setup as follows.
In Step 1: Choose an Amazon Machine Image (AMI), pick the Ubuntu Server 16.04 LTS (HVM).
Stick to the free tier option (t2.micro) because it’s got enough computing power for most small-scale personal projects. Instead of choosing the Review and Launch button, click through the different configuration options and stop at Step 6: Configure Security Group. Here, add a new security group with the following settings:
This will allow users from anywhere in the world to be able to access a port on your running EC2 instance using HTTP, which is perfect for our web application. Now when you finish this step, review and click the launch button you’ll see the following dialog box:
Make sure to select “Create a new key pair” (if you don’t already have one), and save this .pem file in a secure location. You’ll need this later on. Congratulations, your EC2 instance is now up and running! It’s time to connect to it and migrate your application.
Now that our instance is up and running, we can connect to it. The connection process will look different based on your OS, so I can’t be of much help for Mac/Linux users, but here’s a great page with resources for you folks. I’ll be walking primarily through the Windows setup process, and again I’ll point you towards some good resources while mentioning hurdles and extra steps. I highly suggest using PuTTY as your SSH client because of its ease of use and simplicity. The best guide available to walk through the connection sequence is again the AWS official one, so feel free to work through that.
Once you've completed generating your .ppk key from your .pem key and are ready to connect to your instance, the following details will help:
Hostname: ubuntu@your_public_dns_name
Where your public DNS name can be found on your AWS EC2 homepage by clicking “running instances”:
The rest of the steps covered by the guide for connecting to your EC2 instance are fairly straight-forward, but make sure to save your settings in the PuTTY page so you don’t have to set this up every time. Note: your connection type is SSH and ensure that your .ppk file is connected under Connection > SSH > Auth before saving your settings.
If everything went smoothly, after this step you’ll be able to access your instance using the PuTTY client. This will be a dark DOS-looking screen from the ’70s and that’s exactly what we’re looking for!
Like I mentioned earlier in the article, we’re going to be deploying a machine learning web application that I built over the past 2 weeks. Before we get into code migration, a little knowledge about the model, application and project structure is necessary. The model is a basic sentiment analysis classifier with incremental learning capabilities. We created a single page application on top of this to help a user interact with our model. We have two Flask API routes which allow the user to enter a review/thought and receive a sentiment analysis, and provide feedback to the model allowing for ongoing learning.
The project structure can be seen in the image on the right. All our assets (images, models, etc.) are in different sub-folders inside the same main folder static , our HTML page is inside the templates folder and our app.py file is in the python folder.
We’ll be using the SCP command to help us transfer our files from our local computer (windows) to our EC2 instance. Before doing that, go ahead and create a directory (I called mine web_app, I would suggest using the same name to avoid any confusion) inside /home/ubuntu where your application will exist using the following command-
mkdir web_app
So your desired deployment location on your instance is /home/ubuntu/web_app. Now, you’ll have to download and unzip the application mentioned above into your local machine. You can find the project code in this GitHub repo. Once you have the project files in your local machine, you can use the following SCP command (from the windows terminal) to move your files from your local machine to your AWS EC2 instance:
scp -i <path/to/pem/key> -r <local/path/to/project/folder> ubuntu@<instance/public/DNS>:/home/ubuntu/web_app
Note: if you encounter an error with the following message “Permissions for ‘private-key’ are too open”, check out this awesome article about getting past that.
Great! At this point, your project files should now all be in your EC2 instance. Ensure that the folder structure/paths are correct (ex: /home/ubuntu/web_app/python/app.py etc.) and now we can move on to the next step.
Now, this step can be the most confusing for people because python environments, modules and other installations can quickly get complicated and cross-dependent. We’ll keep it simple by breaking this part into two main steps:
Install pip and other python dependenciesInstall Apache and mod_wsgi on our EC2 instance
Install pip and other python dependencies
Install Apache and mod_wsgi on our EC2 instance
Let's start by ensuring we’re running Python 3 and installing the correct version of Pip. Your EC2 instance should come pre-installed with python3. To check, use the following command:
python3 -V
You should see a version greater than 3.5. If that’s the case you can move on to the next step. If not, look through this official guide. Once you have python3 installed, you’ll need to download and install the correct pip version. To do so, use the following commands (in order):
curl -O https://bootstrap.pypa.io/get-pip.py sudo python3 get-pip.py
Now, you should have both python3 and pip installed. Before moving on to the next step run the following command to ensure everything is up-to-date:
sudo apt-get update
We’ll finish this step off by installing our web app dependencies (Flask and Scikit-learn) using the following commands:
sudo pip install Flasksudo pip install scikit-learn
Now we can move to the next step: installing Apache and mod_wsgi.
To set up Apache you need two modules: Apache2 and mod_wsgi. Apache2 is our simple web server and mod_wsgi is an Apache module used for Python based web applications. To install the correct versions for python3, use the following commands:
sudo apt-get install apache2sudo apt-get install libapache2-mod-wsgi-py
At this point, the Apache server should be serving a default page on your AWS EC2 public DNS. To verify this, note the public DNS (ec2-xx-xxx-xx-xxx.compute-x.amazonaws.com/) from your AWS console and visit it in the browser. You should see a screen which looks like the one on the left.
If you can see the Apache default screen, rejoice because you’re almost there! If not, feel free to use the comment section so myself and others can help you. You can also look through the Apache log file (/var/log/apache2/error.log) to try and debug yourself.
You’ve set up python3 and pip, installed Apache and it’s required modules and are already serving up a page. Now, all that’s left is to setup Apache and point it towards your project folder and give it permission to access those files.
To get our application running on the server, we need to set some Apache configurations. This involves two steps: set up server configurations/permissions and set up mod_wsgi configuration.
To set up your server configuration, you need to edit the following file: /etc/apache2/sites-enabled/000-default.conf. This is a restricted file and thus you’ll have to use sudo to edit it. Use the following command:
sudo vi /etc/apache2/sites-enabled/000-default.conf
Add the following code block right after the line ServerAdmin webmaster@localhost:
DocumentRoot /home/ubuntu/web_appWSGIDaemonProcess flaskapp threads=5 python-home=/usr/local/lib/python3.5/site-packages/ user=ubuntu        WSGIScriptAlias / /home/ubuntu/web_app/static/flaskapp.wsgi<Directory /home/ubuntu/web_app>            WSGIProcessGroup flaskapp            WSGIApplicationGroup %{GLOBAL}            Require all granted        </Directory><Directory python>            Require all granted        </Directory><Directory static>            Require all granted        </Directory><Directory static/models>            Require all granted        </Directory>
These configuration settings should point Apache towards the location of our web application and give it all the required permissions to interact with our files and models.
The last step in our Apache setup is configuring mod_wsgi to support our Flask-based application. To do so, you have to create a file named flaskapp.wsgi in the static folder. Put the following code in that file:
import sysimport sitesite.addsitedir(‘/home/ubuntu/.local/lib/python3.5/site-packages’)sys.path.insert(0, ‘/home/ubuntu/web_app/python’)from app import app as application
These are configurations needed by Apache to locate your python dependencies and your project folder(s). Once you’ve made/modified these files and put in the appropriate code, your application is ready to run. Restart your server using the following command to see the changes take effect:
sudo apachectl restart
Hopefully, at this point, your web application is successfully running on your EC2 public DNS and is ready for the world to interact with! If you see a 403 or 500 error code, try to look through the Apache log file (/var/log/apache2/error.log) for clues about what went wrong. As always, you also use the comment section to share errors and I’ll do my best to help. If everything went smoothly, you should see our app when you visit your public DNS in a browser:
You can check out a live demo here.
I think the internet should be full of real world projects built by people to openly communicate ideas they’re most excited about. Learning how to build a model from scratch, designing and developing a web application around it and finally deploying it online for the world to see is a great step towards that goal. I hope some of you get inspired to build and share something of your own and if you do, don’t forget to pay it forward by inspiring others to do the same.
I hope you enjoyed reading this article just as much as I enjoyed putting it together. If you have any questions, feedback or comments, feel free to get in touch with me through LinkedIn, or my website. Additionally, if you did end up building and deploying your own application, please share it with me because I’d love to see it!