0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IBM Cloudで機械学習/深層学習モデルを開発・運用するプログラム集

Last updated at Posted at 2025-01-26

この記事は、IBM Cloudで機械学習/深層学習モデル(AIモデル)を開発・運用するためのPythonプログラムについて記載しています。

概要

IBM CloudでAIモデルを開発・運用するためのステップの一例として、以下が挙げられます。

ws_wml_overview.png

  1. AIモデルの開発はIBM CloudのWatson Studioサービスで行い、AIモデルの管理はIBM CloudのWatson Machine Learningサービスで行うため、これらのサービスを作成します
  2. AIモデルを開発するためにプロジェクトを作成します
  3. 作成したプロジェクトで、Jupyterノートブック・エディターを使用してAIモデルの開発を行います
  4. AIモデルの学習に必要なデータはデータベースやオブジェクト・ストレージなどから取得します。それらのデータ・ソースへの接続情報は、プロジェクトに定義します
  5. 作成したAIモデルをプロジェクトに保存します
  6. AIモデルを管理するために、デプロイメント・スペースを作成します
  7. プロジェクトに保存されたAIモデルをデプロイメント・スペースに取り込みます(プロモート)
  8. デプロイメント・スペースにプロモートされたAIモデルを同じデプロイメント・スペース上にデプロイします。デプロイすると、そのAIモデルに対してREST APIを使って推論できるようになります
  9. REST APIで、デプロイされたAIモデルを使って推論します

この記事では、上記、4, 5, 7, 8, 9 について、Pythonでどのように実装するのかについて述べます。7と8はIBM CloudのWeb画面を使って実現可能ですが、Pythonのプログラムでできるようにしておくと自動化に利用できて便利です。
Pythonのライブラリは、ibm-watson-machine-learing を使用します。
AIモデルの例として、scikit-learnを使った機械学習モデル(住宅ローンの許可/却下の分類)、Kerasを使った深層学習モデル(画像の分類)、PyTorchを使った深層学習モデル(画像の分類)を取り上げます。

1. ベースとなるAPIClientオブジェクトの作成

Pythonのライブラリ ibm-watson-machine-learning で各種処理を行うためには、ベースとなるAPIClientオブジェクトを作成する必要があります。
この作成時に認証も行いますが、IBM CloudのSaaS環境 (Cloud Pak for Data as a Service) か、オンプレ環境 (Cloud Pak for Data) かで、やり方が異なります。

1.1. SaaS環境 (Cloud Pak for Data as a Service)

オブジェクトを作成する際の認証情報として、APIキーとSaaS環境のURLが必要となります。APIキーは、IBM CloudのWeb画面を使用して作成することができます。
IBM Cloudにログインし、管理 > アクセス(IAM) を選択

apikey_saas_1.png

画面左メニューの APIキー を選択し、画面右にある作成ボタンを選択してAPIキーを作成

apikey_saas_2.png

SaaS環境のURLは、https://[ロケーション].ml.cloud.ibm.com で、ロケーション情報は、IBM Cloud の Jupyter ノートブック・エディターを使用する場合、RUNTIME_ENV_REGION 環境変数から得られます。
APIClientオブジェクトを作成するプログラムは以下になります。

import os
from ibm_watson_machine_learning import APIClient

location = os.environ['RUNTIME_ENV_REGION'] 
apikey = "[APIキー]"
wml_credentials = {
    "apikey": apikey,
    "url": 'https://' + location + '.ml.cloud.ibm.com'
}
wml_client = APIClient(wml_credentials)

1.2. オンプレ環境 (Cloud Pak for Data)

オンプレでAPIClientオブジェクトを作成するためには、url, username, apikey, instance_id, version が必要となります。

  • URLは、https://[Cloud Pak for Data のホスト名]
  • usernameは、Cloud Pak for Data のユーザー名
  • apikeyは、上記ユーザーのAPIキー。上記ユーザーでCloud Pak for Data にログインしたWeb画面で、上部のメニュー右から2つ目のアイコンをクリックし、「プロファイルと設定」を選択。切り替わった画面右にある「API鍵」をクリックして「新規鍵の生成」を選択するとAPIキーを作成することができます

