Deploying Serverless Recommendation Microservice with AWS Lambda


In this tutorial, we deploy a machine learning microservice using AWS Lambda, AWS Api Gateway and Python 3.6

Before you begin, make sure you are running python 3 and you have a valid AWS account and your AWS credentials file is properly installed.

Introduction to dataset

In this project we are going to create product recommendation based on title item. This is not simplified the problem but we chose this strategy becouse it can give us better recommendation compaire to recommendation based on item discription.

import numpy as np
import pandas as pd
pd.set_option('display.max_colwidth', -1)

data_source = 'data/Jkt-Index-tiny.csv'
ds = pd.read_csv(data_source)
ds['title']
0     3G External Antena Modem Bolt Slim & Max 3dbi ts9 - e5776 - Black                     
1     4G LTE External Antenna for Modem Routers - CRC9 Connector - White                    
2     4G LTE External Antenna for Modem Routers - SMA Connector - White                     
3     4G LTE External Antenna for Modem Routers - TS9 Connector - White                     
4     4G LTE MIMO External Antenna for Modem Routers - Dual CRC9 Connector - White          
5     4G LTE MIMO External Antenna for Modem Routers - Dual TS9 Connector - White           
6     7dBi GSM 3G Magnetic Base Antenna MB-49A - Black                                      
7     9dBi Rubber Antenna for 2.4Ghz Magnetic Base M24-9-SR-MB - Black                      
8     Antenna DVB-T for Huawei E510 - Black                                                 
9     Antenna for Router Network 2.4GHz 22dbi RP-SMA - Black                                
10    Antenna Penguat Sinyal Handphone 3G 12dbi with Phone Holder - Black                   
11    Antenna Sierra Wireless 875U 595U 8781U - Black                                       
12    External Antenna for Huawei 4G LTE 10dbi - TS9 - White                                
13    FME Extension cable 5 Meter - No Color                                                
14    GSM 3G Magnetic Base Antenna 4.0mm Plug - Black                                       
15    GSM 3G Modem Antenna 4.0mm Plug for Huawei D602 - Black                               
16    Hame Little U USB Connector - White                                                   
17    Huawei Docking Station for Huawei E5830 E5832 - E5-1 Cradle - Gray Silver             
18    Huawei HB4F1 Battery for Mifi E5830 E5832 E585 (E583x) Original - No Color            
19    Kabel Antena Male to Male 1.5 Meter - White                                           
20    Omni Minimax G45 Portable 4G LTE External Antenna 45dBi with TS9 Connector - White    
21    Omni Outdoor Antenna OM-R11-07U + FME Extension Cable 5 meter - No Color              
22    Pigtail Huawei - No Color                                                             
23    Pigtail Huawei E5331 - No Color                                                       
24    Pigtail Huawei U8300 - Black                                                          
25    Pigtail OPTION GlobeTrotter - No Color                                                
26    Pigtail Sierra Wireless 312U - Black                                                  
27    Pigtail Sierra Wireless 753s 754s - Black                                             
28    Pigtail Sierra Wireless 875 - No Color                                                
29    Pigtail ZTE MF633 - No Color                                                          
30    Powerfull 3G Magnetic Antenna MB-11F (Hanya Antena panjang) - No Color                
31    Powerfull 3G Magnetic Antenna MB-15F (Hanya antena pendek) - No Color                 
32    Softcover Edition RP-SMA Male to Female Cable 174 Antenna Extension Cable - 3m - Black
33    Yagi Antenna YG-R12-11U + FME Extension Cable 5 meter - No Color                      
34    Huawei E220 USB 7.2Mbps - Logo Vodafone (14 Days) - White                             
35    Huawei E220 USB 7.2Mbps - Logo Vodafone (NEW) - White                                 
36    Huawei E3276 - 4G LTE 100 Mbps - Logo STC - White                                     
37    Huawei E3372 4G LTE Cat4 USB Modem - 827F - Black                                     
38    Huawei Vodafone K3765 HSDPA USB Stick - White                                         
39    Huawei Vodafone K4305 HSPA 21.6 Mbps - White                                          
40    Onda MDC833UP HSUPA 10.2Mbps - Black                                                  
41    Option iCON XY 7.2 Mbps - White                                                       
42    Sierra Wireless AirCard 308U HSPA+ 21.6Mbps - White                                   
43    WWAN Ericsson KM266 Mini-Card DELL Wireless 5530 HSPA 3G with GPS - No Color          
44    ZTE MF667 HSPA USB Modem Turkcell VINN 21.6 Mbps - Black                              
45    ZTE Vodafone HSPA 3G MiFi 42 Mbps R209-Z MF65 - White                                 
46    ZTE Vodafone K3772-Z HSUPA 7.2 Mbps - White                                           
Name: title, dtype: object

