Creating a Basic Model & Serving it with Flask

In this lesson, you'll learn how to build a simple predictive model using Python and then deploy it as a web service using Flask. This will teach you the fundamentals of model deployment, allowing you to make your models accessible and usable in real-world applications.

Learning Objectives

  • Create a basic machine learning model using scikit-learn.
  • Understand the concept of model serialization using pickle.
  • Build a simple Flask application to serve the model.
  • Test and interact with the deployed model through an API endpoint.

Text-to-Speech

Listen to the lesson content

Lesson Content

Introduction to Model Deployment

Model deployment is the process of making your trained machine learning model available for use. This means making it accessible to other applications or users. Without deployment, your model sits unused and doesn't provide any value. We'll be using a simple example: predicting whether a person has diabetes, based on some basic health indicators. We'll use Python, scikit-learn for the model, and Flask for the web server.

Building a Simple Model with Scikit-learn

Let's create a basic model using a popular dataset. We'll use the Pima Indians Diabetes Dataset. We will train a simple Logistic Regression model. First, you'll need to install scikit-learn: pip install scikit-learn. Then, import the necessary libraries.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# Load the dataset (replace with the correct path to the data file if needed)
df = pd.read_csv('diabetes.csv')

# Separate features (X) and target variable (y)
X = df.drop('Outcome', axis=1)
y = df['Outcome']

# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Create and train the model
model = LogisticRegression(solver='liblinear', random_state=42) # Added solver and random_state to avoid warnings
model.fit(X_train, y_train)

# Make predictions on the test set
y_pred = model.predict(X_test)

# Evaluate the model
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy}')

Important: Ensure you have a diabetes.csv file available in the same directory as your Python script or modify the file path in the pd.read_csv() function. Also, it's good practice to set random_state for reproducibility.

Model Serialization with Pickle

Once your model is trained, you need to save it so it can be used later. Serialization is the process of converting a Python object (like our trained model) into a byte stream that can be stored (e.g., in a file) or transmitted over a network. We'll use the pickle library for this.

import pickle

# Save the model to a file
filename = 'diabetes_model.pkl'
pickle.dump(model, open(filename, 'wb'))

# To load the model later (in your Flask app):
# loaded_model = pickle.load(open(filename, 'rb'))

Here, pickle.dump() saves the trained model to a file named 'diabetes_model.pkl'. The 'wb' argument specifies 'write binary' mode. The loaded model in the comment is what you'll use in the next step.

Creating a Flask Application

Flask is a micro web framework in Python that allows you to build web applications easily. We'll use it to create an API endpoint that receives input data and returns a prediction from our saved model. First install flask: pip install flask.

from flask import Flask, request, jsonify
import pickle
import pandas as pd

app = Flask(__name__)

# Load the saved model
model = pickle.load(open('diabetes_model.pkl', 'rb')) # Make sure the file name is the same.

@app.route('/predict', methods=['POST'])
def predict():
    try:
        # Get JSON data from the request
        data = request.get_json(force=True)

        # Convert data to DataFrame (or a list of lists if you want to support batch requests)
        input_df = pd.DataFrame([data])

        # Make prediction
        prediction = model.predict(input_df)[0]

        # Return prediction as JSON
        return jsonify({'prediction': int(prediction)})

    except Exception as e:
        return jsonify({'error': str(e)})

if __name__ == '__main__':
    app.run(debug=True) # Set debug to False for production

This code does the following:

  1. Imports: Imports necessary modules (Flask, pickle, pandas).
  2. Loads Model: Loads the saved diabetes_model.pkl.
  3. Defines the API endpoint: @app.route('/predict', methods=['POST']) defines a route that accepts POST requests at /predict.
  4. Receives Data: Inside the predict() function, it retrieves the JSON data sent in the request (request.get_json(force=True)).
  5. Preprocesses Data: Transforms the input JSON into a Pandas DataFrame that the model can understand. This can also be a list of lists, but you have to modify the way you call predict() and deal with the data.
  6. Makes Prediction: Uses the loaded model to predict the output based on the input data.
  7. Returns Results: Returns the prediction as a JSON response using jsonify().
  8. Error Handling: Includes a try...except block to catch any errors and return an error message.
  9. Runs the App: app.run(debug=True) starts the Flask development server (debug mode for development, set to False for production).

Testing Your Flask API

After running your Flask application (usually with python your_script_name.py), you can test it by sending a POST request to the /predict endpoint. You can use tools like curl, Postman, or the requests library in Python. Here's an example using curl from your terminal:

curl -X POST -H "Content-Type: application/json" -d '{"Pregnancies":6, "Glucose":148, "BloodPressure":72, "SkinThickness":35, "Insulin":0, "BMI":33.6, "DiabetesPedigreeFunction":0.627, "Age":50}' http://127.0.0.1:5000/predict

Or, with the Python requests library:

import requests
import json

url = 'http://127.0.0.1:5000/predict'
data = {"Pregnancies":6, "Glucose":148, "BloodPressure":72, "SkinThickness":35, "Insulin":0, "BMI":33.6, "DiabetesPedigreeFunction":0.627, "Age":50}
headers = {'Content-Type': 'application/json'}

response = requests.post(url, headers=headers, data=json.dumps(data))

print(response.json())

Replace the example input data with your own and observe the output, which should be either 0 or 1, representing the prediction from your model.

Progress
0%