LoginSignup
5
6

More than 3 years have passed since last update.

PythonでつくったモデルをWatson Machine LearningでREST API化(CP4D編)

Posted at

Cloud pak for Data 3.0.1(以下CP4D) でPythonでつくったモデルをREST API化します。
Watson Stuido Localという開発環境でモデルを作成し、Watson Machine Learningという実行環境にデプロイすることでREST API化することができます。
REST API化するとつくったモデルを外部のアプリケーションから呼び出すことが可能になります。例えば、Webの回遊行動から購入を予測するようなモデルを作れば、スマホのアプリにリアルタイムにその広告をだしたりすることができます。また、装置のセンサーデータから故障を予想するようなモデルを作れば、リアルタイムに故障の可能性があることを通知するようなことができます。

image.png

サポートされているフレームワークは以下になります。scikitlearnやKeras、xgboostなどがサポートされています。
Framework support details
https://www.ibm.com/support/knowledgecenter/en/SSQNUZ_3.0.1/wos/wos-frameworks-wml-cloud.html

■テスト環境
CP4D: 3.0.1
WML Client: 1.0.103
Scikitlearn: 0.22.1

①プロジェクト作成

最初にモデルを作成するNotebookを作るためにプロジェクトを作成します。すでにプロジェクトがある場合にはそれをつかっていただいて構いません。その場合は②に進んでください。

image.png

CP4Dのメニューからプロジェクトを選択します

image.png

新しいプロジェクトを作成します。
image.png

分析プロジェクトを選択し、次へをクリックしてください。
image.png

空のプロジェクトを作成します。
image.png

名前を設定して、作成します。
image.png

②プロジェクトのDeployment Space連携

Watson Machine LearningでREST API化するためにはWatson Machine Learning内にDeployment Spaceという場所を用意し、そこに作成したモデルを保管する必要があります。ここではWatson Studioのプロジェクトに対応するDeployment Spaceを設定します。

image.png

プロジェクトの設定タブに移ります。
image.png

デプロイメントスペースの関連付けボタンをクリックしてください。
image.png

既存のDeployment Spaceがある場合はそれを選択しても構いませんが、ここでは新規に作成し、関連付けをクリックします。
image.png

以下のように関連付けができたことを確認します。
image.png

注:正確に言えば、デプロイメント・スペースの作成は必須ですが、プロジェクトとデプロイメント・スペースを関連付けること自体は必須ではありません。関連付けられていないデプロイメント・スペースにもモデルを保存することはできます。ただ、関連付けをしておくことでデプロイメント・スペースのuidを見つけやすくすることができ、便利になります。

③ScikitLearnモデル作成

Watson StudioのNotebookでScikitLearnの予測モデルを作成します。

image.png

資産タブに移り、プロジェクトに追加ボタンをクリックしてください。
image.png

Notebookをクリックしてください。
image.png

「URLから」を選択し、任意の名前を指定します。
ノートブックURLに以下のURLを指定します。
https://raw.githubusercontent.com/hkwd/200701WML/master/cp4d301/iris_WMLCP4D301pub.ipynb
設定ができたら、ノートブックの作成をクリックしてください。
image.png

モデル作成のセルを実行してください。
Scikitlearnのライブラリに入っているirisのデータを読み込んでモデルを作っています。modelという変数にモデルが格納されました。

"sepallength"(ガクの長さ), "sepalwidth"(ガクの幅), "petallength"(花弁の長さ), "petalwidth"(花弁の幅)をつかって、アヤメの種類であるSetosa、Virginica、Versicolorのいずれかを判別予測するモデルになっています。predictionが判別結果で、0がSetosa、1がVirginica、2がVersicolorを意味しています。Setosa_prob、Virginica_prob、Versicolor_probの各列はそれぞれのアヤメの種類である確率を意味しています。以下の例の0番目のアヤメで言うと80%の確率でVirginica種であると予測したことになります。

image.png

④WML Clientの接続

プロジェクトやデプロイメント・スペースにモデルを格納したり、デプロイしたりするために、NotebookからWatson Machine Learningのクライアント・ライブラリを読み込み、Watson Machine Learningのサービスに接続します。

image.png

Watson Machine Learningのクライアント・ライブラリ(watson-machine-learning-client-V4)はCP4DのPython環境では読み込まれているのですが、バージョンが1.0.95とやや古くCP4D3.0.1に対応できていないので、まず、pipで更新してください。ここではバージョン1.0.103を使いました。

!pip install --upgrade  watson-machine-learning-client-V4

以下でWMLクライアントでWatson Machine Learningのサービスに接続します。
clientというオブジェクトでWatson Machine Learningの操作が可能になります。

import sys,os,os.path

token = os.environ['USER_ACCESS_TOKEN']
from watson_machine_learning_client import WatsonMachineLearningAPIClient