Training

Training is really expensive it can take hours or event more. We will use pretraining strategy and save it as python pickle.

Upload your model to Amazon S3

$ aws s3 cp model.pkl s3://yourbucketname

Creating a Python Flask API

create a project directory

$ mkdir serverless-recommendation-enggine
$ cd serverless-recommendation-enggine

Wrapt python with virtualenv

$ pip install virtualenv
$ virtualenv your_virtual_environment_name
$ source your_virtual_environment_name/bin/activate

Install Python Library

$ pip install zappa sklearn numpy scipy

Now, we’re ready to build our API. Create a directory api with a file called app.py and write this into it:

import io
import numpy as np

import boto3
import pickle
from flask import Flask, jsonify, request, json
import redis

BUCKET_NAME = 'zappa-oo5s5cklwld'
MODEL_FILE_NAME = 'model.pkl'

app = Flask(__name__)

S3 = boto3.client('s3', region_name='us-east-2') 

def memoize(f):
    memo = {}

    def helper(x):
        if x not in memo:
            memo[x] = f(x)
        return memo[x]

    return helper   
    return json.dumps(result)

@app.route('/predicts3', methods=['POST'])
def predic_s3():
    body_dict = request.get_json(silent=True)
    idx = body_dict['idx']

    prediction = predict_s3(idx)
    result = {'prediction': prediction}
    return json.dumps(result)


@memoize
def load_model_s3(key):
    response = S3.get_object(Bucket=BUCKET_NAME, Key=key)
    #model_str = (response['Body'].read())

    with io.BytesIO(response["Body"].read()) as f:
        # rewind the file
        f.seek(0)
        model = np.load(f)

    return model


def predict_s3(idx):
    cosine_similarities = load_model_s3(MODEL_FILE_NAME)
    return cosine_similarities[idx].argsort()[:-6:-1][1:].tolist()

if __name__ == '__main__':
    app.run(host= '0.0.0.0')

The code is basically self-explanatory. We make a Flask object, use the ‘route’ decorator functions to define our paths, and call a run function when we run it locally (which you can confirm by calling python api/app.py and visiting localhost:5000 in your browser.)

Configure AWS Lambda & API Gateway

We use a framework called Zappa to create and configure both AWS Lambda and the API Gateway automatically. Think of it as “serverless” web hosting for your Python apps.

That means infinite scaling, zero downtime, zero maintenance — and at a fraction of the cost of your current deployments!

Next, we initialize Zappa.

$ zappa init

Zappa has automatically created the a zappa_settings.json configuration file:

{
    "dev": {
        "app_function": "api.app.app",
        "aws_region": "us-east-2",
        "profile_name": "serverless-admin",
        "project_name": "flask-aws",
        "runtime": "python3.6",
        "slim_handler": true,
        "s3_bucket": "zappa-oo5s5cwld"
    }
}

Testing the API locally

The API can be tested locally like a regular Flask application First, run the Flask app as usual:

$ python api/app.py

Second, make a test API call

import requests
url = 'http://localhost:5000/predic_s3'
data = '{  "idx": 8 }'
response = requests.post(url, data=data,headers={"Content-Type": "application/json"})
print(response)

Output:

{
    "prediction": [
        24,
        15,
        22,
        12
    ]
}

Deploying to AWS Lambda

Now, we’re ready to deploy to AWS. It’s as simple as:

$ zappa deploy dev

And our serverless Machine Learning microservice is alive!

import requests
url = 'https://xxx.execute-api.us-east-2.amazonaws.com/dev/predic_s3'
data = '{  "idx": 8 }'
response = requests.post(url, data=data,headers={"Content-Type": "application/json"})
print(response)

Output:

{
    "prediction": [
        24,
        15,
        22,
        12
    ]
}

Analize the prediction

To get recommendation we must create post request with json format :

{
    "idx": 8 
}

8 is index for "Antenna DVB-T for Huawei E510 - Black", and its similar to:

{
    "prediction": [
        24,
        15,
        22,
        12
    ]
}

which is:

24    Pigtail Huawei U8300 - Black                                             
15    GSM 3G Modem Antenna 4.0mm Plug for Huawei D602 - Black                  
22    Pigtail Huawei - No Color                                                
12    External Antenna for Huawei 4G LTE 10dbi - TS9 - White                                           
Name: title, dtype: object