apikey_private_1.png

apikey_private_2.png

  • instance_idは、openshift
  • versionは、Cloud Pak for Dataのバージョン(例: "5.0")

APIClientオブジェクトを作成するプログラムは以下になります。

cp4d_url = "https://[Cloud Pak for Data のホスト名]"
cp4d_user = "[ユーザー名]"
cp4d_apikey = "[APIキー]"
cp4d_version = "Cloud Pak for Data のバージョン(例: 5.0)"
wml_credentials = {
    "url": cp4d_url,
    "username": cp4d_user,
    "apikey": cp4d_apikey,
    "instance_id": "openshift",
    "version": cp4d_version
}
wml_client = APIClient(wml_credentials)

以降、生成したAPIClientオブジェクトの変数名をwml_clientとして説明します。

2. 作業する対象環境(特定のプロジェクトまたはデプロイメント・スペース)を指定

プロジェクトにAIモデルを保存したり、プロジェクトのAIモデルをデプロイメント・スペースにプロモートする場合、プロジェクトIDを以下のようにセットします。

project_id = "[プロジェクトID]"
wml_client.set.default_project(project_id)

プロジェクトIDは、プロジェクトの「管理」タブの「一般」に表示されています。

project_id.png

デプロイメント・スペースにプロモートされたAIモデルをデプロイする場合、デプロイメント・スペースのID(スペースID)を以下のようにセットします。

space_id="[スペースID]"
wml_client.set.default_space(space_id)

スペースIDは、以下のプログラムで、デプロイメント・スペース名から特定することができます。

space_name = "[デプロイメント・スペース名]"
space_id = None
for space in wml_client.spaces.get_details()['resources']:
    # print(space['metadata']['id'], space['entity']['name'], space['metadata']['created_at'])
    if space['entity']['name'] == space_name:
        space_id = space['metadata']['id']
        break
if space_id:
    print(f'Deployment space name: "{space_name}", Deployment space ID: "{space_id}"')
else:
    emsg = f'Deployment space name "{space_name}" not found.'
    raise Exception(emsg)

IBM CloudのWeb画面からも得ることができ、デプロイメント・スペースの「管理」タブの「一般」に表示されています(スペースGUID)。

space_id.png

3. AIモデル開発に使用するデータ・アクセス

3.1. Db2データベースに保存されたデータ取得

プロジェクトに保存したDb2接続情報の取得とSELECT文の結果をPandasのデータフレームに保存するプログラム例を以下に述べます。

import ibm_db_dbi
import pandas as pd

wml_client.set.default_project(project_id)

db2_name = "Db2 Mortgage Approval Data"    # Db2接続情報名
db2_info = None
for detail in wml_client.connections.get_details()["resources"]:
    if detail["entity"]["name"] == db2_name:
        db2_info = wml_client.connections.get_details(detail["metadata"]["id"])["entity"]["properties"]
print(f"db2_info={db2_info}")
con_url = f'DATABASE={db2_info["database"]};HOSTNAME={db2_info["host"]};PORT={db2_info["port"]};PROTOCOL=TCPIP;UID={db2_info["username"]};PWD={db2_info["password"]}'
if db2_info["ssl"] == "true":
    con_url = con_url + ";Security=SSL"
print(f"con_url={con_url}")
con = ibm_db_dbi.connect(con_url,'','')
sql_query = "select * from AI_MORTGAGE.MORTGAGE_APPROVAL_VIEW"
df_mortgage = pd.read_sql_query(sql_query, con)
df_mortgage.head()

画面出力例

db2_info={'database': 'BLUDB', 'auth_method': 'username_password', 'password': 'xxx', 'port': '50001', 'host': 'xxx.us-south.db2w.cloud.ibm.com', 'ssl': 'true', 'username': 'xxx'}

