This is a tutorial on how to deploy a machine learning model using Django, by first training the model, save the trained model and then deploy it using Django. The deployed model will then predict new instances of inputs from users. After prediction based on the user input, the received user input and the predicted outcome will be saved into the project database. The model to be deployed was trained on the famous (Fisher’s or Anderson’s) iris data which has four features namely sepal length and width and petal length and width measured in centimeters and a label named species which has three iris species (categories), namely Iris setosa, versicolor, and virginica. Since this tutorial is about how to deploy a machine learning model, instead of giving a detailed explanation of the model, I will only give the lines of code used to train the mode and a heading describing the functions of the code.
Lines of Code Used To Train The Model
packages needed for performing the analysis
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from xgboost import XGBClassifier
from sklearn.metrics import roc_auc_score,roc_curve,accuracy_score,confusion_matrix
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import seaborn as sns
import joblib
import os
from pandas.api.types import is_string_dtype, is_numeric_dtype,is_categorical_dtype
%matplotlib inline
Loading the iris data and scaling the input variables
iris_data=load_iris()
scalar=StandardScaler()
iris_feat=scalar.fit_transform(iris_data.data)
Splitting the dataset into training and testing sets
X_train, X_test, y_train, y_test = train_test_split( iris_data.data, iris_data.target,
test_size=0.33, random_state=42)
Training the model
xgbd=XGBClassifier(n_estimators=100,criterion='entropy', max_delta_step=6,
min_samples_split=45,colsample_bytree=.4,max_depth=13,
gama=10,max_features=11,min_child_weight=.4)
xgbd.fit(X_train,y_train)
Testing the model on the test data
y_predict = xgbd.predict(X_test)
accuracy_score(y_test,y_predict)
Determining the impact of each variable on the prediction of the species
# converting the data into a data frame
features=pd.DataFrame(iris_data.data,columns=iris_data.feature_names)
# RENAMING THE FEACTURES
features.rename(columns={"sepal length (cm)":"sepal_length(cm)","sepal width (cm)":"sepal_width(cm)",
"petal length (cm)":"petal_length(cm)","petal width (cm)":"petal_width_(cm)"
},inplace=True)
features_impt=pd.Series(xgbd.feature_importances_,index=features.columns)
plt.title('Importances of Features')
sns.barplot(x=fea,y=features_impt.index)
plt.show()
Creating a Confusion Matrix
conf_mat = confusion_matrix(y_test,y_predict)
ax=plt.subplot()
sns.heatmap(conf_mat,annot=True,ax=ax)
ax.set_xlabel('Predicted')
ax.set_ylabel('Actual Values')
ax.set_title('Confusion Matrix')
Saving the trained model
# create a directory named models
os.makedirs('models')
# SAVE THE MODEL
joblib.dump(xgbd,'models/iris_model.pkl')
Example of how to load a saved model
# loading the saved model
model=joblib.load('models/iris_model.pkl')
model
After training and saving the model, we will now deploy the trained model to predict new species of iris based on users inputs using Django framework.
The Django Project (ml_django project)
A project is a collection of configuration which can contain multiple apps. Before creating the Django project which will be named ml_django, we need to first install Django, so from the command line run:
$ pip install Django
After installing Django, cd (change directory) into a directory where you’d like to store your project and run the following command:
$ django-admin startproject ml_django
to create the ml_django project in your current directory. Since the ml_django project has been created let’s look at what the ml_django project contains
The files are:
-
The outer ml_django/ root directory is just a container for the project.
-
manage.py is a command-line utility that lets you interact with the ml_django project.
-
The inner ml_django/ directory is the actual Python package for the project.
-
ml_django/init.py is an empty file that tells Python to treat ml_django directory as a Python module
-
ml_django/settings.py: is the main configuration file for the ml_django project containing initial default settings.
-
ml_django/urls.py is the URL declarations for the ml_django project. Each URL defined here is mapped to a view and it tells the project how to handle each view.
-
ml_django/wsgi.py is an entry-point for WSGI-compatible web servers to serve your project.
The development server
Change into the outer ml_django directory and start the development server by running the following command:
$ python manage.py runserver
After running the command, open a Web browser and visit http://127.0.0.1:8000/ and you will see something similar to the one below
with everything working we are now set to create the iris app
Creating the iris app
An app is a Web application that does something. In our case the app will be predicting new instances of the iris species based on a user input. Let create the iris app by running the command:
$ python manage.py startapp iris
Managing Static Files
Websites generally need to serve additional files such as JavaScript files and CSS files. In Django these files are known as static files. These static files are import factor in web development and are used in designing the UI. Django provides django.contrib.staticfiles to help you manage them. In the outer ml_django/ root directory create a directory/folder named static which will contain all our static files. Your static folder should be similar to the one below depending on the sub-folders
For us to be able use these static files we need to edit the settings file, so in your settings file move to the bottom and define STATIC_URL to be
STATIC_URL = '/static/'
STATIC_URL is the base url of which the static files in the STATIC_ROOT are served
Create another folder in the outer ml_django/ root directory named static_dir and beneath STATIC_URL in the settings file define
STATIC_ROOT=os.path.join(BASE_DIR,"/static_dir")
We have set STATIC_ROOT to the static_dir directory and this is where we’d like to serve the static files when we run
$ python manage.py collectstatic
Let now define a list of directories (STATICFILES_DIRS) in the settings file where django will look for the static files
STATICFILES_DIRS=('static','C:/Users/USER/Music/ml_django/static')
where C:/Users/USER/Music/ml_django/static is the absolute path to the static directory containing the static files. From the command-line run
$ python manage.py collectstatic
to copy all files from your static folders into the STATIC_ROOT directory
The Model For The Iris App
Since the application will be accepting input from users, we need a database to store users inputs. The model is essentially our database layout, with additional metadata. Edit the iris/models.py file and add the following lines code to it
from django.db import models
# Create your models here.
class IrisData(models.Model):
sepal_length= models.FloatField()
sepal_width= models.FloatField()
petal_length= models.FloatField()
petal_width= models.FloatField()
species= models.CharField(max_length=50)
class Meta:
db_table = 'IrisData'
#managed = True
verbose_name = 'data'
verbose_name_plural = 'Data From Users'
which will define the models for the iris application.
Activating the Iris application
To keep track of our application and be able to create database tables for the model created above, we need to activate the iris app. To do so, edit the settings.py file and add under INSTALLED_APPS add ‘iris.apps.IrisConfig’
# Application definition
INSTALLED_APPS = [
'iris.apps.IrisConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Since we’ve installed the iris application into our project let run
$ python manage.py makemigrations
which tells Django that we’ve made some changes to the models (in this case, we’ve create a new one) and that we’d like the changes to be stored as a migration and then run
$ python manage.py migrate
for it to run the migrations and manage the database schema automatically.
Django Admin Interface
iris/admin.py contains the configuration necessary to connect our iris app to the administration interface. Let’s add the model IrisData we created to the administration site and customize the way model is displayed by editing iris/admin.py as below:
from django.contrib import admin
from .models import IrisData
# Register your models here.
@admin.register(IrisData)
class IrisDataAdmin(admin.ModelAdmin):
list_display=('sepal_length','sepal_width','petal_length','petal_width','species')
For us to get access to the admin interface, we’ll need to create a user who can login to the admin site by Running the following command:
$ python manage.py createsuperuser
enter the desired username and press enter.
Username:
You will then be prompted for your desired email address:
Email address:
then
Password: **********
Password (again): *********
Superuser created successfully
Let run the development server again by running
$ python manage.py runserver
In your browser enter localhost:8000/admin
fill in your particulars to get access to the admin interface which should be like the figure below
Creating The Views Of The iris Application
In Django, web pages and other content are delivered by views. Each view is represented by a simple Python function (or method, in the case of class-based views). Django will choose a view base on the requested URL. So let’s first create our application views and define a URL pattern for these views.
Before creating the views, create a sub-directory named model which resides in the iris folder and copy the saved model into that folder (iris/models/iris_model.pkl). Let now create the views by editing the iris/views.py to have
from datetime import datetime
from django.shortcuts import render
from xgboost import XGBClassifier
import numpy as np
from xgboost import XGBClassifier
import joblib
import os
from .models import IrisData
import posixpath
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# loading the saved model
model=joblib.load(os.path.join(BASE_DIR,'iris/models/iris_model.pkl'))
#,{'title':'Home Page','year':datetime.now().year,}
def home(request):
return render(request,'iris/form.html')
def SpeciesPrediction(request):
if request.method=='POST':
# receive the values entered by the user
sepal_l=request.POST['sepal_length']
sepal_w=request.POST['sepal_width']
petal_l=request.POST['petal_length']
petal_w=request.POST['petal_width']
""" saving the received data as a list according to the position of the features
in the dataset used to train the model which can be known by calling iris_data.feature_names
and is giving below as
['sepal length (cm)','sepal width (cm)','petal length (cm)','petal width (cm)']
"""
data=[sepal_l,sepal_w,petal_l,petal_w]
# converting the data into array
data=np.array(data).reshape(-1,4)
# the expected prediction by the model based on the user input
result=model.predict(data)
Species = ['Setosa', 'versicolor', 'virginica']
result = Species[result[0]]
# saving the data into the database
save_data=IrisData(sepal_length=sepal_l,sepal_width=sepal_w,petal_width=petal_w,
petal_length=petal_l,species=result )
save_data.save()
context={"result":result}
return render(request, 'iris/irispredict.html', context)
Defining A URL Patterns For The Iris Application Views
Let define the urls and map them to the views created so that when a user request a url Django runs through each URL pattern and stops at the first one that matches the requested URL. Django then import the view of the matching URL pattern and executes it. Let Define our urls by editing ml_django/urls.py
"""
Definition of urls for IrisPrediction.
"""
from datetime import datetime
from django.urls import path
from django.contrib import admin
from iris import views
urlpatterns = [
path('', views.home, name='home'),
path('SpeciesPrediction',views.SpeciesPrediction,name='SpeciesPrediction'),
path('admin/', admin.site.urls),
]
and finally, we will create the HTML files for the views created.
Templates Configuration
In Django, templates engines are configured under the TEMPLATES setting in the settings file so in the settings file under TEMPLATES set “DIRS” to
TEMPLATES = [
{
'DIRS': [os.path.join(BASE_DIR,'templates')],
}
]
and in the outer ml_django/ root directory create a directory/folder named templates and then a sub-directory named iris. Within the iris sub-directory in the templates directory let create an HTML form name form.html that accept inputs from users and then send that information back to the server, an irispredict.html that render the result generated by the views and layout.thml to serve as the base layout for the project.Click on layout.html, form.html irispredict.html to copy the files to their respective files in the templates/iris folder. The templates directory should be similar to the figure below
After copy the html files, Let now test our application on new instance from users by running
python manage.py runserver
After running the command, open a Web browser and visit http://127.0.0.1:8000/ and you will see something similar to the one below
Now enter the values for the features
and click on Predict Species for the model to predict the species based on the values entered
visit http://127.0.0.1:8000/admin to accesses the admin interface and then click on Data From Users to look at the saved data from users in the database
References: