Deploy Machine Learning models with Django(the easy way)
Published: 2022-10-22 01:08:46

The goal of building a machine learning application is to solve a problem, and an ML model can only do this when it is actively being used in production. As such, ML model deployment is just as important as ML model development. 

Deployment is the process by which an ML model is moved from an offline environment and integrated into an existing production environment, such as a live application. It is a critical step that must be completed in order for a model to serve its intended purpose and solve the challenges it is designed for.

A common complaint among ML teams, however, is that deploying ML models in production is a complicated process. It is such a widespread issue that some experts estimate that as many as 90 percent of ML models never make it into production in the first place. 

In this article, I will show you the basic way to deploy a machine learning model using a really popular python web framework, Django. We will build a model that recommends a music genre to someone depending on their age and gender. I am assuming you already know about ML model development and are looking for a way to deploy them.

### The dataset.
Below is the dataset we will use to train our model, to easily follow along, save it as ***music.csv***


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/roervlcxt2fdl2x2lcd3.png)


## Step 1: Fit the model and store it in a joblib file.

If you are quite familiar with machine learning, the code below is one of the simplest cases so should not be difficult to understand.

```
import joblib
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split

data = pd.read_csv("music.csv")

X,y = data.drop(columns= ["genre"]), data.genre

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.3)

dtc = DecisionTreeClassifier()

dtc.fit(X_train, y_train)

joblib.dump(dtc, "premus.joblib")
```

### What is happening?

First and foremost, we install packages pandas, which we use later to read our [.csv](https://en.wikipedia.org/wiki/Comma-separated_values) dataset, [DecisionTreeClassifier](https://scikit-learn.org/stable/modules/tree.html) which is the algorithm we will use to fit the model, [train_test_split](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) will be used to split the data into training and testing sets.

Secondly, we load the data, from which we select the predictor variables and outcome variables, X and y respectively.

Next up, we then split the data into training and test sets to avoid over-fitting. We then initialize the model and train it (fitting with the training set).

Finally, store a binary file of our model that we will use later to make predictions, we use joblib to do this (dump).

## Step 2: Set up Django

Django is a high-level Python framework for creating scalable and robust web applications. In python, this is the most widely used framework.

The most efficient method to integrate machine learning models in Django is to create a communication interface between the ML model and the web interface. It will acquire data for the model, which will then process it on its own. This interface will navigate you back to the web application's end once you've received the prediction from the model. We can do this through REST APIs or WebSocket.

### Install Django

```
python -m pip install Django
```

### Create the project

```
django-admin startproject premus
```
This will create a "premus" directory in your current directory. If it didn’t work, see [Problems running django-admin](https://docs.djangoproject.com/en/4.1/faq/troubleshooting/#troubleshooting-django-admin). *premus* is just a name I chose for our app to mean music-prediction


The new **startproject** created should appear something like this

```
premus/
    manage.py
    premus/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
```

### Add templates

We then work on templates, the HTML code through which the user will enter data and the prediction will be shown. So, we will require base.html page.

The base.html will contain an HTML form that will take all the necessary fields as input and upon submitting the form, the user will be redirected back with a recommendation displayed.

The new project structure should look something like this (the order of the files and folders may change)

```
premus/
    manage.py
    premus/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
    templates/
        form.html
```

### Tell Django where to read the templates from

To do this, add "templates" to the DIRS in the object inside the TEMPLATES list in settings.py

```
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ["templates"],  # right here
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
```

### Add code to base.html

Add the code below to base.html to collect the fields required. We will not be styling our HTML templates, for now, I just want us to create something functional, you can always do the styling later.

```
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Music Recommender</title>
  </head>
  <body>
    <header>
      <nav></nav>
    </header>
    <section>
      <h1>Select to options to get Recommendation</h1>
      <form action="{% url 'prediction' %}" method="post">
        {% csrf_token %}
        <div>
          <label>
            Male
            <input type="radio" name="gender" value="1" />
          </label>
          <label>
            Female
            <input type="radio" name="gender" value="0" />
          </label>
        </div>
        <div>
          <label>
            Age
            <input type="number" name="age" placeholder="eg. 19" />
          </label>
        </div>
        <input type="submit" value="submit and get recommendation" />
      </form>
      <div class="output">
        <h2>Prediction= {{prediction}}</h2>
      </div>
      <div class="output">
        <h3>Age= {{settings.age}}</h3>
        <h3>Gender= {{settings.gender}}</h3>
    </section>
  </body>
</html>
```

### Integrating the music recommender model in a Django project

Copy your trained model dump (the joblib file) and paste it into the inner premus directory, at the end, the setup should look something like this (the order of files may be different due to sorting by alphabetical order).

```
premus/
    manage.py
    premus/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
        premus.joblib
    templates/
        form.html
```

### Create views.py and urls.py

Now we need to write some code in urls.py, this code lets the computer know which link to show what page

```
from django.contrib import admin
from django.urls import path
from . import views

app_name = "premus"
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.index, name="index"),
    path('/prediction', views.prediction, name="prediction")
]
```

The views.py will contain code on how to process the user-entered information.

```
from django.shortcuts import render
import joblib
from pathlib import Path


def index(request):
    return render(request, "base.html", {"prediction": "None"})


def prediction(request):
    BASE_DIR = Path(__file__).resolve().parent.parent
    premus = joblib.load(BASE_DIR / "premus/premus.joblib")
    gender, age = request.POST["gender"], request.POST["age"]
    prediction = premus.predict([[age, gender]])
    settings = {"gender": gender, "age": age}
    return render(request, "base.html", {"prediction": prediction[0], "settings": settings})

```

## Step 3: Start the server and test out
To start the Django development server, navigate to the root of your Django project(where there is manage.py) and run the following command using the terminal

```
python manage.py runserver
```

If you enter the URL provided (most likely `http://127.0.0.1:8000/`) into the browser, the form the user will have to enter data and the results will look something like the below screenshot.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t9o464m4po3orlxvuitj.png)

You can extend this to do some more efficient stuff on your other exciting ML project. If you learned something, follow and subscribe to my newsletter for more content like this. Follow me on [Twitter](https://twitter.com/juma_shafara)