ID 	NAME 	STREET_ADDRESS 	CITY 	STATE 	STATE_CODE 	ZIP_CODE 	EMAIL_ADDRESS 	PHONE_NUMBER 	GENDER 	... 	NUMBER_OF_CARDS 	CREDITCARD_DEBT 	LOANS 	LOAN_AMOUNT 	CREDIT_SCORE 	COMMERCIAL_CLIENT 	COMM_FRAUD_INV 	PROPERTY_VALUE 	AREA_AVG_PRICE 	MORTGAGE_APPROVAL
0 	110424 	Adah Marks 	4355-5 Pelham South 	Park Ridge 	Illinois 	IL 	41227 	Adah.Marks@donny.ca 	206-220-3128 	Male 	... 	2 	1168.0 	1 	7478.0 	547 	FALSE 	FALSE 	548618.0 	NaN 	0
1 	110425 	Jerrell Eichmann 	5642-1 Hwy 78 East 	Reston 	Virginia 	VA 	41198 	Jerrell.Eichmann@trycia.biz 	972-510-7295 	Male 	... 	2 	1167.0 	1 	7476.0 	547 	TRUE 	FALSE 	548638.0 	NaN 	0
2 	110426 	Glennie Barrows 	6736-1 Whitfield Ave 	Houston 	Texas 	TX 	41169 	Glennie.Barrows@elwin.us 	609-564-9894 	Female 	... 	2 	1166.0 	1 	7474.0 	547 	FALSE 	FALSE 	548658.0 	NaN 	0
3 	110427 	Susanna Schaefer 	4529-0 Madison Blvd 	Woodridge 	Illinois 	IL 	41140 	Susanna.Schaefer@elta.ca 	484-261-6798 	Female 	... 	2 	1165.0 	1 	7471.0 	547 	FALSE 	FALSE 	548678.0 	NaN 	0
4 	110428 	Jettie Waters 	3698-Kelley Blvd 	Truckee 	California 	CA 	41110 	Jettie.Waters@kacie.co.uk 	253-973-4793 	Male 	... 	2 	1164.0 	1 	7469.0 	546 	TRUE 	FALSE 	548698.0 	721244.0 	0

5 rows × 29 columns

3.2. IBM Cloud Object Storage (ICOS) に保存されたデータ取得

認証方法を「リソース・インスタンスIDとAPIキー」として登録した場合のプログラム例を以下に示します。

import ibm_boto3
from ibm_botocore.client import Config

wml_client.set.default_project(project_id)

icos_name = "icos1"    # ICOS接続情報名
bucket_name = "cloud-object-storage-mortgage-2021-jp"
file_name = "mortgage_approval_view.csv"
icos_info = None
for detail in wml_client.connections.get_details()["resources"]:
    if detail["entity"]["name"] == icos_name:
        icos_info = wml_client.connections.get_details(detail["metadata"]["id"])["entity"]["properties"]
print(f"icos_info={icos_info}")
if not icos_info["url"].startswith("http"):
    icos_info["url"] = "https://" + icos_info["url"]
cos = ibm_boto3.client(service_name="s3",
    ibm_api_key_id=icos_info["api_key"],
    ibm_service_instance_id=icos_info["resource_instance_id"],
    ibm_auth_endpoint='https://iam.bluemix.net/oidc/token',
    config=Config(signature_version='oauth'),
    endpoint_url=icos_info["url"])
cos.download_file(Bucket=bucket_name, Key=file_name, Filename=file_name)
!ls -l $file_name

画面出力例

icos_info={'trust_all_ssl_cert': 'false', 'auth_method': 'instanceid_apikey', 'iam_url': 'https://iam.cloud.ibm.com/identity/token', 'api_key': 'xxx', 'resource_instance_id': 'crn:v1:bluemix:public:cloud-object-storage:global:xxx', 'url': 's3.us-south.cloud-object-storage.appdomain.cloud'}
-rw-rw---- 1 wsuser wscommon 1281702 Jan 25 05:42 mortgage_approval_view.csv