wml_credentials = {
   "token": token,
   "instance_id" : "wml_local",
   "url": os.environ['RUNTIME_ENV_APSX_URL'],
   "version": "3.0.1"
}

client = WatsonMachineLearningAPIClient(wml_credentials)

⑤プロジェクトにモデル登録

先ほどインスタンス化したWMLのクライアントであるclientをつかって、プロジェクトに①でつくったirisの予測モデルであるmodelを保存します。

image.png

まず、set.default_projectでWMLクライアントでプロジェクトにつなぎます。

project_id = os.environ['PROJECT_ID']
client.set.default_project(project_id)

次にモデルのメタデータを作っていきます。メタデータにどんなものがあるかはclient.repository.ModelMetaNames.show()で調べることができます。

ここではいくつか主要なものを設定します。
以下は説明変数のスキーマを設定しています。この設定がされているとWatson Machine LearningのGUIでテスト実行をするUIが使えるようになります。
説明変数の入ったpandasのDataFrameであるx_trainから列名とデータ型を取得しています。

x_fields=[{'name': i, 'type': str(v)} for i,v in x_train.dtypes.items()]

image.png

以下は出力結果のスキーマを設定しています。基本的には定型文ですが、目的変数の入ったpandasのDataFrameであるy_trainからデータ型を取得しています。

y_fields=[{'name': 'prediction', 'type': str(y_train.dtypes[0]),'metadata': {'modeling_role': 'prediction'}}]
y_fields.append({'name': 'probability', 'type': 'list','metadata': {'modeling_role': 'probability'}})

image.png

その他、NAMEやTYPEなどのメタデータも設定し、ディクショナリにまとめます。なお、scikit learnが0.20ではRUNTIME_UIDを指定していましたが、今回モデルを作成したscikit learnが0.22の場合はRUNTIME_UIDではなくSOFTWARE_SPEC_UIDの指定が必要でした。

model_name = 'iris_skl_model'
#scikit learnが0.22の場合はRUNTIME_UIDではなくSOFTWARE_SPEC_UIDの指定が必要
sw_spec_uid = client.software_specifications.get_uid_by_name("scikit-learn_0.22-py3.6")

#モデルのメタデータを定義
pro_model_meta_props = {
    client.repository.ModelMetaNames.NAME: model_name,
    client.repository.ModelMetaNames.SOFTWARE_SPEC_UID: sw_spec_uid,
    client.repository.ModelMetaNames.TYPE: "scikit-learn_0.22",
    client.repository.ModelMetaNames.INPUT_DATA_SCHEMA:[{
        "id":"input1",
        "fields":x_fields
    }],
    client.repository.ModelMetaNames.OUTPUT_DATA_SCHEMA: {
        "id":"output",
        "fields": y_fields}
}

WMLのクライアントのrepository.store_modelのメソッドでプロジェクトの資産としてmodelを保存します。
戻り値の中にIDが含まれているので取っておきます。

#プロジェクトにモデルを保存
stored_pro_model_details = client.repository.store_model(model,
                                               meta_props=pro_model_meta_props,
                                               training_data=x_train,
                                               training_target=y_train)

pro_model_uid=stored_pro_model_details['metadata']['guid']

この時点でプロジェクトの資産をみてみるとモデルとして保存されているのがわかります。
image.png

image.png

WMLクライアントのrepository.list_models()メソッドでも同様に確認ができます。
image.png

注:正確に言えば、プロジェクトへのモデル保存は、REST API化するという目的のためには必須ではありませんが、デプロイメント・スペースに保存するモデルをプロジェクトにも保存しておくことで、Watson Studio上でもテストをしたり、GUIでデプロイメント・スペースに保存する(プロモート機能)ことができるようになります。

⑥デプロイメントスペースにモデルを登録

いよいよmodelをWatson Machine Learning内のデプロイメント・スペースに登録していきます。

image.png

Watson Data APIというREST APIをつかって②で関連付けたデプロイメント・スペースのIDを取得し、set.default_spaceメソッドで接続します。

#関連付けられたデプロイメント・スペースのIDを取得
import json, requests
# get project info
r = requests.get(os.environ['RUNTIME_ENV_APSX_URL'] + "/v2/projects/" + os.environ['PROJECT_ID'], headers = {"Authorization": "Bearer " + os.environ['USER_ACCESS_TOKEN']})
wmlProjectCompute = [c for c in r.json()["entity"]["compute"] if c["type"] == "machine_learning"][0]
space_uid = wmlProjectCompute["properties"]["space_guid"]
print(space_uid)

#デプロイメントスペースに接続
client.set.default_space(space_uid)

先ほど⑤で作成したモデルのメタデータに加えて、上で取得したデプロイメント・スペースのuidを設定します。

