Tips for deploying a simple model with Flask on Heroku

Riley Jones
2 min readJun 2, 2020

Prerequisites: Python, Pipenv

  • Create a folder for the project or clone the repo at the bottom.
  • In the folder there are going to be a few different files.
  • Pipfile and Pipfile.lock are used by pipenv to install the necessary Python packages.
  • app.py: This is contains all the code we need for our app, GET and POST requests are handled by Flask and other libraries.
  • Procfile and requirements.txt are used to deploy to Heroku

At the top of app.py all the packages are imported.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import io
import base64
from math import pi
from flask import Flask, jsonify, request
from sklearn.preprocessing import MinMaxScaler
from sklearn.neighbors import NearestNeighbors
from flask_cors import CORS
from sqlalchemy import create_engine

CORS stands for Cross-origin resource sharing and is necessary in many cases to allow the endpoint to be accessed by the front end.

The data that’s used for prediction is stored in a database on ElephantSQL.

app = Flask(__name__)CORS(app) engine = create_engine("postgress://ELEPHANT_SQL_URL") songs_df = pd.read_sql_table('songs_df', con=engine) y = songs_df[songs_df.columns[:3]]
X = songs_df[songs_df.columns[3:]]

In our project here, we define a few different functions to be used in the REST application.

  • spider_plot : Creates a radar style plot with Matplotlib to showcase and compare the attributes of a song that are relevant for prediction such as acousticness, danceability, energy, instrumentalness, liveness, loudness, speechiness, and valence.
  • preprocess: data manipulation in pandas, drop unecessary columns
  • create_model: specify the parameters of a sklearn Nearest Neighors model, create it and fit in on our data.
  • suggest_songs: takes in a source song and a model and returns the spider plot, and a dictionary of recommendations (JSON)
my_model = create_model(preprocess(X))@app.route('/pred', methods=['GET'])
def returnAll():

song_dict = {"artist_name":"YG","track_id":"2RM4jf1Xa9zPgMGRDiht8O","track_name":"Big Bank feat. 2 Chainz, Big Sean, Nicki Minaj","acousticness":0.00582,"danceability":0.743,"duration_ms":238373,"energy":0.339,"instrumentalness":0.0,"key":1,"liveness":0.0812,"loudness":-7.678,"mode":1,"speechiness":0.409,"tempo":203.927,"time_signature":4,"valence":0.118,"popularity":15}
song_dict.update((x, [y]) for x, y in song_dict.items()) song_df = pd.DataFrame.from_dict(song_dict) song_df = song_df[song_df.columns[3:]] result = suggest_songs(song_df, my_model)
return jsonify(result)
@app.route('/pred', methods=['POST'])
def runPred():
input_song = request.get_json(force=True)
input_song.update((x, [y]) for x, y in input_song.items())
song_df = pd.DataFrame.from_dict(input_song)
song_df = song_df[song_df.columns[3:]]
results = suggest_songs(song_df, my_model)
return jsonify(results)
if __name__ == '__main__':
app.run(debug=True, port=8000)

To run the app locally from the terminal:

Once the app is working locally it’s fairly easy to deploy to Heroku as long as the files “Procfile” and “requirements.txt” are correct:

Procfile:

web: gunicorn app:app

requirements.txt:

Flask==1.1.1
FlaskSQLAlchemy==2.4.1
gunicorn==20.0.4
pandas==0.25.3
requests==2.22.0
scikit-learn==0.22.1
scipy==1.4.1
matplotlib==3.1.2
Flask-Cors==3.0.8
psycopg2==2.8.4

My repo for a spotify song recommedation engine app :

Pipenv help :

https://realpython.com/pipenv-guide/

--

--