Jupyter ノートブックのファイルシステムにあるファイルをICOSにアップロードするには、upload_file メソッドをコールします。引数は、上記の例で使用している download_file メソッドと同じです。

4. AIモデルの保存

4.1. scikit-learnを使った機械学習モデルの保存

scikit-leanのpiplelineを使った機械学習モデルを例として述べます。
機械学習モデルを開発するプログラムの詳細は省略しますが、その中で、モデルの保存に必要な情報は以下になります。

target_col='MORTGAGE_APPROVAL'   # 推論結果を表す列
X = df_mortgage.drop([target_col], axis=1)
model = Pipeline(steps=[('preprocessor', preprocessor),
    ('model', RandomForestClassifier(n_estimators=top_ne, max_depth=top_md, max_features=top_mf, random_state=0))])

AIモデルを新規保存またはバージョンアップするプログラムの例は以下になります。AIモデルの保存は wml_client.repository.store_model メソッドを利用します。このメソッドでAIモデルを保存すると、同じ名前でもIDの異なる新規のAIモデルが作成されてしまいます。同じ名前の場合は、wml_client.repository.update_model メソッドを使ってバージョンアップするのがお勧めです。

model_name = "Mortgage Approval Model"
# AIモデルが既に保存されているか確認
models = wml_client.repository.get_model_details()['resources']
model_ids = [m['metadata']['id'] for m in models if m['metadata']['name'] == model_name]
model_id = None
if len(model_ids) > 1:
    emsg = 'Multiple models with the same model name "{}" exist: {}'.format(model_name, model_ids)
    raise KeyError(emsg)
elif len(model_ids) == 1:
    model_id = model_ids[0]
print(f"existing model_id: {model_id}")
# AIモデルが保存されていなかったら新規作成、保存されていたらバージョンアップ
if model_id == None:
    # 実行環境情報のセット
    software_spec_uid = wml_client.software_specifications.get_id_by_name("runtime-24.1-py3.11")
    print(software_spec_uid)
    # training_data_references情報のセット
    db2_name = "Db2 Mortgage Approval Data"    # Db2接続情報名
    connection_id = None
    for detail in wml_client.connections.get_details()["resources"]:
        if detail["entity"]["name"] == db2_name:
            connection_id = detail["metadata"]["id"]
    sql_query = "select * from AI_MORTGAGE.MORTGAGE_APPROVAL_VIEW"
    training_data_references = [{
        "id": "Mortgage_data",
        "type": "connection_asset",
        "connection": {
            "id": connection_id,
        },
        "location": {
            "select_statement": sql_query,
            "table_name": "Mortgage_Approval_view"
        }
    }]
    # モデル・プロパティ値のセット
    model_props = {
        wml_client._models.ConfigurationMetaNames.NAME:model_name,
        wml_client._models.ConfigurationMetaNames.TYPE: "scikit-learn_1.3",
        wml_client._models.ConfigurationMetaNames.SOFTWARE_SPEC_UID: software_spec_uid,
        wml_client._models.ConfigurationMetaNames.LABEL_FIELD:target_col,
        wml_client._models.ConfigurationMetaNames.INPUT_DATA_SCHEMA:[{'id': '1', 'type': 'struct', 'fields': [{"name":column_name,"type":str(column_type[0])} for column_name,column_type in pd.DataFrame(X.dtypes).T.to_dict('list').items()]}],
        wml_client.repository.ModelMetaNames.TRAINING_DATA_REFERENCES: training_data_references
    }
    # モデルをプロジェクトに保存
    model_detail = wml_client.repository.store_model(model=model, meta_props=model_props, 
        training_data=X_train, training_target=y_train)
    print(f'The model "{model_name}" successfully stored in the project.')
else:
    model_props = {
        wml_client._models.ConfigurationMetaNames.NAME:model_name
    }
    # モデルの更新(バージョン・アップ)
    model_detail = wml_client.repository.update_model(
        model_uid=model_id,
        updated_meta_props=model_props,
        update_model=model
    )
    print(f'The model "{model_name}" successfully updated in the project.')