# モデルのメタデータにデプロイメントスペースのIDを追加
ds_model_meta_props=pro_model_meta_props
ds_model_meta_props[client.repository.ModelMetaNames.SPACE_UID]= space_uid

先ほどの⑤と同様にrepository.store_modelでmodelを保存し、戻り値からモデルのuidを取得します。

#デプロイメントスペースにモデルを保存
stored_ds_model_details = client.repository.store_model(model,
                                               meta_props=ds_model_meta_props,
                                               training_data=x_train,
                                               training_target=y_train)
ds_model_uid = stored_ds_model_details["metadata"]["guid"]

これでデプロイメント・スペースにもモデルが保存されました。
分析デプロイメントを開いてみます。
image.png

②でプロジェクトと関連付けたデプロイメント・スペースをクリックしてください。
image.png

以下のようにモデルが登録されていることがわかります。
image.png

⑦モデルをオンラインスコアリングとしてデプロイ

デプロイメント・スペースに保存したモデルをデプロイしてREST API化します。

image.png

分析デプロイメントのGUIでもデプロイは可能ですが、ここではWMLクライアントのAPIで行ってみます。

まずデプロイメントのメタデータを定義します。
client.deployments.ConfigurationMetaNames.get()でどんなメタデータがあるかは確認ができます。
ここではNAMEとONLINEを指定します。
ONLINEを指定するとREST APIで説明変数を入力すると、リアルタイムに予測結果の目的変数を返すことができます。
その他にもBATCHなどのデプロイ方法があります。

deployment_on_name = 'iris_skl_model_rt'
# オンラインスコアリングのメタデータ定義
deploy_on_meta_props = {
    client.deployments.ConfigurationMetaNames.NAME: deployment_on_name,
    client.deployments.ConfigurationMetaNames.ONLINE: {}
}

deployments.createメソッドでモデルをデプロイします。artifact_uidにはデプロイメントスペースに登録したモデルのuidを指定します。プロジェクトに保存したモデルのuidではないことに注意してください。

# モデルのデプロイ
deployment_on_details = client.deployments.create(
    artifact_uid=ds_model_uid, 
    meta_props=deploy_on_meta_props)

少し時間がかかり、以下のようなメッセージがでて、モデルがデプロイされます。

image.png

戻り値にデプロイメントのuidが含まれるのでそれを取得します。

deployment_on_uid = client.deployments.get_uid(deployment_on_details)

分析デプロイメントに移って、デプロイされていることを確認します。
image.png

image.png

先ほど登録したモデルをクリックします。
image.png

以下のようにオンラインタイプとしてデプロイされていることがわかります。
デプロイメントをクリックします。
image.png

このデプロイメントのREST APIのエンドポイントURLや様々な言語でのサンプルコードが表示されます。
image.png

⑧スコアリング

先ほどのサンプルコードなどを使って、以下の図のように外部のアプリケーションからスコアリングするのが本来の使い方ですが、ここではテストとして、WMLクライアントをつかってNotebookからスコアリングしてみます。

image.png

まずインプットデータである説明変数をテストデータのpandasから作ります。ここではx_test[0:2]で先頭から2行分を抜き出しています。

payload = {
    client.deployments.ScoringMetaNames.INPUT_DATA:[{
        "fields": x_test.columns.tolist(),
        "values": x_test[0:2].values.tolist()
    }]
}

以下のようなデータをインプットデータとして作りました。
"sepallength"(ガクの長さ), "sepalwidth"(ガクの幅), "petallength"(花弁の長さ), "petalwidth"(花弁の幅)という説明変数名とその値を[4.5, 2.3, 1.3, 0.3], [6.0, 3.4, 4.5, 1.6]という2件分与えています。

image.png

スコアリングはdeployments.scoreのメソッドで行います。デプロイメントのuidとインプットデータを与えます。

predict=client.deployments.score(deployment_on_uid, payload )
}

以下の結果が返ってきました。

image.png

1件目の結果は[1, [0.0, 0.99, 0.01]]です。まずpredictionとして1が返っていますのでVirginicaと予測しています。次のリスト[0.0, 0.99, 0.01]はSetosa_prob、Virginica_prob、Versicolor_probです。Virginicaが99%の確率だと予測しています。同様に2件目は100%の確率でSentosaだと予測しています。

まとめ

PythonのScikitLearnでつくったモデルがREST APIになり、アプリケーションから利用できるようになりました。

完成したNotebookはこちらです。
https://github.com/hkwd/200701WML/blob/master/cp4d301/iris_WMLCP4D301pub.ipynb

参考

PythonでのCloud Pak for Dataのオブジェクト操作例 (WML client, project_lib) - Qiita https://qiita.com/ttsuzuku/items/eac3e4bedc020da93bc1

5
6
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
5
6