å人ã®çããã3ææ«ã«
ãããŒã¿ãµã€ãšã³ãã£ã¹ããã³ãŒã¹ã§æ°ããã¹ããªãŒã ãéå§ããŸãã ãããŠä»ãç§ãã¡ã¯ã³ãŒã¹ã§åœ¹ç«ã€è³æãããªããšå
±æãå§ããŠããŸãã
ã¯ããã«æ©æ¢°åŠç¿ïŒMLïŒã«å¯Ÿããç§ã®æ
ç±ã®åæã®çµéšãæãåºããŠãç§ã¯å€ãã®åªåãæ¬åœã«è¯ãã¢ãã«ãæ§ç¯ããããšã«è²»ãããããšèšãããšãã§ããŸãã ã¢ãã«ã®æ¹åæ¹æ³ãçè§£ããããã«ãã®åéã®å°éå®¶ãšçžè«ããå¿
èŠãªæ©èœã«ã€ããŠèããææ¡ãããã¹ãŠã®ãã³ããèæ
®ãããããã«ããŸããã ããããããã§ãåé¡ãçºçããŸããã
å®éã®ãããžã§ã¯ãã«ã¢ãã«ãå®è£
ããæ¹æ³ã¯ïŒ ãã®ã¹ã³ã¢ã«ã€ããŠã¯ã¢ã€ãã¢ããããŸããã§ããã ãããŸã§ç ç©¶ãããã¹ãŠã®æç®ã¯ãã¢ãã«ã®æ¹åã®ã¿ã«çŠç¹ãåœãŠãŠããŸããã ç§ã¯åœŒãã®éçºã®æ¬¡ã®ã¹ããããèŠãŸããã§ããã

ããããç§ãä»ãã®ã¬ã€ããæžããŠããçç±ã§ãã ç§ã®æä»£ã«ééããåé¡ã«çŽé¢ããŠã»ããã®ã§ãããããã«è§£æ±ºã§ããŸããã ãã®èšäºã®çµãããŸã§ã«ãPythonã®Flaskãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠæ©æ¢°åŠç¿ã¢ãã«ãå®è£
ããæ¹æ³ã玹ä»ããŸãã
å
容- æ©æ¢°åŠç¿ã¢ãã«ã®å®è£
ãªãã·ã§ã³ã
- APIãšã¯äœã§ããïŒ
- Pythonç°å¢ã®ã€ã³ã¹ããŒã«ãšFlaskã«é¢ããåºæ¬æ
å ±ã
- æ©æ¢°åŠç¿ã¢ãã«ã®äœæã
- æ©æ¢°åŠç¿ã¢ãã«ã®ä¿åïŒã·ãªã¢ã«åãšéã·ãªã¢ã«åã
- Flaskã䜿çšããŠAPIãäœæããŸãã
æ©æ¢°åŠç¿ã¢ãã«ã®å®è£
ãªãã·ã§ã³ã
ã»ãšãã©ã®å Žåãæ©æ¢°åŠç¿ã¢ãã«ã®å®éã®äœ¿çšã¯ãèªååãããé»åã¡ãŒã«é
ä¿¡ã·ã¹ãã ãŸãã¯ãã£ãããããã®ã»ãã®å°ããªã³ã³ããŒãã³ãã§ãã£ãŠããéçºã®äžå¿çãªéšåã§ãã å®è£
ã®éå£ãä¹ãè¶ããããªããšæãããå ŽåããããŸãã
ããšãã°ãã»ãšãã©ã®MLå°éå®¶ã¯ç§åŠç ç©¶ã«RãŸãã¯Pythonã䜿çšããŸãã ãã ãããŸã£ããç°ãªããã¯ãããžãŒã¹ã¿ãã¯ã䜿çšãããœãããŠã§ã¢ãšã³ãžãã¢ã¯ããããã®ã¢ãã«ã䜿çšããŸãã ãã®åé¡ã解決ã§ãã2ã€ã®ãªãã·ã§ã³ããããŸãã
ãªãã·ã§ã³1ïŒéçºãšã³ãžãã¢ã䜿çšããèšèªã§ãã¹ãŠã®ã³ãŒããæžãæããŸãã ããçšåºŠè«ççã«èãããŸãããéçºãããã¢ãã«ãè€è£œããã«ã¯å€ãã®æéãšåŽåãããããŸãã æçµçã«ã¯ãæéã®ç¡é§ã«ãªããŸãã JavaScriptãªã©ã®ã»ãšãã©ã®èšèªã«ã¯ãMLãæäœããã®ã«äŸ¿å©ãªã©ã€ãã©ãªããããŸããã ãããã£ãŠããã®ãªãã·ã§ã³ã䜿çšããªãã®ã¯åççãªãœãªã¥ãŒã·ã§ã³ã§ãã
ãªãã·ã§ã³2ïŒAPIã䜿çšããŸãã ãããã¯ãŒã¯APIã¯ãç°ãªãèšèªã®ã¢ããªã±ãŒã·ã§ã³ãæ±ãåé¡ã解決ããŸããã ããã³ããšã³ãã®éçºè
ãæ©æ¢°åŠç¿ã¢ãã«ã䜿çšããŠWebã¢ããªã±ãŒã·ã§ã³ãäœæããå¿
èŠãããå ŽåãAPIã«ã€ããŠèª¬æããŠããå®å
ãµãŒããŒã®URLãååŸããã ãã§æžã¿ãŸãã
APIãšã¯äœã§ããïŒç°¡åã«èšãã°ãAPIïŒã¢ããªã±ãŒã·ã§ã³ããã°ã©ãã³ã°ã€ã³ã¿ãŒãã§ãŒã¹ïŒã¯2ã€ã®ããã°ã©ã éã®äžçš®ã®ã³ã³ãã©ã¯ãã§ããããŠãŒã¶ãŒããã°ã©ã ãç¹å®ã®åœ¢åŒã§å
¥åããŒã¿ãæäŸããå Žåãéçºè
ã®ããã°ã©ã ïŒAPIïŒã¯ãããééããããŠãŒã¶ãŒã«å¿
èŠãªåºåããŒã¿ãæäŸããŸãã
APIãéçºè
ã®éã§éåžžã«äººæ°ã®ããéžæè¢ã§ããçç±ããã説æããŠããèšäºãèªåã§èªãããšãã§ããŸãã
ã»ãšãã©ã®å€§èŠæš¡ãªã¯ã©ãŠããµãŒãã¹ãããã€ããŒãšãå°èŠæš¡ã§æ©æ¢°ã«çŠç¹ãåœãŠãéäžåŠç¿äŒæ¥ã¯ãããã«äœ¿çšã§ããAPIãæäŸããŠããŸãã 圌ãã¯æ©æ¢°åŠç¿ãçè§£ããŠããªããããã®ãã¯ãããžãŒããœãªã¥ãŒã·ã§ã³ã«çµ±åãããéçºè
ã®ããŒãºãæºãããŠããŸãã
ããšãã°ããããã®APIãããã€ããŒã®1ã€ã¯ã
Google Vision APIãåãã
Googleã§ãã
éçºè
ãè¡ãå¿
èŠãããã®ã¯ãGoogleãæäŸããSDKã䜿çšããŠRESTïŒRepresentational State TransferïŒAPIãåŒã³åºãã ãã§ãã
Google Vision APIã䜿çšããŠã§ããããšãã芧ãã ããã
ããã§ããã ãã®èšäºã§ã¯ãPythonãã¬ãŒã ã¯ãŒã¯ã§ããFlaskã䜿çšããŠç¬èªã®APIãäœæããæ¹æ³ã説æããŸãã
泚 ïŒFlaskã¯ããã®ç®çã®ããã®å¯äžã®ãããã¯ãŒã¯ãã¬ãŒã ã¯ãŒã¯ã§ã¯ãããŸããã ãŸããDjangoãFalconãHugãããã³ãã®èšäºã§èšåãããŠããªãä»ã®å€ãã®ãã®ããããŸãã ããšãã°ãRã«ã¯
plumberãšããããã±ãŒãžããããŸã
Pythonç°å¢ã®ã€ã³ã¹ããŒã«ãšFlaskã«é¢ããåºæ¬æ
å ±ã1ïŒAnacondaã䜿çšããŠä»®æ³ç°å¢ãäœæããŸãã Pythonçšã®ç¬èªã®ä»®æ³ç°å¢ãäœæããäŸåé¢ä¿ã®å¿
èŠãªç¶æ
ãç¶æããå¿
èŠãããå ŽåãAnacondaã¯ãã®ããã®åªãããœãªã¥ãŒã·ã§ã³ãæäŸããŸãã æ¬¡ã¯ã³ãã³ãã©ã€ã³ã§åäœããŸãã
- Pythonçšã®minicondaã€ã³ã¹ããŒã©ãŒããããŸãã
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
- äžé£ã®è³ªåã«åŸããŸãã
source .bashrc
conda
ãšå
¥åãããšã䜿çšå¯èœãªã³ãã³ããšãã«ãã®ãªã¹ãã衚瀺ãããŸãã- æ°ããç°å¢ãäœæããã«ã¯ã次ãå
¥åããŸã
conda create --name <environment-name> python=3.6
- æç€ºãããæé ã«åŸããæåŸã«æ¬¡ãå
¥åããŸã
source activate <environment-name>
- å¿
èŠãªPythonããã±ãŒãžãã€ã³ã¹ããŒã«ããŸãã æãéèŠãªã®ã¯ã ãã©ã¹ã³ãšgunicornã§ãã
2ïŒ gunicornã䜿çšããŠãã·ã³ãã«ãªãHello worldãFlaskã¢ããªã±ãŒã·ã§ã³ãäœæããããšããŸãã- ãæ°ã«å
¥ãã®ããã¹ããšãã£ã¿ãŒãéãããã©ã«ããŒã«
hello-world.py
ãã¡ã€ã«ãäœæããŸã - 次ã®ã³ãŒããèšè¿°ããŸãã
"""Filename: hello-world.py """ from flask import Flask app = Flask(__name__) @app.route('/users/<string:username>') def hello_world(username=None): return("Hello {}!".format(username))
- ãã¡ã€ã«ãä¿åããŠãã¿ãŒããã«ã«æ»ããŸãã
- APIãéå§ããã«ã¯ãã¿ãŒããã«ã§å®è¡ããŸãïŒ
gunicorn --bind 0.0.0.0:8000 hello-world:app
- 以äžãåŸãããã°ãããªãã¯æ£ããè»éã«ä¹ã£ãŠããŸãã