model_id = wml_client.repository.get_model_id(model_detail)
new_model_revision = wml_client.repository.create_model_revision(model_id)
rev_id = new_model_revision["metadata"].get("rev")
print(f"Model ID: {model_id}")
print(f"Revison ID: {rev_id}")

4.2. Keras を使った深層学習モデルの保存

AIモデルのバージョンアップについては 4.1. scikit-learnを使った機械学習モデルの保存 と同じようにできるので、ここでは、新規保存についてのみ述べます。
以下のモデルを例に述べます。

from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation

def cnn_model(x_train, class_labels_count):
    model = Sequential()
    model.add(Conv2D(32, (3, 3), padding="same", input_shape=x_train.shape[1:]))
    model.add(Activation('relu'))
    model.add(Conv2D(32, (3, 3))) 
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    model.add(Conv2D(64, (3, 3), padding='same'))
    model.add(Activation('relu'))
    model.add(Conv2D(64, (3, 3)))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    model.add(Flatten())
    model.add(Dense(512))
    model.add(Activation('relu'))
    model.add(Dropout(0.5))
    model.add(Dense(class_labels_count))
    model.add(Activation('softmax'))

    model.compile(
        loss='categorical_crossentropy',
        optimizer='adam',
        metrics=['accuracy']
    )
    return model

モデルの保存は以下のようになります。

h5file = 'mnist-keras.h5'
gzfile = 'mnist-keras.tar.gz'
model.save(h5file)
import tarfile
with tarfile.open(gzfile, 'w:gz') as tf:
    tf.add(h5file)

model_name = "mnist-keras"
software_spec_uid = wml_client.software_specifications.get_uid_by_name("runtime-24.1-py3.11")
model_props = {
    wml_client._models.ConfigurationMetaNames.NAME:model_name,
    wml_client._models.ConfigurationMetaNames.TYPE: "tensorflow_2.14",
    wml_client._models.ConfigurationMetaNames.SOFTWARE_SPEC_UID: software_spec_uid,
}
model_detail = wml_client.repository.store_model(model=gzfile, meta_props=model_props)
model_id = wml_client.repository.get_model_id(model_detail)
new_model_revision = wml_client.repository.create_model_revision(model_id)
rev_id = new_model_revision["metadata"].get("rev")
print(f"Model ID: {model_id}")
print(f"Revison ID: {rev_id}")

4.3. PyTorch を使った深層学習モデルの保存

こちらも、AIモデルのバージョンアップについては 4.1. scikit-learnを使った機械学習モデルの保存 と同じようにできるので、ここでは、新規保存についてのみ述べます。
以下のモデルを例に述べます。

import torch
import torchvision
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torchvision.transforms as transforms

class cifar10_cnn(nn.Module):
  def __init__(self, num_classes):
    super(cifar10_cnn,self).__init__()
    self.conv1 = nn.Conv2d(3, 32, 3, padding=(1,1), padding_mode='replicate')
    self.conv2 = nn.Conv2d(32, 32, 3)
    self.conv3 = nn.Conv2d(32, 64, 3, padding=(1,1), padding_mode='replicate')
    self.conv4 = nn.Conv2d(64, 64, 3)
    self.relu = nn.ReLU(inplace=True)
    self.dropout1 = nn.Dropout(0.25)
    self.dropout2 = nn.Dropout(0.5)
    self.maxpool = nn.MaxPool2d((2,2))
    self.classifier1 = nn.Linear(2304, 512)
    self.classifier2 = nn.Linear(512, num_classes)

    self.features = nn.Sequential(
        self.conv1,
        self.relu,
        self.conv2,
        self.relu,
        self.maxpool,
        self.dropout1,
        self.conv3,
        self.relu,
        self.conv4,
        self.relu,
        self.dropout1,
        self.maxpool)
    
    self.classifier = nn.Sequential(
       self.classifier1,
       self.relu,
       self.dropout2,
       self.classifier2)

  def forward(self, x):
    x = self.features(x)
    x = x.view(x.size(0), -1)
    x = self.classifier(x)
    return x

