LoginSignup
17
15

More than 5 years have passed since last update.

Pythonで機械学習 - Deployment

Last updated at Posted at 2018-02-11

BIツールTableauからPythonの機械学習モデルを呼び出す仕組みであるTabPy Serverへのデプロイを説明します。

TabPy Server

インストール

以下のサイトを参考にTabPy Serverをインストールします。

https://github.com/tableau/TabPy/blob/master/server.md

TabPy Serverは以下の2つの方法でインストールが可能です。
- セットアップスクリプトでAnaconda環境ごとインストールする
- 既存のPython環境にpipでインストールする

TabPy Serverをインストールすると、あわせてTabPy Clientもインストールされます。Clientは、Python環境からTabPy Serverへモデルをデプロイしたり、テスト用にTabPy Serverの処理を呼び出したりするのに使います。

サーバの起動

インストール後は、TabPy Serverのインストールフォルダにあるstartup.shまたはstartup.batによりTabPy Serverが起動できます。デフォルトではTabPy Serverはポート9004でListenします。

TabPy Serverの仕組み

TabPy Serverの使い方

Tabpy Serverは主に2つの使い方ができます。
- Evaluate : Pythonのコードをパラメータとして渡し、TabPy Server上で実行して結果を返却する
- Query : あらかじめ関数をエンドポイントとして登録しておき、呼び出し時にパラメータを渡して実行結果を返却する

教師あり機械学習による予測モデルを使う場合、あらかじめ予測モデルを構築するため、Queryの方を使います。
一方、クラスタリングなど教師なしモデルの場合、Evaluateでアドホックにコードを実行できます。

Tab.png
)

TabPy Serverの操作

TabPy Serverの操作はTableauからの接続の他、HTTPによるRESTでの呼び出し、またはPythonからTabPy-Clientライブラリ経由での操作が可能です。

教師ありモデルによる予測

関数のデプロイ

教師あり学習の予測モデルの場合、事前に学習済みの予測モデルを構築し、TabPy Serverにデプロイしておきます。以下に、その手順を説明します。

ライブラリをインポートします。

import tabpy_client
import pandas as pd
from sklearn.ensemble import RandomForestClassifier

データを読み込みます。

train = pd.read_csv("train_prep.csv")

学習のための説明変数と目的変数を準備します。

X_train = train[["Pclass","SexInt","AgeFillNa","IsAlone","FareFillNa","EmbarkedInt"]]
Y_train = train["Survived"]

アルゴリズムを選択して学習データを与え、予測モデルを生成します。ここではランダムフォレストを例として使います。

clf = RandomForestClassifier()
clf.fit(X_train, Y_train)
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_impurity_split=1e-07, 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)

生成した予測モデルを使って、説明変数をパラメータとして受け取って目的変数を予測する関数を定義します。

クラスを判別する関数を定義します。

def predict(Pclass,Sex,Age,SibSp,Parch,Fare,Embarked):
    SexMap = {"male":0,"female":1}
    EmbarkedMap = {"S":0,"C":1,"Q":2}
    import pandas as pd
    import numpy as np
    SexInt = map(lambda val:SexMap[val],Sex)
    IsAlone = map(lambda val:1 if val==0 else 0, np.array(SibSp) + np.array(Parch))
    EmbarkedInt = map(lambda val:EmbarkedMap[val],Embarked)
    data = pd.DataFrame({
        "Pclass":Pclass,
        "SexInt":SexInt,
        "AgeFillNa":Age,
        "IsAlone":IsAlone,
        "FareFillNa":Fare,
        "EmbarkedInt":EmbarkedInt
    })
    return clf.predict(data).tolist()

クラスに属する確率を返す関数を定義します。(任意)

def predict_proba(Pclass,Sex,Age,SibSp,Parch,Fare,Embarked):
    SexMap = {"male":0,"female":1}
    EmbarkedMap = {"S":0,"C":1,"Q":2}
    import pandas as pd
    import numpy as np
    SexInt = map(lambda val:SexMap[val],Sex)
    IsAlone = map(lambda val:1 if val==0 else 0, np.array(SibSp) + np.array(Parch))
    EmbarkedInt = map(lambda val:EmbarkedMap[val],Embarked)
    data = pd.DataFrame({
        "Pclass":Pclass,
        "SexInt":SexInt,
        "AgeFillNa":Age,
        "IsAlone":IsAlone,
        "FareFillNa":Fare,
        "EmbarkedInt":EmbarkedInt
    })
    return clf.predict_proba(data)[:,1].tolist()

TabPy ClientでTabPy Serverに接続します。

client = tabpy_client.Client("http://localhost:9004")

関数をデプロイします。

client.deploy("predict",predict,"predict titanic survival",override=True)
client.deploy("predict_proba",predict_proba,"predict probability of titanic survival",override=True)

デプロイした関数の確認・テスト

関数がエンドポイントとしてデプロイされていることを確認します。

client.get_endpoints()
{u'predict': {'name': 'predict', 'description': 'predict titanic survival', 'creation_time': datetime.datetime(2018, 2, 10, 16, 3, 43), 'version': 8, 'dependencies': [], 'last_modified_time': datetime.datetime(2018, 2, 11, 5, 50, 54), 'schema': None, 'type': 'model'},
 u'predict_proba': {'name': 'predict_proba', 'description': 'predict probability of titanic survival', 'creation_time': datetime.datetime(2018, 2, 10, 16, 32, 34), 'version': 4, 'dependencies': [], 'last_modified_time': datetime.datetime(2018, 2, 11, 5, 50, 54), 'schema': None, 'type': 'model'}}

関数を実行してみます。

client.query("predict",[1,3],["male","female"],[0,30],[0,0],[0,1],[20,40],["Q","S"])
{u'model': u'predict',
 u'response': [1, 0],
 u'uuid': u'c9f6230a-c8c7-4b9e-b50c-cffe4d242e64',
 u'version': 8}

REST APIでの関数実行も試してみます。

import requests
url = "http://localhost:9004/query/predict_proba"
payload = """
{
    "data":{
        "Pclass":[1,3],
        "Sex":["male","male"],
        "Age":[0,30],
        "SibSp":[0,0],
        "Parch":[0,1],
        "Fare":[20,40],
        "Embarked":["Q","S"]
    }
}
"""
res = requests.post(url,data=payload)
print res.text
{"model": "predict_proba", "version": 4, "response": [0.9, 0.0], "uuid": "d4bcd22c-d055-4777-8424-afb841957ace"}

Tableauからの呼び出し

Tableauから呼び出す場合、以下の手順を実施します。
- ヘルプから外部サーバ接続の設定を表示し、TabPy ServerのURL、ポート番号をセット
- 関数を定義し、SCRIPT_XXX関数を計算式として定義

計算式の例(エンドポイント呼び出しの場合):

SCRIPT_INT('return tabpy.query("predict",_arg1,_arg2)["response"]',AVG([Pclass]),AVG(Age))

戻る

17
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
15