更新履歴:
(2020/9/8) WML client初期化でのversion番号を自動取得するように変更
はじめに
Cloud Pak for Data (以下CP4D)の分析プロジェクトでNotebook (Jupyter Notebook)でモデルを作る場合、データの取り込みやモデルの格納、作ったモデルのデプロイなどを行うためのライブラリとしてwatson-machine-learning-client-V4 (以下WML client)1とproject_lib2があります。どちらもCP4DのNotebookの標準Python環境にデフォルトで入ってます。
この記事では、これらのライブラリの具体的な使い方を紹介します。
なお、WML clientはURLを指定して認証も行うため、CP4D外のPython環境でも動作します。外部のバッチプログラムなどからCP4D内のモデルやデプロイメントなどのオブジェクト操作手段としても使えます。
(動作確認済バージョン)
- Cloud Pak for Data v2.5 / v3.0LA / v3.0.1
- WML client v1.0.64 / v1.0.103
- project_lib v1.7.1
Notebookでのpipコマンドでの確認方法
!pip show watson-machine-learning-client-V4
Name: watson-machine-learning-client-V4
Version: 1.0.64
Summary: Watson Machine Learning API Client
Home-page: http://wml-api-pyclient-v4.mybluemix.net
Author: IBM
Author-email: svagaral@in.ibm.com, nagiredd@in.ibm.com, kamigupt@in.ibm.com
License: BSD
Location: /opt/conda/envs/Python-3.6-WMLCE/lib/python3.6/site-packages
Requires: urllib3, pandas, tabulate, requests, lomond, tqdm, ibm-cos-sdk, certifi
Required-by:
!pip show project_lib
Name: project-lib
Version: 1.7.1
Summary: programmatic interface for accessing project assets in IBM Watson Studio
Home-page: https://github.ibm.com/ax/project-lib-python
Author: IBM Watson Studio - Notebooks Team
Author-email: None
License: UNKNOWN
Location: /opt/conda/envs/Python-3.6-WMLCE/lib/python3.6/site-packages
Requires: requests
Required-by:
CP4D上での主な操作と使用するライブラリ一覧
データ資産(Data Asset)、モデル(Models)、関数(Functions)、デプロイメント(Deployments)などを生成したり、保存したりできます。また、作成したデプロイメントを実行することも可能です。
分析プロジェクトに対する操作
データ資産は主にproject_libを使用し、モデル系はWML clientを使用します。
主な操作 | 使用するライブラリ |
---|---|
データ資産からのデータの読み込み3 | project_lib または、 pandas.read_csvで'/project_data/data_asset/ファイル名'を直接読む |
データ資産へのファイルデータの出力4 | project_lib |
データ資産の一覧表示 | WML client |
モデルの保存 | WML client |
モデルの一覧表示 | WML client |
関数の保存 | WML client |
関数の一覧表示 | WML client |
デプロイメントスペース(分析デプロイメント)に対する操作
全てWML clientを使用します。
主な操作 | 使用するライブラリ |
---|---|
データ資産へのファイルデータの出力 | WML client |
データ資産の一覧表示 | WML client |
モデルの保存 | WML client |
モデルの一覧表示 | WML client |
機能(関数)の保存5 | WML client |
機能(関数)の一覧表示5 | WML client |
デプロイメントの作成 | WML client |
デプロイメントの一覧表示 | WML client |
デプロイメントの実行 | WML client |
WML clientのインポートと初期化
WML clientのインポート
from watson_machine_learning_client import WatsonMachineLearningAPIClient
WML clientの初期化(認証)
接続先や認証情報を付与して、WML clientを初期化します。認証情報の取得方法は2種類あります。
- OS環境変数 USER_ACCESS_TOKEN の値を使う
- CP4Dユーザー名とパスワードを使う
1はCP4D上のNotebookで使える方法。もし、CP4D外の環境でWML clientを使うときは2です。
注意事項としては、
- instance_id は "wml_local" または "openshift" とします。マニュアルには前者が記載されてますが、後者を使うようガイドされたことがあります。実質的にはどちらでも動くようです。
- urlは、使用しているCP4D環境のURL(https://ホスト名 or IPアドレス(:ポート番号))とします。最後にスラッシュを付けないことがポイントです。付けたら後続の処理でエラーになります(ハマりポイント)。
- versionは、2.5の場合は"2.5.0"、3.0LAなら"3.0.0"、3.0GAなら"3.0.1" -> (2020/9/8更新) 方法1はrequestsを使ってバージョン番号を自動で取得する方法に変更しました。
import requests, os
token = os.environ['USER_ACCESS_TOKEN']
url = "https://cp4d.host.name.com"
version = requests.get(os.environ['RUNTIME_ENV_APSX_URL'] + "/diag").text[0:5]
wml_credentials = {
"token" : token,
"instance_id" : "openshift",
"url": url,
"version": version
}
client = WatsonMachineLearningAPIClient(wml_credentials)
# usernameとpasswordは、実際に認証に使うCP4Dユーザーのものを指定する
url = "https://cp4d.host.name.com"
wml_credentials = {
"username":"xxxxxxxx",
"password": "xxxxxxxx",
"instance_id": "openshift",
"url" : url,
"version": "3.0.0"
}
client = WatsonMachineLearningAPIClient(wml_credentials)
分析プロジェクトとデプロイメントスペースの切り替え
後続の処理の操作対象を、分析プロジェクト(default_project)かデプロイメントスペース(default_space)のどちらにするかをセットします。初期状態は分析プロジェクトにセットされています。
操作する対象を変更する場合は、この切替え操作を必ず実施するのを忘れないこと(ハマりポイント)。
各IDの調べ方
分析プロジェクトのIDは、OS環境変数 PROJECT_ID に入っているものを使います。
project_id = os.environ['PROJECT_ID']
デプロイメントスペースのIDは、CP4D画面のデプロイメントスペースの「設定」にある「スペースGUID」で予め調べて置くか、以下の方法でclient.repository.list_spaces() で表示されるGUIDを使います。
client.repository.list_spaces()
------------------------------------ -------------------- ------------------------
GUID NAME CREATED
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx DepSpaceName 2020-05-25T09:13:04.919Z
------------------------------------ -------------------- ------------------------
space_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
操作対象の切り替え
client.set.default_project(project_id)
client.set.default_space(space_id)
データ資産の操作
データ資産の一覧表示 (分析プロジェクト)
WML clientを使用します。
# 分析プロジェクトに切り替え(切り替える必要がある場合のみ実施)
client.set.default_project(project_id)
# データ資産の一覧を表示
client.data_assets.list()
データ資産の一覧表示 (デプロイメントスペース)
WML clientを使用します。
# デプロイメントスペースに切り替え(切り替える必要がある場合のみ実施)
client.set.default_space(space_id)
# データ資産の一覧を表示
client.data_assets.list()
データ資産からのデータの読み込み (分析プロジェクト)
Notebook画面の右上にあるデータボタン(0100と書いてある)をクリックし、該当のデータ資産名 > コードに挿入 > pandas DataFrame をクリックすることで、Notebook内のセルにコードが自動挿入されます。これを使うのが楽です。
CSVなどファイルの場合は、pandas.read_csvでデータを読むコードが自動挿入されます。df_data_XのXの部分は、挿入操作を繰り返すと自動的に増えていきます。
import pandas as pd
df_data_1 = pd.read_csv('/project_data/data_asset/filename.csv')
df_data_1.head()
project_libを使ったファイルデータを読むコード例は製品マニュアル内に例がありますが、こんなコードです。
from project_lib import Project
project = Project.access()
my_file = project.get_file("filename.csv")
my_file.seek(0)
import pandas as pd
df = pd.read_csv(my_file)
DBテーブルの場合は、前述の「コードに挿入」でproject_libを使ったコードが自動挿入されます。頭に# @hidden_cell
と入っているので、Notebookを共有する時にこのセルを含めない選択が可能です。6
# @hidden_cell
# This connection object is used to access your data and contains your credentials.
# You might want to remove those credentials before you share your notebook.
from project_lib import Project
project = Project.access()
TBL1_credentials = project.get_connected_data(name="TBL1")
import jaydebeapi, pandas as pd
TBL1_connection = jaydebeapi.connect('com.ibm.db2.jcc.DB2Driver',
'{}://{}:{}/{}:user={};password={};'.format('jdbc:db2',
TBL1_credentials['host'],
TBL1_credentials.get('port', '50000'),
TBL1_credentials['database'],
TBL1_credentials['username'],
TBL1_credentials['password']))
query = 'SELECT * FROM SCHEMANAME.TBL1'
data_df_1 = pd.read_sql(query, con=TBL1_connection)
data_df_1.head()
# You can close the database connection with the following code.
# TBL1_connection.close()
# To learn more about the jaydebeapi package, please read the documentation: https://pypi.org/project/JayDeBeApi/
データ資産へのデータの保存 (分析プロジェクト)
pandasのデータフレームをCSVファイルとして保存する方法です。project_libを使います。
from project_lib import Project
project = Project.access()
project.save_data("filename.csv", df_data_1.to_csv(),overwrite=True)
データ資産へのデータの保存 (デプロイメントスペース)
同様に、CSVファイルをデプロイメントスペースへ保存する方法です。デプロイメントスペースのデータ資産は、デプロイメントのバッチ実行時の入力データとして使用されます。
WML clientを使います。
# pandasデータフレームをCSVファイルとして一旦出力。デフォルトでは/home/wsuser/work配下に格納される
df_data_1.to_csv("filename.csv")
# デプロイメントスペースに切り替え(切り替える必要がある場合のみ実施)
client.set.default_space(space_id)
# データ資産として保存
asset_details = client.data_assets.create(name="filename.csv",file_path="/home/wsuser/work/filename.csv")
保存したデータ資産のIDやhrefは、createの戻り値asset_details内に含まれています。IDやhrefはデプロイメントスペースでデプロイメントをバッチ実行する際に使用します。
# createの戻り値(メタ情報)の確認
asset_details
{'metadata': {'space_id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
'guid': 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy',
'href': '/v2/assets/zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz?space_id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
'asset_type': 'data_asset',
'created_at': '2020-05-25T09:23:06Z',
'last_updated_at': '2020-05-25T09:23:06Z'},
'entity': {'data_asset': {'mime_type': 'text/csv'}}}
以下のように取り出します。
asset_id = client.data_assets.get_uid(asset_details)
asset_href = client.data_assets.get_href(asset_details)
asset_id = asset_details['metadata']['guid']
asset_href = asset_details['metadata']['href']
モデルの操作
準備としてモデルを作成しておく
例として、Irisのサンプルデータを使ったsckikt-learnのランダムフォレストモデルを作成します。
# Irisサンプルデータをロード
from sklearn.datasets import load_iris
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['iris_type'] = iris.target_names[iris.target]
# ランダムフォレストでモデルを作成
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
X = df.drop('iris_type', axis=1)
y = df['iris_type']
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=0)
clf = RandomForestClassifier(max_depth=2, random_state=0, n_estimators=10)
model = clf.fit(X_train, y_train)
# モデルの精度を確認
from sklearn.metrics import confusion_matrix, accuracy_score
y_test_predicted = model.predict(X_test)
print("confusion_matrix:")
print(confusion_matrix(y_test,y_test_predicted))
print("accuracy:", accuracy_score(y_test,y_test_predicted))
上記のmodel
が学習済モデルです。
モデルの保存 (分析プロジェクト)
分析プロジェクトへのモデルの保存は、デプロイのための必須操作ではないですが可能です。
WML clientを使用します。
# 分析プロジェクトに切り替え(切り替える必要がある場合のみ実施)
client.set.default_project(project_id)
# モデルのメタ情報を記述
model_name = "sample_iris_model"
meta_props={
client.repository.ModelMetaNames.NAME: model_name,
client.repository.ModelMetaNames.RUNTIME_UID: "scikit-learn_0.22-py3.6",
client.repository.ModelMetaNames.TYPE: "scikit-learn_0.22",
client.repository.ModelMetaNames.INPUT_DATA_SCHEMA:{
"id":"iris model",
"fields":[
{'name': 'sepal length (cm)', 'type': 'double'},
{'name': 'sepal width (cm)', 'type': 'double'},
{'name': 'petal length (cm)', 'type': 'double'},
{'name': 'petal width (cm)', 'type': 'double'}
]
},
client.repository.ModelMetaNames.OUTPUT_DATA_SCHEMA: {
"id":"iris model",
"fields": [
{'name': 'iris_type', 'type': 'string','metadata': {'modeling_role': 'prediction'}}
]
}
}
# モデルを保存。戻り値に作成したモデルのメタデータが含まれる
model_artifact = client.repository.store_model(model, meta_props=meta_props, training_data=X, training_target=y)
補足: モデルに含めるメタ情報
モデルに含めるメタ情報meta_propsで、INPUT_DATA_SCHEMAとOUTPUT_DATA_SCHEMAの指定は必須ではありませんが、デプロイ後のデプロイメント詳細画面でテスト実行をフォーム形式で指定したい場合は必須です。ここで指定した形式がフォーム入力の形式となります(ハマりポイント)。
指定可能なRUNTIME_UIDの調べ方
# https://wml-api-pyclient-dev-v4.mybluemix.net/#runtimes
client.runtimes.list(limit=200)
-------------------------- -------------------------- ------------------------ --------
GUID NAME CREATED PLATFORM
do_12.10 do_12.10 2020-05-03T08:35:16.679Z do
do_12.9 do_12.9 2020-05-03T08:35:16.648Z do
pmml_4.3 pmml_4.3 2020-05-03T08:35:16.618Z pmml
pmml_4.2.1 pmml_4.2.1 2020-05-03T08:35:16.590Z pmml
pmml_4.2 pmml_4.2 2020-05-03T08:35:16.565Z pmml
pmml_4.1 pmml_4.1 2020-05-03T08:35:16.537Z pmml
pmml_4.0 pmml_4.0 2020-05-03T08:35:16.510Z pmml
pmml_3.2 pmml_3.2 2020-05-03T08:35:16.478Z pmml
pmml_3.1 pmml_3.1 2020-05-03T08:35:16.450Z pmml
pmml_3.0 pmml_3.0 2020-05-03T08:35:16.422Z pmml
ai-function_0.1-py3.6 ai-function_0.1-py3.6 2020-05-03T08:35:16.378Z python
ai-function_0.1-py3 ai-function_0.1-py3 2020-05-03T08:35:16.350Z python
hybrid_0.2 hybrid_0.2 2020-05-03T08:35:16.322Z hybrid
hybrid_0.1 hybrid_0.1 2020-05-03T08:35:16.291Z hybrid
xgboost_0.90-py3.6 xgboost_0.90-py3.6 2020-05-03T08:35:16.261Z python
xgboost_0.82-py3.6 xgboost_0.82-py3.6 2020-05-03T08:35:16.235Z python
xgboost_0.82-py3 xgboost_0.82-py3 2020-05-03T08:35:16.204Z python
xgboost_0.80-py3.6 xgboost_0.80-py3.6 2020-05-03T08:35:16.173Z python
xgboost_0.80-py3 xgboost_0.80-py3 2020-05-03T08:35:16.140Z python
xgboost_0.6-py3 xgboost_0.6-py3 2020-05-03T08:35:16.111Z python
spss-modeler_18.2 spss-modeler_18.2 2020-05-03T08:35:16.083Z spss
spss-modeler_18.1 spss-modeler_18.1 2020-05-03T08:35:16.057Z spss
spss-modeler_17.1 spss-modeler_17.1 2020-05-03T08:35:16.029Z spss
scikit-learn_0.22-py3.6 scikit-learn_0.22-py3.6 2020-05-03T08:35:16.002Z python
scikit-learn_0.20-py3.6 scikit-learn_0.20-py3.6 2020-05-03T08:35:15.965Z python
scikit-learn_0.20-py3 scikit-learn_0.20-py3 2020-05-03T08:35:15.939Z python
scikit-learn_0.19-py3.6 scikit-learn_0.19-py3.6 2020-05-03T08:35:15.912Z python
scikit-learn_0.19-py3 scikit-learn_0.19-py3 2020-05-03T08:35:15.876Z python
scikit-learn_0.17-py3 scikit-learn_0.17-py3 2020-05-03T08:35:15.846Z python
spark-mllib_2.4 spark-mllib_2.4 2020-05-03T08:35:15.816Z spark
spark-mllib_2.3 spark-mllib_2.3 2020-05-03T08:35:15.788Z spark
spark-mllib_2.2 spark-mllib_2.2 2020-05-03T08:35:15.759Z spark
tensorflow_1.15-py3.6 tensorflow_1.15-py3.6 2020-05-03T08:35:15.731Z python
tensorflow_1.14-py3.6 tensorflow_1.14-py3.6 2020-05-03T08:35:15.705Z python
tensorflow_1.13-py3.6 tensorflow_1.13-py3.6 2020-05-03T08:35:15.678Z python
tensorflow_1.11-py3.6 tensorflow_1.11-py3.6 2020-05-03T08:35:15.646Z python
tensorflow_1.13-py3 tensorflow_1.13-py3 2020-05-03T08:35:15.619Z python
tensorflow_1.13-py2 tensorflow_1.13-py2 2020-05-03T08:35:15.591Z python
tensorflow_0.11-horovod tensorflow_0.11-horovod 2020-05-03T08:35:15.562Z native
tensorflow_1.11-py3 tensorflow_1.11-py3 2020-05-03T08:35:15.533Z python
tensorflow_1.10-py3 tensorflow_1.10-py3 2020-05-03T08:35:15.494Z python
tensorflow_1.10-py2 tensorflow_1.10-py2 2020-05-03T08:35:15.467Z python
tensorflow_1.9-py3 tensorflow_1.9-py3 2020-05-03T08:35:15.435Z python
tensorflow_1.9-py2 tensorflow_1.9-py2 2020-05-03T08:35:15.409Z python
tensorflow_1.8-py3 tensorflow_1.8-py3 2020-05-03T08:35:15.383Z python
tensorflow_1.8-py2 tensorflow_1.8-py2 2020-05-03T08:35:15.356Z python
tensorflow_1.7-py3 tensorflow_1.7-py3 2020-05-03T08:35:15.326Z python
tensorflow_1.7-py2 tensorflow_1.7-py2 2020-05-03T08:35:15.297Z python
tensorflow_1.6-py3 tensorflow_1.6-py3 2020-05-03T08:35:15.270Z python
tensorflow_1.6-py2 tensorflow_1.6-py2 2020-05-03T08:35:15.243Z python
tensorflow_1.5-py2-ddl tensorflow_1.5-py2-ddl 2020-05-03T08:35:15.209Z python
tensorflow_1.5-py3-horovod tensorflow_1.5-py3-horovod 2020-05-03T08:35:15.181Z python
tensorflow_1.5-py3.6 tensorflow_1.5-py3.6 2020-05-03T08:35:15.142Z python
tensorflow_1.5-py3 tensorflow_1.5-py3 2020-05-03T08:35:15.109Z python
tensorflow_1.5-py2 tensorflow_1.5-py2 2020-05-03T08:35:15.079Z python
tensorflow_1.4-py2-ddl tensorflow_1.4-py2-ddl 2020-05-03T08:35:15.048Z python
tensorflow_1.4-py3-horovod tensorflow_1.4-py3-horovod 2020-05-03T08:35:15.019Z python
tensorflow_1.4-py3 tensorflow_1.4-py3 2020-05-03T08:35:14.987Z python
tensorflow_1.4-py2 tensorflow_1.4-py2 2020-05-03T08:35:14.945Z python
tensorflow_1.3-py2-ddl tensorflow_1.3-py2-ddl 2020-05-03T08:35:14.886Z python
tensorflow_1.3-py3 tensorflow_1.3-py3 2020-05-03T08:35:14.856Z python
tensorflow_1.3-py2 tensorflow_1.3-py2 2020-05-03T08:35:14.829Z python
tensorflow_1.2-py3 tensorflow_1.2-py3 2020-05-03T08:35:14.799Z python
tensorflow_1.2-py2 tensorflow_1.2-py2 2020-05-03T08:35:14.771Z python
pytorch-onnx_1.2-py3.6 pytorch-onnx_1.2-py3.6 2020-05-03T08:35:14.742Z python
pytorch-onnx_1.1-py3.6 pytorch-onnx_1.1-py3.6 2020-05-03T08:35:14.712Z python
pytorch-onnx_1.0-py3 pytorch-onnx_1.0-py3 2020-05-03T08:35:14.682Z python
pytorch-onnx_1.2-py3.6-edt pytorch-onnx_1.2-py3.6-edt 2020-05-03T08:35:14.650Z python
pytorch-onnx_1.1-py3.6-edt pytorch-onnx_1.1-py3.6-edt 2020-05-03T08:35:14.619Z python
pytorch_1.1-py3.6 pytorch_1.1-py3.6 2020-05-03T08:35:14.590Z python
pytorch_1.1-py3 pytorch_1.1-py3 2020-05-03T08:35:14.556Z python
pytorch_1.0-py3 pytorch_1.0-py3 2020-05-03T08:35:14.525Z python
pytorch_1.0-py2 pytorch_1.0-py2 2020-05-03T08:35:14.495Z python
pytorch_0.4-py3-horovod pytorch_0.4-py3-horovod 2020-05-03T08:35:14.470Z python
pytorch_0.4-py3 pytorch_0.4-py3 2020-05-03T08:35:14.434Z python
pytorch_0.4-py2 pytorch_0.4-py2 2020-05-03T08:35:14.405Z python
pytorch_0.3-py3 pytorch_0.3-py3 2020-05-03T08:35:14.375Z python
pytorch_0.3-py2 pytorch_0.3-py2 2020-05-03T08:35:14.349Z python
torch_lua52 torch_lua52 2020-05-03T08:35:14.322Z lua
torch_luajit torch_luajit 2020-05-03T08:35:14.295Z lua
caffe-ibm_1.0-py3 caffe-ibm_1.0-py3 2020-05-03T08:35:14.265Z python
caffe-ibm_1.0-py2 caffe-ibm_1.0-py2 2020-05-03T08:35:14.235Z python
caffe_1.0-py3 caffe_1.0-py3 2020-05-03T08:35:14.210Z python
caffe_1.0-py2 caffe_1.0-py2 2020-05-03T08:35:14.180Z python
caffe_frcnn caffe_frcnn 2020-05-03T08:35:14.147Z Python
caffe_1.0-ddl caffe_1.0-ddl 2020-05-03T08:35:14.117Z native
caffe2_0.8 caffe2_0.8 2020-05-03T08:35:14.088Z Python
darknet_0 darknet_0 2020-05-03T08:35:14.059Z native
theano_1.0 theano_1.0 2020-05-03T08:35:14.032Z Python
mxnet_1.2-py2 mxnet_1.2-py2 2020-05-03T08:35:14.002Z python
mxnet_1.1-py2 mxnet_1.1-py2 2020-05-03T08:35:13.960Z python
-------------------------- -------------------------- ------------------------ --------
他にもmeta_propsに含められるメタ情報はあり、作成したモデルがどのような条件下で作成されたのかを記録しておけるので、できるだけ付与しておくことが一般的にはおすすめです。
meta_propsに記述できるメタ情報
client.repository.ModelMetaNames.get()
['CUSTOM',
'DESCRIPTION',
'DOMAIN',
'HYPER_PARAMETERS',
'IMPORT',
'INPUT_DATA_SCHEMA',
'LABEL_FIELD',
'METRICS',
'MODEL_DEFINITION_UID',
'NAME',
'OUTPUT_DATA_SCHEMA',
'PIPELINE_UID',
'RUNTIME_UID',
'SIZE',
'SOFTWARE_SPEC_UID',
'SPACE_UID',
'TAGS',
'TRAINING_DATA_REFERENCES',
'TRAINING_LIB_UID',
'TRANSFORMED_LABEL_FIELD',
'TYPE']
モデルの保存 (デプロイメントスペース)
WML clientを使用して、デプロイメントスペースにモデルを保存します。
その他の方法として、モデルを上記の操作で分析プロジェクトに保存した後、CP4D画面上で該当モデルの"プロモート"をクリックすることで、分析プロジェクトのモデルをデプロイメントスペースへコピー保存することでも同じ結果になります。
# デプロイメントスペースに切り替え(切り替える必要がある場合のみ実施)
client.set.default_space(space_id)
# モデルのメタ情報を記述
model_name = "sample_iris_model"
meta_props={
client.repository.ModelMetaNames.NAME: model_name,
client.repository.ModelMetaNames.RUNTIME_UID: "scikit-learn_0.22-py3.6",
client.repository.ModelMetaNames.TYPE: "scikit-learn_0.22",
client.repository.ModelMetaNames.INPUT_DATA_SCHEMA:{
"id":"iris model",
"fields":[
{'name': 'sepal length (cm)', 'type': 'double'},
{'name': 'sepal width (cm)', 'type': 'double'},
{'name': 'petal length (cm)', 'type': 'double'},
{'name': 'petal width (cm)', 'type': 'double'}
]
},
client.repository.ModelMetaNames.OUTPUT_DATA_SCHEMA: {
"id":"iris model",
"fields": [
{'name': 'iris_type', 'type': 'string','metadata': {'modeling_role': 'prediction'}}
]
}
}
# モデルを保存。戻り値に作成したモデルのメタデータが含まれる
model_artifact = client.repository.store_model(model, meta_props=meta_props, training_data=X, training_target=y)
補足として、meta_props内に含めるメタ情報については、上にかいた「補足:モデルに含めるメタ情報」と同じなのでそちらを参照ください。
保存したモデルのIDは、戻り値model_artifact内に含まれています。IDはデプロイを作成する際に必要となります。以下のようにIDを取り出します。
model_id = client.repository.get_model_uid(model_artifact)
model_id = model_artifact['metadata']['guid']
モデルの一覧表示 (分析プロジェクト)
# 分析プロジェクトに切り替え(切り替える必要がある場合のみ実施)
client.set.default_project(project_id)
# モデルの一覧を表示
client.repository.list_models()
モデルの一覧表示 (デプロイメントスペース)
WML clientを使用します。
# デプロイメントスペースに切り替え(切り替える必要がある場合のみ実施)
client.set.default_space(space_id)
# モデルの一覧を表示
client.repository.list_models()
デプロイメントの操作 (デプロイメントスペースのみ)
WML clientを使用します。デプロイメントはBatch型とOnline型があります。作成するcreateにはデプロイするモデルのIDを与えます。
デプロイメントの作成(Online型)
dep_name = "sample_iris_online"
meta_props = {
client.deployments.ConfigurationMetaNames.NAME: dep_name,
client.deployments.ConfigurationMetaNames.ONLINE: {}
}
deployment_details = client.deployments.create(model_id, meta_props=meta_props)
デプロイは1分弱かかりますが、以下のような出力が出ればデプロイ成功です。
#######################################################################################
Synchronous deployment creation for uid: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' started
#######################################################################################
initializing
ready
------------------------------------------------------------------------------------------------
Successfully finished deployment creation, deployment_uid='yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy'
------------------------------------------------------------------------------------------------
作成したデプロイメントのIDは、戻り値から以下のように取り出せます。
# ONLINE型デプロイメントのID
dep_id_online = deployment_details['metadata']['guid']
デプロイメントの作成(Batch型)
dep_name = "sample_iris_batch"
meta_props = {
client.deployments.ConfigurationMetaNames.NAME: dep_name,
client.deployments.ConfigurationMetaNames.BATCH: {},
client.deployments.ConfigurationMetaNames.COMPUTE: {
"name": "S",
"nodes": 1
}
}
deployment_details = client.deployments.create(model_id, meta_props=meta_props)
Successfullyと表示されたらデプロイ成功です。
作成したデプロイメントのIDは、戻り値から以下のように取り出せます。
# BATCH型デプロイメントのID
dep_id_batch = deployment_details['metadata']['guid']
デプロイメントの一覧表示
こちらもWML clientを使用します。
# デプロイメントの一覧を表示
client.deployments.list()
デプロイメントの実行(Online型)
Online型のデプロイメントの実行では、スコアリング用の入力データ(JSON形式)を作成して、それをデプロイメントにRESTで投げ、予測結果を受け取ります。まず、サンプル入力データを作成します。
# sample data for scoring (setosa)
scoring_x = pd.DataFrame(
data = [[5.1,3.5,1.4,0.2]],
columns=['sepal length (cm)','sepal width (cm)','petal length (cm)','petal width (cm)']
)
values = scoring_x.values.tolist()
fields = scoring_x.columns.values.tolist()
scoring_payload = {client.deployments.ScoringMetaNames.INPUT_DATA: [{'fields': fields, 'values': values}]}
scoring_payload
{'input_data': [{'fields': ['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)'],
'values': [[5.1, 3.5, 1.4, 0.2]]}]}
Onlineデプロイメントの実行は、WML clientとrequestsの2つの方法が可能です。
prediction = client.deployments.score(dep_id_online, scoring_payload)
prediction
{'predictions': [{'fields': ['prediction', 'probability'],
'values': [[0, [0.8131726303900102, 0.18682736960998966]]]}]}
requestsの実行例は、CP4D画面のデプロイメント詳細画面にあるコードスニペットからコピペで使えます。
mltokenはAPIの認証トークンで、この記事の最初の方にある[WML clientの初期化(認証)](# WML-clientの初期化認証)でOS環境変数 USER_ACCESS_TOKEN から得たtoken
がそのまま使用できます。
CP4D外の環境から実行する場合は、CP4D製品マニュアルの「ベアラー・トークンの取得」を実施して予め入手しておきます。
import urllib3, requests, json
# token = "XXXXXXXXXXXXXXXXXX"
# url = "https://cp4d.host.name.com"
header = {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token}
dep_url = url + "/v4/deployments/" + dep_id_online + "/predictions"
response = requests.post(dep_url, json=scoring_payload, headers=header)
prediction = json.loads(response.text)
prediction
{'predictions': [{'fields': ['prediction', 'probability'],
'values': [['setosa', [0.9939393939393939, 0.006060606060606061, 0.0]]]}]}
もしCP4Dのドメインが自己署名証明書を使っていてrequests.postが証明書チェックで失敗する場合は、requests.postのオプションverify=False
を使うと暫定的に回避できます。ご利用は自己責任で。
デプロイメントの実行(Batch型)
Batch型のデプロイメントの実行では、入力データとなるCSVファイルを予めデプロイメントスペースのデータ資産に登録しておき、そのデータ資産のhrefを指定します。
# サンプルとしてIris学習データXの先頭5行をCSV化
X.head(5).to_csv("iris_test.csv")
# デプロイメントスペースに切り替え(切り替える必要がある場合のみ実施)
client.set.default_space(space_id)
# データ資産への登録
asset_details = client.data_assets.create(name="iris_test.csv",file_path="/home/wsuser/work/iris_test.csv")
asset_href = client.data_assets.get_href(asset_details)
# 実行ジョブのメタ情報を作成
job_payload_ref = {
client.deployments.ScoringMetaNames.INPUT_DATA_REFERENCES: [{
"location": {
"href": asset_href
},
"type": "data_asset",
"connection": {}
}],
client.deployments.ScoringMetaNames.OUTPUT_DATA_REFERENCE: {
"location": {
"name": "iris_test_out_{}.csv".format(dep_id_batch),
"description": "testing csv file"
},
"type": "data_asset",
"connection": {}
}
}
# バッチ実行(create_jobすると実行される)
job = client.deployments.create_job(deployment_id=dep_id_batch, meta_props=job_payload_ref)
job_id = client.deployments.get_job_uid(job)
実行結果のステータスは、以下のコードで確認できます。プログラムに組み込む場合は、stateがcompletedになるまでループを回すと良いと思います。
# バッチ実行ジョブのステータス確認
client.deployments.get_job_status(job_id)
# 実行中の場合
{'state': 'queued', 'running_at': '', 'completed_at': ''}
# 実行完了の場合
{'state': 'completed',
'running_at': '2020-05-28T05:43:22.287357Z',
'completed_at': '2020-05-28T05:43:22.315966Z'}
以上です。
他にも、Python関数を保存したりデプロイしたりできますが、機会があれば追記 or 別の記事で書きます。
(2020/6/1追記) 以下のGitリポジトリにCP4D v3.0で使えるモデルやデプロイ系のサンプルNotebookがありました。https://github.ibm.com/GREGORM/CPDv3DeployML
-
詳細は、WML client リファレンスガイド watson-machine-learning-client(V4) および、CP4D v2.5 製品マニュアル Python クライアントを使用したデプロイを参照。WML clientリファレンスガイドは随時更新される可能性があるので注意。 ↩
-
詳細は、CP4D v2.5 製品マニュアル Python 用の project-lib の使用を参照 ↩
-
データの読み込みは、Notebook画面の右上にあるデータボタン(0100と書いてある)をクリックし、該当のデータ資産名 > コードに挿入 > pandas DataFrame をクリックすることで、Notebook内のセルにコードが自動挿入されます。標準では、ファイルの場合はpandas.read_csvのコードが、DBテーブルの場合はproject_libのコードが挿入されるようです。 ↩
-
WML clientでも可能ですが、格納されたファイルが本来のデータ資産とは異なる領域にファイルが保存され、ダウンロードするとファイル名が不正になるなど問題が確認されているため、WML clientでのデータ資産への保管はオススメしません。その方法もこの記事には書きません。 ↩
-
デプロイメントスペースの画面上は、関数が「機能」と表現されています。日本語訳が統一されておらずイマイチな気がしますが。 ↩ ↩2
-
CP4D v2.5 製品マニュアル ノートブックでの機密コード・セルの非表示を参照 ↩