モデルの保存は以下のようになります。

# ダミーデータの作成
dummy_input = torch.randn((1, 3, 32, 32)).to(device)

# onyx形式でexport
torch.onnx.export(net, dummy_input, "mnist-pytorch.onnx", 
                  keep_initializers_as_inputs=True, verbose=True, opset_version=9)

# gz形式に圧縮
!tar czvf mnist-pytorch.gz mnist-pytorch.onnx

gzfile = "mnist-pytorch.gz"
model_name = "mnist-pytorch"
software_spec_uid = wml_client.software_specifications.get_uid_by_name("runtime-24.1-py3.11")
model_props = {
    wml_client._models.ConfigurationMetaNames.NAME:model_name,
    wml_client._models.ConfigurationMetaNames.TYPE: "pytorch-onnx_2.1",
    wml_client._models.ConfigurationMetaNames.SOFTWARE_SPEC_UID: software_spec_uid,
}
model_detail = wml_client.repository.store_model(model=gzfile, meta_props=model_props)
model_id = wml_client.repository.get_model_id(model_detail)
new_model_revision = wml_client.repository.create_model_revision(model_id)
rev_id = new_model_revision["metadata"].get("rev")
print(f"Model ID: {model_id}")
print(f"Revison ID: {rev_id}")

torch.onnx.exportメソッドの引数 opset_version を指定しないと、モデルのデプロイでエラーとなるようです。

5. AIモデルのプロモート

以下のように行います。

# wml_clientにプロジェクトIDのセット
project_id = "[プロジェクトID]"
wml_client.set.default_project(project_id)

# 以下に記載の [モデル名] を、以下に記載の [デプロイメント・スペース名] にプロモート
model_name = "[モデル名]"
space_name = "[デプロイメント・スペース名]"

# プロジェクトに保存されているモデルIDの取得
entities = wml_client.repository.get_details()['models']['resources']
model_id = None
for entity in entities:
    name = entity['metadata']['name']
    if name == model_name:
        model_id = entity['metadata']['id']
        break
if model_id:
    print(f'Model name: "{model_name}", Model ID: "{model_id}"')
else:
    emsg = f'Model name "{model_name}" not found.'
    raise Exception(emsg)

# プロモート先となるデプロイメントスペースIDの取得
space_id = None
for space in wml_client.spaces.get_details()['resources']:
    # print(space['metadata']['id'], space['entity']['name'], space['metadata']['created_at'])
    if space['entity']['name'] == space_name:
        space_id = space['metadata']['id']
        break
if space_id:
    print(f'Deployment space name: "{space_name}", Deployment space ID: "{space_id}"')
else:
    emsg = f'Deployment space name "{space_name}" not found.'
    raise Exception(emsg)

# モデルのプロモート
if model_id and space_id:
    space_model_id = wml_client.spaces.promote(asset_id=model_id, source_project_id=project_id, target_space_id=space_id)
    print(f'Model asset ID in deployment space "{space_name}": "{space_model_id}"')

6. モデルのデプロイ

以下のように行います。

# 以下に記載の [デプロイメント・スペース名] にプロモートされている [モデル名] をデプロイ 
space_name = "[デプロイメント・スペース名]"
space_model_name = "[モデル名]"

# デプロイメントスペースIDの取得
space_id = None
for space in wml_client.spaces.get_details()['resources']:
    # print(space['metadata']['id'], space['entity']['name'], space['metadata']['created_at'])
    if space['entity']['name'] == space_name:
        space_id = space['metadata']['id']
        break
if space_id:
    print(f'Deployment space name: "{space_name}", Deployment space ID: "{space_id}"')
else:
    emsg = f'Deployment space name "{space_name}" not found.'
    raise Exception(emsg)

# wml_clientにスペースIDのセット
wml_client.set.default_space(space_id)

