In this blog I will be covering the steps I took to host my project 'DeepNeuralNetwork' on Heroku. I used Flask to power a keras model and serve its output as an API which I consumed using streamlit while create responsive, fast and clean UI
A bit about Heroku
Everying in Heroku is an app which can be deoployed to dyons which are basically light weight linux containers which can host your app It uses container-based architecture to host apps, which means you can easily scale up your apps by increase the number of containers to balance out the load!
When you sign up with Heroku, you automatically get some free dyno hours, a sort of currency which can be used to run your apps in dynos. When your app runs, it consumes dyno hours. And when your app is idle for 30 minutes or more it automatically sleeps to stop consuming dyno hours. Don't worry it will take up automatically if you give it any task to do (might take a few seconds to warm up)
They also provide a free tier service and its main features are:
- 550 Hours of dyno hours per month
- After adding a credit card you will get +450 hours per month
- Your monthly dyno hours can be shared by two or more apps
- 1 dyno per app
- 512 MB ram per dyno, which will be used to load all the extra packages you will be installing (This information will be useful afterwards).
- Upto 5 free apps (without credit card) or 100 (with credit card)
I'll be referring terminal on Linux/Mac and cmd on windows as terminal, so that is easy for me
Setting up Heroku CLI
I am assuming that you have made an account on Heroku.
Before starting any sort of deployment you need to setup Heroku cli to be able to push your code directly to Heroku from here after downloading and installing Heroku cli, open your terminal/cmd and type
heroku login
which should promote you to login to Heroku on a browser, after successfully loging in you shoud something like
Logging in... done
Logged in as me@example.com
on your terminal. This means you have completed the 1st step of learning to host on Heroku
Hosting flask + keras model
You will mainly need the following files to host your application on Heroku
- app.py (core logic of your app)
- Procfile
- runtime.txt
- requirements.txt
After which you will have to do the following steps
- Create an Heroku app
- Pushing your code to Heroku's server
Create your flask app
Mine loads a pre-trained model using a .h5 file and serves its outputs over an API. All the code snipits in this section are part of a same file app.py in the order given bellow
- Importing all the necessary stuff
import json
import tensorflow as tf
import numpy as np
import random
from flask import Flask, request
- Loading my pre-trained MNSIT model from model.h5
model = tf.keras.models.load_model('model.h5')
feature_model = tf.keras.models.Model(
model.inputs,
[layer.output for layer in model.layers]
)
_, (x_test, _ ) = tf.keras.datasets.mnist.load_data()
x_test = x_test/255
def get_prediction():
index = np.random.choice(x_test.shape[0])
image = x_test[index, :, :]
image_arr = np.reshape(image, (1, 784))
return feature_model.predict(image_arr), image
- Using flask to create a API which serves values from each node of different layers in my model
app = Flask(__name__)
@app.route('/', methods=['GET','POST'])
def index():
if request.method == "POST":
preds, image = get_prediction()
final_preds = [p.tolist() for p in preds]
return json.dumps({
'prediction': final_preds,
'image': image.tolist()
})
return "Welcome to Neural Network Visualization"
if __name__=="__main__":
app.run()
Create Procfile
Yes it has no extensions, so avoid adding any. The Procfile
is used by Heroku's dynos to understand what commands are to be run on start up of application.
web:gunicorn app:app
The second part of the statment app:app
specifies that the app file has to be run. Suppose if the name of main file would have been index.py
we would have insted wrote
web:gunirn index:app
Create a runtime.txt
This file is used to specify the python version we will be using in this dyno.
python-3.7.6
Create a requirements.txt
It is used to store the pip modules that you have used and should be installed on your dyno to run your app smoothly. Don't worry if you haven't written the exact version of your pip modules, just the name should be enough, Heroku will install the latest version matching that name.
An example of my requirements.txt
is
tensorflow==1.14.0
numpy==1.18.1
json5==0.9.1
Flask==1.1.1
gunicorn
Notice: that I am using an old version of tensorflow 1.14.0 insted of latest ones 2.x.x because size wise the latest tensorflow package is above 500 MB which results in slug size too large
errors while hosting your application on Heroku as the max size of application Heroku can allows is 500MB. Better to keep that in mind while creating your new app!
Run the following commands which will create an app in your Heroku account
heroku create <your-app-name>
Run the following commands to push your code to Heroku server
git init
git add .
git commit -m "<your-message>
git push heroku master
Congrats your Flask app is hosted on Heroku :tada:! You can now view your app on Heroku's dashboard and change its settings from there
To Open your app on browser via terminal
Make sure you are on the root folder of your app
heroku open
Hosting Streamlit to Heroku
You will mainly need the following files to host your streamlit application on Heroku
- app.py (core logic of your app)
- Procfile
- requirements.txt
- setup.sh
After which you will have to do the following steps
- Create an Heroku app
- Pushing your code to Heroku's server
Creating your streamlit App
Creating a streamlit app is quite simple as it emphasises and primarily used on python scripting behaviour. They also have cool demos you can build while learing on their website
My Streamlit application looks something like this
- Importing all my stuff
import streamlit as st
import json
import requests
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import numpy as np
- Decplring the URL of my server (you might wanna fill it with url of your own server)
# Url of your Flask server
URL = ''
- Adding a title to my page and a sidebar where I will show my image
st.title('Neural Network Visualizer')
st.sidebar.markdown('## Input Image')
- If the button 'Get random predicition' is clicked' the following code section inside if-statment will run.
Which sends a post request to the URL collects it output, reshapes the image to a square size and adds it to the side bar. The for loop creats a graphical view from the values of each nodes in different layers and plots it in the end
if st.button('Get random prediction'):
response = requests.post(URL, data={})
response = json.loads(response.text)
preds = response.get('prediction')
image = response.get('image')
image = np.reshape(image, (28,28))
st.sidebar.image(image, width=150)
# print(preds)
for layer, p in enumerate(preds):
# print(layer,p)
numbers = np.squeeze(np.array(p))
plt.figure(figsize=(32,6))
if layer == 2:
row = 1
col = 10
else:
row = 2
col = 16
for i, number in enumerate(numbers):
plt.subplot(row,col,i+1)
plt.imshow(number * np.ones((8,8,3)).astype('float32'))
plt.xticks([])
plt.yticks([])
if layer == 2:
plt.xlabel(str(i), fontsize=40)
plt.subplots_adjust(wspace=0.05, hspace=0.05)
plt.tight_layout()
st.text('Layer {}'.format(layer+1))
st.pyplot()
Creating a Procfile
Make sure to now add any extensions like '.txt' while creating the file. Here we are telling the dyno to first run our setup.sh file (which we will be creating after this) and start our streamlit server after that. Streamlit servers are started with the command streamlit run <filename>
Procfile:
web: sh setup.sh && streamlit run app.py
Creating a setup.sh file
It helps us to create the necessary changes in the environment for our streamlit app to run smoothly
echo "\
[server]\n\
headless = true\n\
port = $PORT\n\
enableCORS = false\n\
\n\
" > ~/.streamlit/config.toml
Creating a requirements.txt
It is used to store the pip modules that you have used and should be installed on your dyno to run your app smoothly. Heroku will automatically install all the pip modules written in this file. Don't worry if you haven't written the exact version of your pip modules, just the name should be enough, Heroku will install the latest version matching that name. An example of my requirements.txt
is
numpy==1.18.1
json5==0.9.1
jsonschema==3.2.0
streamlit==0.61.0
matplotlib==3.1.3
Creating an App on Heroku
I am assuming you have installed heroku cli and logged in using heroku login, if not follow the step given in the starting of this tutorial to setup Heroku cli and login using your account.
Create your app on Heroku by typing
heroku create <your-app-name>
Run the following commands to push your code to Heroku server
git init
git add .
git commit -m "<your-message>
git push heroku master
Congrats your Streamlit app is now hosted on Heroku :tada:! You can now view your app on Heroku's daskboard and change its settings from there
To Open your app on browser via terminal
Make sure you are on the root folder of your app and run
heroku open
Hope this helped you in hosting your Flask and Streamlit app on Heroku. Consider checking out my Github Repo which contains all the code which was talked about in this tutorial