gRPC - это тип RPC (удаленный вызов процедуры). Он разработан в Google и использует Protocol Buffer в качестве языка описания интерфейса. Он может поддерживать 10 языков, включая Golang, JAVA, Python, Ruby и т. Д. Scikit-learn - мощный пакет машинного обучения. В нем есть несколько методов обучения с учителем и обучения без учителя. Обычно мы используем Scikit-learn с Python. Итак, давайте попробуем создать службу gRPC с помощью Python!

Цель

Разверните модель классификации, созданную с помощью scikit-learn с python, на сервере gRPC. Пользователь использует клиент gRPC для вызова функции прогнозирования и получения результата.

Предварительная обработка

Прежде чем мы создадим сервер gRPC, нам нужно подготовить модель. Мы выбираем открытый набор данных: набор данных Титаник для обучения модели классификации.

Предварительный процесс 1. Обучите модель и сохраните ее
* Источник данных: набор данных Titanic ( https://www.kaggle.com / c / titanic / data )
* Цель:
Предсказать, пассажир выжил или нет при затоплении Титаника
* Метод: RandomForestClassifier

# data analysis and wrangling
import pandas as pd
import numpy as np
# visualization
import seaborn as sns
import matplotlib.pyplot as plt
# machine learning
from sklearn.ensemble import RandomForestClassifier
# model export
from sklearn.externals import joblib
## load data
train_df = pd.read_csv('titanic/train.csv')
test_df = pd.read_csv('titanic/test.csv')
## feature process
train_df['Sex'] = train_df['Sex'].map( {'male': 1, 'female': 0} ).astype(int)
test_df['Sex'] = test_df['Sex'].map( {'male': 1, 'female': 0} ).astype(int)
train_df['Embarked2'] = train_df['Embarked']
test_df['Embarked2'] = test_df['Embarked']
train_df.Embarked2.fillna('S',inplace=True)
test_df.Embarked.fillna('S',inplace=True)
test_df['Fare'].fillna(test_df['Fare'].dropna().median(), inplace=True)
train_df['Embarked2'] = train_df['Embarked2'].map( {'S': 1, 'C': 2, 'Q': 3} ).astype(int)
test_df['Embarked2'] = test_df['Embarked2'].map( {'S': 1, 'C': 2, 'Q': 3} ).astype(int)
train_df['Embarked'] = train_df['Embarked2']
test_df['Embarked'] = test_df['Embarked2']
train_df = train_df.drop(['Ticket', 'Cabin','Age','PassengerId','Name','SibSp','Parch','Embarked2'], axis=1)
test_df = test_df.drop(['Ticket', 'Cabin','Age','PassengerId','Name','SibSp','Parch','Embarked2'], axis=1)
X_train = train_df.drop("Survived", axis=1)
Y_train = train_df["Survived"]
X_test  = test_df.copy()
## train and evaluation
random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train, Y_train)
Y_pred = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)
## save model
joblib.dump(random_forest, 'titanic/save/titanic_rf.pkl')

После этого мы определяем функцию, которая загружает модель и возвращает результат. Затем сервер gRPC может вызвать эту функцию.

Предварительный процесс 2: напишите модуль с функцией прогнозирования
* ввод: Pclass, Sex, Fare, Embarked
* вывод: выжил

# predict_survival_status.py
from sklearn.ensemble import RandomForestClassifier
from sklearn.externals import joblib
def predict_passenger_survived(Pclass, Sex, Fare, Embarked):
    trained_model = joblib.load('titanic/save/titanic_rf.pkl')
    survived = trained_model.predict([[Pclass, Sex, Fare, Embarked]])
    return (survived)

Настроить файл proto

  1. Записать прото-файл
// titanic_demo.proto
//Define the used version of proto:
syntax = 'proto3';
//package titanic;
//Define a message to hold the features input by the client :
message Features{
    int32 Pclass     = 1 ;
    int32 Sex        = 2 ;
    float Fare       = 3 ;
    int32 Embarked   = 4 ;
}
//Define a message to hold the predicted survived :
message Prediction{
    int32 Survived   = 1 ;
}
//Define the service :
service Predict{
    rpc predict_passenger_survived(Features) returns (Prediction){}
}

Файл Proto может определять сообщение и службу. Эти сообщения имеют предопределенное имя и тип данных, они используются при общении со службой и клиентом.

2. Создать код gRPC

# Before run below code, we need to install gRPC and gRPC tools.
# If you have installed, skip this step.
python -m pip install grpcio
python -m pip install grpcio-tools
# create gRPC class
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. titanic_demo.proto

После запуска команды получаем два файла. Будут созданы следующие файлы:
titanic_demo_pb2_grpc.py
titanic_demo_pb2.py

Создать сервер gRPC

Сервер gRPC импортирует файлы, созданные на предыдущих шагах. Нам необходимо определить следующие элементы:
1. конфигурация сервера
2. содержимое ответа

# titanic_survived_prediction_server.py
import grpc
from concurrent import futures
import time
# import grpc class
import titanic_demo_pb2_grpc
import titanic_demo_pb2
#import predict function
import predict_survival_status
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class PredictServicer(titanic_demo_pb2_grpc.PredictServicer):
    def predict_passenger_survived(self, request, context):
        response = titanic_demo_pb2.Prediction()
        response.Survived = predict_survival_status.predict_passenger_survived(request.Pclass,request.Sex, request.Fare, request.Embarked)
        return response
def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
    titanic_demo_pb2_grpc.add_PredictServicer_to_server(
        PredictServicer(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        server.stop(0)
if __name__ == '__main__':
    serve()

Создать клиент gRPC

Клиенту gRPC также необходимы файлы импорта, созданные на предыдущих шагах. В клиенте нам сначала нужно создать заглушку с каналом для подключения к серверу. Во-вторых, мы определяем сообщения запроса и используем их с заглушкой для вызова сервера.

# titanic_survived_prediction_client.py
import random
import logging
import grpc
import argparse
# import grpc class
import titanic_demo_pb2
import titanic_demo_pb2_grpc
# Parse from argparse
parser = argparse.ArgumentParser()
parser.add_argument('--Pclass', type=int, help='input:Pclass')
parser.add_argument('--Sex', type=int, help='input:Sex')
parser.add_argument('--Fare', type=float, help='input:Fare')
parser.add_argument('--Embarked', type=int, help='input:Embarked')
args = parser.parse_args()
channel = grpc.insecure_channel('localhost:50051')
stub = titanic_demo_pb2_grpc.PredictStub(channel)
requestPrediction  = titanic_demo_pb2.Features(Pclass = args.Pclass, Sex = args.Sex, Fare = args.Fare, Embarked = args.Embarked)
responsePrediction = stub.predict_passenger_survived(requestPrediction)
print('The prediction is :',responsePrediction.Survived)

Попробуем воспользоваться клиентом!

Ссылка :

Что дальше:

В следующем рассказе я попытаюсь сравнить производительность RESTful и gRPC. Сборка сервера RESTful с использованием Flask и Gunicorn. Если я обновлю его, я добавлю сюда URL.