# モデルIDの取得
entities = wml_client.repository.get_details()["models"]["resources"]
space_model_id = None
for entity in entities:
    name = entity['metadata']['name']
    if name == space_model_name:
        space_model_id = entity['metadata']['id']
        break
if space_model_id:
    print(f'Space Model name: "{space_model_name}", Space Model ID: "{space_model_id}"')
else:
    emsg = f'Space Model name "{space_model_name}" not found.'
    raise Exception(emsg)

# モデルのデプロイ
meta_props={
    wml_client.deployments.ConfigurationMetaNames.NAME: space_model_deployment_name,
    wml_client.deployments.ConfigurationMetaNames.ONLINE: {}
}

if space_id and space_model_id:
    deployment_id = wml_client.deployments.create(artifact_uid=space_model_id, meta_props=meta_props, target_space_id=space_id)
    space_model_deployment_id = deployment_id['entity']['asset']['id']
    print(f'Deployment name: "{space_model_deployment_name}", Deployment  ID: "{space_model_deployment_id}"')

7. デプロイされたAIモデルの利用

SaaS環境 (Cloud Pak for Data as a Service) も、オンプレ環境 (Cloud Pak for Data) も、デプロイされたモデルをWeb画面で開くと、APIリファレンスタブがあり、REST APIで推論要求するためのプログラムの断片(コード・スニペット)が記載されています。

SaaS環境の例

code_snippet_ml_saas.png

オンプレ環境の例

code_snippet_ml.png

SaaS環境とオンプレ環境の違いは認証方法のみで、それ以外は呼び出し先のURLが異なるだけで、プログラムは同じです。

7.1. 認証方法

7.1.1. SaaS環境 (Cloud Pak for Data as a Service) の認証方法

コード・スニペットに記載の通り、以下のようにプログラムします。

API_KEY = "[APIキー]"
token_response = requests.post('https://iam.cloud.ibm.com/identity/token', data={"apikey":
 API_KEY, "grant_type": 'urn:ibm:params:oauth:grant-type:apikey'})
mltoken = token_response.json()["access_token"]

header = {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + mltoken}

7.1.2. オンプレ環境 (Cloud Pak for Data)

認証情報として、ログインしているユーザー名とそのAPIキーを利用して以下を実行します。

$ echo "[ユーザー名]:[APIキー]" | base64

ユーザー名を cpadmin 、APIキーを ABCDE12345 とすると、以下のようになります。

$ echo "cpadmin:ABCDE12345" | base64
Y3BhZG1pbjpBQkNERTEyMzQ1Cg==

上記の値をmltokenにセットして、headerを以下のようにします。

mltoken = "Y3BhZG1pbjpBQkNERTEyMzQ1Cg=="
header = {'Content-Type': 'application/json', 'Authorization': 'ZenApiKey ' + mltoken}

7.2. モデルの推論

headerは、上記で述べたようにSaaS環境とオンプレ環境で異なります。ここでは、headerがセットされた前提で、それ以降のプログラムを、SaaSのURLを用いて説明します。
SaaSのURLは、プライベート・エンドポイントとパブリック・エンドポイントがあり、スニペットはプライベート・エンドポイントが記載されています。Watson Studio の Jupyter ノードブック等、IBM Cloud内からのコールの場合、プライベート・エンドポイントを利用します。IBM Cloud外からのアクセスの場合は、パブリック・エンドポイントに変更します。
以下の3つのモデル(scikit-learn機械学習モデル、Keras深層学習モデル、PyTorch深層学習モデル)の例では、IBM Cloud外からパブリック・エンドポイントに変更して実行しています。

7.2.1. scikit-learn機械学習モデル

プログラム