- ãã©ãŠã¶ã§ã次ãå
¥åããŸã
https://localhost:8000/users/any-name

ãã£ãïŒ åããŠã®Flaskããã°ã©ã ãäœæããŸããïŒ ãããã®ç°¡åãªæé ã®çµéšããããããããŒã«ã«ã«ã¢ã¯ã»ã¹ã§ãããããã¯ãŒã¯ãšã³ããã€ã³ããäœæã§ããŸãã
Flaskã䜿çšãããšãã¢ãã«ãã©ããããŠWeb APIãšããŠäœ¿çšã§ããŸãã ããè€éãªãããã¯ãŒã¯ã¢ããªã±ãŒã·ã§ã³ïŒJavaScriptãªã©ïŒãäœæããå Žåã¯ãããã€ãã®å€æŽã远å ããå¿
èŠããããŸãã
æ©æ¢°åŠç¿ã¢ãã«ã®äœæã- å§ããã«ã¯ã ããŒã³äºæž¬ç«¶äºæ©æ¢°åŠç¿ã³ã³ãã¹ããå§ããŸãããã äž»ãªç®çã¯ãååŠçãã€ãã©ã€ã³ãæ§æããå±éäžã®äºæž¬ã¿ã¹ã¯ã容æã«ããããã®MLã¢ãã«ãäœæããããšã§ãã
import os import json import numpy as np import pandas as pd from sklearn.externals import joblib from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.base import BaseEstimator, TransformerMixin from sklearn.ensemble import RandomForestClassifier from sklearn.pipeline import make_pipeline import warnings warnings.filterwarnings("ignore")
- ããŒã¿ã»ããããã©ã«ããŒã«ä¿åããŸãã
!ls /home/pratos/Side-Project/av_articles/flask_api/data/
test.csv training.csv
data = pd.read_csv('../data/training.csv')
list(data.columns)
['Loan_ID', 'Gender', 'Married', 'Dependents', 'Education', 'Self_Employed', 'ApplicantIncome', 'CoapplicantIncome', 'LoanAmount', 'Loan_Amount_Term', 'Credit_History', 'Property_Area', 'Loan_Status']
data.shape
(614, 13)
ul>
åã§null / Nanå€ãèŠã€ããŸãã
for _ in data.columns: print("The number of null values in:{} == {}".format(_, data[_].isnull().sum()))
The number of null values in:Loan_ID == 0 The number of null values in:Gender == 13 The number of null values in:Married == 3 The number of null values in:Dependents == 15 The number of null values in:Education == 0 The number of null values in:Self_Employed == 32 The number of null values in:ApplicantIncome == 0 The number of null values in:CoapplicantIncome == 0 The number of null values in:LoanAmount == 22 The number of null values in:Loan_Amount_Term == 14 The number of null values in:Credit_History == 50 The number of null values in:Property_Area == 0 The number of null values in:Loan_Status == 0
- 次ã®ã¹ãããã¯ããã¬ãŒãã³ã°ãšãã¹ãçšã®ããŒã¿ã»ãããäœæããããšã§ãã
red_var = ['Gender','Married','Dependents','Education','Self_Employed','ApplicantIncome','CoapplicantIncome',\ 'LoanAmount','Loan_Amount_Term','Credit_History','Property_Area'] X_train, X_test, y_train, y_test = train_test_split(data[pred_var], data['Loan_Status'], \ test_size=0.25, random_state=42)
- å®éšã®åŸã§ããã¹ãŠã®ååŠçã¹ããããæ£ããå®äºããäºæž¬äžã«äœãèŠèœãšããªãããã«ããããã«ãååŠççšã®ç¬èªã®Scikit-learnãšããªã¥ãšãŒã¿ãŒïŒååŠçScikit-learnãšã¹ãã£ã¡ãŒã¿ãŒïŒãäœæããŸãã
äœææ¹æ³ãçè§£ããã«ã¯ã
以äžããèªã¿ãã ããã
from sklearn.base import BaseEstimator, TransformerMixin class PreProcessing(BaseEstimator, TransformerMixin): """Custom Pre-Processing estimator for our use-case """ def __init__(self): pass def transform(self, df): """Regular transform() that is a help for training, validation & testing datasets (NOTE: The operations performed here are the ones that we did prior to this cell) """ pred_var = ['Gender','Married','Dependents','Education','Self_Employed','ApplicantIncome',\ 'CoapplicantIncome','LoanAmount','Loan_Amount_Term','Credit_History','Property_Area'] df = df[pred_var] df['Dependents'] = df['Dependents'].fillna(0) df['Self_Employed'] = df['Self_Employed'].fillna('No') df['Loan_Amount_Term'] = df['Loan_Amount_Term'].fillna(self.term_mean_) df['Credit_History'] = df['Credit_History'].fillna(1) df['Married'] = df['Married'].fillna('No') df['Gender'] = df['Gender'].fillna('Male') df['LoanAmount'] = df['LoanAmount'].fillna(self.amt_mean_) gender_values = {'Female' : 0, 'Male' : 1} married_values = {'No' : 0, 'Yes' : 1} education_values = {'Graduate' : 0, 'Not Graduate' : 1} employed_values = {'No' : 0, 'Yes' : 1} property_values = {'Rural' : 0, 'Urban' : 1, 'Semiurban' : 2} dependent_values = {'3+': 3, '0': 0, '2': 2, '1': 1} df.replace({'Gender': gender_values, 'Married': married_values, 'Education': education_values, \ 'Self_Employed': employed_values, 'Property_Area': property_values, \ 'Dependents': dependent_values}, inplace=True) return df.as_matrix() def fit(self, df, y=None, **fit_params): """Fitting the Training dataset & calculating the required values from train eg: We will need the mean of X_train['Loan_Amount_Term'] that will be used in transformation of X_test """ self.term_mean_ = df['Loan_Amount_Term'].mean() self.amt_mean_ = df['LoanAmount'].mean() return self
y_train
ããã³y_test
ãnp.array
倿ãnp.array
ã
y_train = y_train.replace({'Y':1, 'N':0}).as_matrix() y_test = y_test.replace({'Y':1, 'N':0}).as_matrix()
ãã€ãã©ã€ã³ãäœæããŠãå®è¡ãããã¹ãŠã®ååŠçã¹ããããscikit-learnè©äŸ¡è
ã®äœæ¥ã§ããããšã確èªããŠã¿ãŸãããã
pipe = make_pipeline(PreProcessing(), RandomForestClassifier())
pipe
Pipeline(memory=None, steps=[('preprocessing', PreProcessing()), ('randomforestclassifier', RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini', max_depth=None, max_features='auto', max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1, oob_score=False, random_state=None, verbose=0, warm_start=False))])
é©åãªãã€ããŒãã©ã¡ãŒã¿ãŒïŒå€é
åŒãªããžã§ã¯ãã®æ¬¡æ°ãšãšããžã®ã¢ã«ãã¡ïŒãââæ€çŽ¢ããã«ã¯ãã°ãªããæ€çŽ¢ïŒã°ãªããæ€çŽ¢ïŒãå®è¡ããŸãã
- param_gridãå®çŸ©ããŸãã
param_grid = {"randomforestclassifier__n_estimators" : [10, 20, 30], "randomforestclassifier__max_depth" : [None, 6, 8, 10], "randomforestclassifier__max_leaf_nodes": [None, 5, 10, 20], "randomforestclassifier__min_impurity_split": [0.1, 0.2, 0.3]}
- ã°ãªããæ€çŽ¢ãéå§ããŸãã
grid = GridSearchCV(pipe, param_grid=param_grid, cv=3)
- ãã€ãã©ã€ã³æšå®åšã®ãã¬ãŒãã³ã°ããŒã¿ã調æŽããŸãã
grid.fit(X_train, y_train)
GridSearchCV(cv=3, error_score='raise', estimator=Pipeline(memory=None, steps=[('preprocessing', PreProcessing()), ('randomforestclassifier', RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini', max_depth=None, max_features='auto', max_leaf_nodes=None, min_impurity_decrease=0.0, min_impu..._jobs=1, oob_score=False, random_state=None, verbose=0, warm_start=False))]), fit_params=None, iid=True, n_jobs=1, param_grid={'randomforestclassifier__n_estimators': [10, 20, 30], 'randomforestclassifier__max_leaf_nodes': [None, 5, 10, 20], 'randomforestclassifier__min_impurity_split': [0.1, 0.2, 0.3], 'randomforestclassifier__max_depth': [None, 6, 8, 10]}, pre_dispatch='2*n_jobs', refit=True, return_train_score=True, scoring=None, verbose=0)
- ã°ãªããæ€çŽ¢ãéžæãããã©ã¡ãŒã¿ãŒãèŠãŠã¿ãŸãããã
print("Best parameters: {}".format(grid.best_params_))
Best parameters: {'randomforestclassifier__n_estimators': 30, 'randomforestclassifier__max_leaf_nodes': 20, 'randomforestclassifier__min_impurity_split': 0.2, 'randomforestclassifier__max_depth': 8}
print("Validation set score: {:.2f}".format(grid.score(X_test, y_test)))
Validation set score: 0.79
- ãã¹ãã¹ã€ãŒããããŠã³ããŒãããŸãã
test_df = pd.read_csv('../data/test.csv', encoding="utf-8-sig") test_df = test_df.head()
grid.predict(test_df)
array([1, 1, 1, 1, 1])
ãã€ãã©ã€ã³ã¯ã次ã®éèŠãªã¹ãããã§ããæ©æ¢°åŠç¿ã¢ãã«ã®ã·ãªã¢ã«åã«é²ãã®ã«ååãªããã§ãã
æ©æ¢°åŠç¿ã¢ãã«ã®ä¿åïŒã·ãªã¢ã«åãšéã·ãªã¢ã«åããã³ã³ãã¥ãŒã¿ãŒãµã€ãšã³ã¹ã§ã¯ãããŒã¿ã¹ãã¬ãŒãžã®ã³ã³ããã¹ãã§ãã·ãªã¢ã«åãšã¯ãããŒã¿æ§é ãŸãã¯ãªããžã§ã¯ãã®ç¶æ
ãä¿åããã圢åŒïŒããšãã°ããã¡ã€ã«ãŸãã¯ã¡ã¢ãªãããã¡ãŒïŒã«å€æããåŸã§åããŸãã¯å¥ã®ã³ã³ãã¥ãŒã¿ãŒç°å¢ã§åæ§ç¯ããããã»ã¹ã§ããã
Pythonã§ã¯ããªããžã§ã¯ããä¿åããåŸã§å
ã®ç¶æ
ã§ååŸããããã®æšæºçãªæ¹æ³ã¯ãé
žæŽãã§ãã ããããããããããã«ãç°¡åãªäŸã瀺ããŸãã
list_to_pickle = [1, 'here', 123, 'walker']
list_pickle
b'\x80\x03]q\x00(K\x01X\x04\x00\x00\x00hereq\x01K{X\x06\x00\x00\x00walkerq\x02e.'
次ã«ã猶詰ãªããžã§ã¯ããå床ã¢ã³ããŒãããŸãã
loaded_pickle = pickle.loads(list_pickle)
loaded_pickle
[1, 'here', 123, 'walker']
猶詰ã®ãªããžã§ã¯ãããã¡ã€ã«ã«ä¿åããŠäœ¿çšã§ããŸãã ãã®æ¹æ³ã¯ãRããã°ã©ãã³ã°ãªã©ã®
.rda
ãã¡ã€ã«ã®äœæã«äŒŒãŠããŸãã
泚ïŒã·ãªã¢ã«åã®ããã®ãã®ä¿åæ¹æ³ãæ°ã«å
¥ããªã人ãããŸãã 代ããã«
h5py
䜿çšã§ããŸãã
ã«ã¹ã¿ã ã¯ã©ã¹ïŒã¯ã©ã¹ïŒãããããã¬ãŒãã³ã°ã®é²è¡äžã«ã€ã³ããŒãããå¿
èŠãããããã
dill
ã¢ãžã¥ãŒã«ã䜿çšããŠã¯ã©ã¹ãšããªã¥ãšãŒã¿ãŒãã°ãªãããªããžã§ã¯ãã«ããã±ãŒãžåããŸãã
ã¢ãã«ããã¬ãŒãã³ã°ããããã®ãã¹ãŠã®ã³ãŒããå«ãåå¥ã®
training.py
ãã¡ã€ã«ãäœæããããšããå§ãããŸãã ïŒäŸã¯
ãã¡ãã«ãããŸã ïŒã
dill
ãã€ã³ã¹ããŒã«ãã
!pip install dill
Requirement already satisfied: dill in /home/pratos/miniconda3/envs/ordermanagement/lib/python3.5/site-packages
import dill as pickle filename = 'model_v1.pk'
with open('../flask_api/models/'+filename, 'wb') as file: pickle.dump(grid, file)
ã¢ãã«ã¯äžèšã§éžæãããã£ã¬ã¯ããªã«ä¿åãããŸãã ã¢ãã«ãäžæåæ¢ãããšãFlaskã©ãããŒã§ã©ããã§ããŸãã ãã ãããã®åã«ã猶詰ãã¡ã€ã«ãæ©èœããããšã確èªããå¿
èŠããããŸãã ãããããŒãããŠãäºæž¬ãè¡ããŸãããã
with open('../flask_api/models/'+filename ,'rb') as f: loaded_model = pickle.load(f)
loaded_model.predict(test_df)
array([1, 1, 1, 1, 1])
ååŠçæé ã«åŸã£ãŠãæ°ããå°çããããŒã¿ããã€ãã©ã€ã³ã®äžéšã«ãªãããã«ããã®ã§ãåã«predictïŒïŒãå®è¡ããå¿
èŠããããŸãã scikit-learnã©ã€ãã©ãªã䜿çšãããšããã€ãã©ã€ã³ãç°¡åã«æäœã§ããŸãã æåã®å®è£
ãã¯ã€ã«ãã«æããŠããéå®å£«ãšãã€ãã©ã€ã³ãããªãã®æéãšç¥çµã®äžè©±ãããŸãã
Flaskã䜿çšããŠAPIãäœæãããã©ã«ãæ§é ãã§ããéãã·ã³ãã«ã«ããŸãããã

ã©ãããŒ
apicall()
颿°ãäœæããã«ã¯ã3ã€ã®éèŠãªéšåããããŸãã
request
ããŒã¿ã®åä¿¡ïŒäºæž¬ãè¡ãããïŒ;- 猶詰ã®éå®å£«ãããŒãããŸãã
- JSON圢åŒã§ã®äºæž¬ã®ç¿»èš³ãšå¿ç
status code: 200
åä¿¡status code: 200
;
HTTPã¡ãã»ãŒãžã¯ãããããŒã𿬿ããäœæãããŸãã äžè¬ã«ãæ¬æã®ã³ã³ãã³ãã¯JSON圢åŒã§éä¿¡ãããŸãã äºæž¬ãåä¿¡ããããã®ããã±ãŒãžãšããŠãåä¿¡ããŒã¿ãïŒ
POST url-endpoint/
ïŒéä¿¡ããŸãã
泚ïŒåœ¢åŒã®äºææ§ã®ããã«ããã¬ãŒã³ããã¹ããXMLãcvsããŸãã¯ç»åãçŽæ¥éä¿¡ã§ããŸããããã®å Žåã¯JSONã䜿çšããããšããå§ãããŸãã
"""Filename: server.py """ import os import pandas as pd from sklearn.externals import joblib from flask import Flask, jsonify, request app = Flask(__name__) @app.route('/predict', methods=['POST']) def apicall(): """API Call Pandas dataframe (sent as a payload) from API Call """ try: test_json = request.get_json() test = pd.read_json(test_json, orient='records')
å®è¡åŸã次ãå
¥åããŸãïŒ
gunicorn --bind 0.0.0.0:8000 server:app
https:0.0.0.0:8000/predict
APIã®ããŒã«ã«èµ·åã®äºæž¬ãšãã¥ãŒã®ããŒã¿ãçæããŸããã
import json import requests
"""Setting the headers to send and accept json responses """ header = {'Content-Type': 'application/json', \ 'Accept': 'application/json'} """Reading test batch """ df = pd.read_csv('../data/test.csv', encoding="utf-8-sig") df = df.head() """Converting Pandas Dataframe to json """ data = df.to_json(orient='records')
data
'[{"Loan_ID":"LP001015","Gender":"Male","Married":"Yes","Dependents":"0","Education":"Graduate","Self_Employed":"No","ApplicantIncome":5720,"CoapplicantIncome":0,"LoanAmount":110.0,"Loan_Amount_Term":360.0,"Credit_History":1.0,"Property_Area":"Urban"},{"Loan_ID":"LP001022","Gender":"Male","Married":"Yes","Dependents":"1","Education":"Graduate","Self_Employed":"No","ApplicantIncome":3076,"CoapplicantIncome":1500,"LoanAmount":126.0,"Loan_Amount_Term":360.0,"Credit_History":1.0,"Property_Area":"Urban"},{"Loan_ID":"LP001031","Gender":"Male","Married":"Yes","Dependents":"2","Education":"Graduate","Self_Employed":"No","ApplicantIncome":5000,"CoapplicantIncome":1800,"LoanAmount":208.0,"Loan_Amount_Term":360.0,"Credit_History":1.0,"Property_Area":"Urban"},{"Loan_ID":"LP001035","Gender":"Male","Married":"Yes","Dependents":"2","Education":"Graduate","Self_Employed":"No","ApplicantIncome":2340,"CoapplicantIncome":2546,"LoanAmount":100.0,"Loan_Amount_Term":360.0,"Credit_History":null,"Property_Area":"Urban"},{"Loan_ID":"LP001051","Gender":"Male","Married":"No","Dependents":"0","Education":"Not Graduate","Self_Employed":"No","ApplicantIncome":3276,"CoapplicantIncome":0,"LoanAmount":78.0,"Loan_Amount_Term":360.0,"Credit_History":1.0,"Property_Area":"Urban"}]'
"""POST <url>/predict """ resp = requests.post("http://0.0.0.0:8000/predict", \ data = json.dumps(data),\ headers= header)
resp.status_code
200
"""The final response we get is as follows: """ resp.json()
{'predictions': '[{"0":"LP001015","1":1},{...
ãããã«ãã®èšäºã§ã¯ãäºæž¬ãæäŸããå®çšçãªAPIãäœæããéäžã§ãMLãœãªã¥ãŒã·ã§ã³ãéçºæžã¿ã¢ããªã±ãŒã·ã§ã³ã«çŽæ¥çµ±åããããšã«äžæ©è¿ã¥ããŸããã 補åã®ãããã¿ã€ãã³ã°ã«åœ¹ç«ã¡ã補åãçã«æ©èœãããã®ã«åœ¹ç«ã€éåžžã«ã·ã³ãã«ãªAPIãäœæããŸãããã補åã補åã«éä¿¡ããã«ã¯ãæ©æ¢°åŠç¿ã®åéã§ã¯ãªããªã£ã調æŽãè¡ãå¿
èŠããããŸãã
APIãäœæããéã«çæãã¹ãç¹ãããã€ããããŸãã
- ã¹ãã²ããã£ã³ãŒãããé«å質ã®APIãäœæããããšã¯ã»ãšãã©äžå¯èœã§ãããããæ©æ¢°åŠç¿ã®ç¥èãæŽ»çšããŠã䟿å©ã§äŸ¿å©ãªAPIãäœæããŸãã
- ã¢ãã«ãšAPIã³ãŒãã®ããŒãžã§ã³ç®¡çã䜿çšããŠã¿ãŠãã ããã Flaskã¯ããŒãžã§ã³ç®¡çããŒã«ã®ãµããŒããæäŸããªãããšã«æ³šæããŠãã ããã MLã¢ãã«ã®ä¿åãšè¿œè·¡ã¯å°é£ãªäœæ¥ã§ããã䟿å©ãªæ¹æ³ãèŠã€ããŠãã ããã ãããè¡ãæ¹æ³ã«ã€ããŠèª¬æããŠããèšäºãããã«ãããŸãã
- scikit-learnã¢ãã«ã®ä»æ§ã«ããããšããªã¥ãšãŒã¿ãŒãšãã¬ãŒãã³ã°ã³ãŒãã飿¥ããŠããããšã確èªããå¿
èŠããããŸãïŒååŠçãŸãã¯ä»ã®åæ§ã®ã¿ã¹ã¯ã«ã«ã¹ã¿ã ãšããªã¥ãšãŒã¿ãŒã䜿çšããŠããå ŽåïŒã ãããã£ãŠãæ¢å®ã®ã¢ãã«ã«ã¯ããã®æšªã«ã¯ã©ã¹ãšããªã¥ãšãŒã¿ãŒããããŸãã
次ã®è«ççãªã¹ãããã¯ããã®ãããªAPIãå°ããªä»®æ³ãã·ã³ã«ãããã€ããããã®ã¡ã«ããºã ãäœæããããšã§ãã ããã«ã¯ããŸããŸãªæ¹æ³ããããŸãããæ¬¡ã®èšäºã§ããããåãäžããŸãã
ãã®èšäºã®ã³ãŒããšèª¬ææçšãªãœãŒã¹ïŒ[1]
ããŒã¿ããã¯ã«ã¹ã«ããªãã§ãã ããã[2]
Scikit Learnäºæãã©ã³ã¹ãã©ãŒããŒã®æ§ç¯ ã
[3]
Flaskã§ã®jsonifyã®äœ¿çš ã
[4]
Flask-QuickStartããã¡ãããã®ãããªè³æã§ãã ãã®åºçç©ãæ°ã«å
¥ã£ãããç§ãã¡ã賌èªãã5幎ã®çµéšãæã€éçºè
ããã³ããŒã¿ç§åŠè
-Alexander Nikitinã 3æ12æ¥ã«éå¬ãããããã¯ãMetric Classification Algorithmsãã«é¢ããç¡æã®
ãªãŒãã³ãŠã§ãããŒã«ãµã€ã³ã¢ããããŸãã