payload_scoring = {
  "input_data": [
    {
      "fields": [
        "INCOME",
        "YRS_AT_CURRENT_ADDRESS",
        "YRS_WITH_CURRENT_EMPLOYER",
        "NUMBER_OF_CARDS",
        "CREDITCARD_DEBT",
        "LOAN_AMOUNT",
        "CREDIT_SCORE",
        "PROPERTY_VALUE",
        "AREA_AVG_PRICE",
        "LOANS",
        "GENDER",
        "EDUCATION",
        "EMPLOYMENT_STATUS",
        "MARITAL_STATUS",
        "APPLIEDONLINE",
        "RESIDENCE",
        "COMMERCIAL_CLIENT",
        "COMM_FRAUD_INV"
      ],
      "values": [
        [
          53115,
          12,
          1,
          2,
          674,
          10455,
          539,
          538588,
          528267,
          0,
          "Female",
          "High School or Below",
          "Employed",
          "Married",
          "NO",
          "Owner Occupier",
          "TRUE",
          "FALSE"
        ]
      ]
    }
  ]
}

response_scoring = requests.post('https://us-south.ml.cloud.ibm.com/ml/v4/deployments/a40b45aa-c8b6-4f9d-b43b-8c4ef46c109d/predictions?version=2021-05-01', json=payload_scoring,
 headers={'Authorization': 'Bearer ' + mltoken})
print("Scoring response")
print(response_scoring.json())

実行結果

Scoring response
{'predictions': [{'fields': ['prediction', 'probability'], 'values': [[0, [0.8599447513812154, 0.14005524861878452]]]}]}

7.2.2. Keras深層学習モデル

以下の画像を分類します。

img_car = np.load("img_car.npy")
print(f"ndim: {img_car.ndim}")
print(f"shape: {img_car.shape}")
ndim: 3
spape: (32, 32, 3)
import matplotlib.pyplot as plt
plt.imshow(img_car)

Kerasの場合、payload_scoringfields は不要で、以下のフォーマットになります。

{"input_data": [{"values": [イメージの配列]}]}

プログラム

payload_scoring = {"input_data": [{"values": [img_car.tolist()]}]}

response_scoring = requests.post('https://us-south.ml.cloud.ibm.com/ml/v4/deployments/912ac537-d1d9-4009-8dbb-0df9e0015d76/predictions?version=2021-05-01', json=payload_scoring,
 headers={'Authorization': 'Bearer ' + mltoken})
print("Scoring response")
print(response_scoring.json())

実行結果

Scoring response
{'predictions': [{'fields': ['prediction'], 'id': 'activation_5', 'values': [[0.0017128867330029607, 0.7528261542320251, 9.030097135109827e-05, 0.00012985964713152498, 0.00011039885430363938, 0.0002107438340317458, 0.00011447971337474883, 0.0006360796396620572, 0.004830101504921913, 0.23933905363082886]]}]}

7.2.3. PyTorch深層学習モデル

こちらもKerasと同じ画像を使用します。
次元は、Kerasで使った画像の3次元目のchannelが最初になるので、以下のように変換しています。

np.transpose(img_car, (2,0,1))

PyTorchの場合、payload_scoringfields が必要となり、以下の値となります。

import onnxruntime
sess = onnxruntime.InferenceSession('mnist-pytorch.onnx')
print(f"input_name: {sess.get_inputs()[0].name}")
input_name: input.1

payload_scoringは、以下のフォーマットとなります。

{"input_data": [{"fields": "input.1", "values": [イメージの配列]}]}

プログラム

payload_scoring = {"input_data": [{"fields": "input.1", "values": [np.transpose(img_car, (2,0,1)).tolist()]}]}

response_scoring = requests.post('https://us-south.ml.cloud.ibm.com/ml/v4/deployments/bd2a7a2b-3440-434b-83c6-944cba26aba3/predictions?version=2021-05-01', json=payload_scoring,
 headers={'Authorization': 'Bearer ' + mltoken})
print("Scoring response")
print(response_scoring.json())

実行結果

Scoring response
{'predictions': [{'values': [[90.16368865966797, 132.31080627441406, -152.7025146484375, -148.4767608642578, -170.6203155517578, -235.80233764648438, -228.36398315429688, -156.88336181640625, 35.36519241333008, 105.59580993652344]]}]}

参考文献

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?