4
1

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の基盤モデルSlateのカスタムモデルをデプロイする

Last updated at Posted at 2024-10-22

0. はじめに

watsonx.aiの学習済みモデルのSlateでカスタムモデルをWatson Studioで作成し、外部アプリからの実行を可能にするためにWatson Machine Learning(WML)にファンクションでラップしてデプロイします。

{1D73952C-E603-41A6-9268-E3132DDAE29F}.png

サンプルソースとデータ

  • テスト環境
    • python 3.10.9
    • NLP+DO Runtime 23.1
    • CP4DaaS
    • jp-tok

1. 事前準備

1-1. APIキーの作成

Python関数の操作をibm_watsonx_aiのAPIで行うのでAPIキーが必要です。

IAMのAPIキーのメニューから「作成」でAPIキーを作ります。
https://cloud.ibm.com/iam/apikeys
image.png

任意の名前を付けて作成します。
image.png

コピーやダウンロードして保存しておきます。
image.png

1-2. デプロイメント・スペースの作成

デプロイメント・スペースの管理のページから「新規デプロイメント・スペース」を作ります。
https://jp-tok.dataplatform.cloud.ibm.com/ml-runtime/spaces?context=cpdaas
image.png

任意の名前を付け、紐づけるWatson Machine Learningのサービスを選択し、作成します。
image.png

作成したデプロイメント・スペースの「管理」タブを開き、スペースGUIDをコピーしておきます。

image.png

2. Slateのカスタムモデルの作成

学習データsentiment.csvをアップロードしておきます。

image.png

Watson NLPを利用できる環境が必要なので、Watson Studioで、ランタイムに「NLP+DO Runtime23.1 on Python 3.10」を選んでNotebookを作成してください(2024/10/21時点ではRuntime 24.1が最新でしたがうまく動かなかったので23.1を選びました)。

image.png

「コード・スニペット」を選び、「データの読み取り」をクリックします。
image.png
「プロジェクトからデータを選択します」をクリックします。
image.png

学習データ「sentiment.csv」を選択します。
image.png

image.png

「pandas DataFrame」を選び「セルにコードを挿入」します。

df_1のpandas DataFrameに読み込むコードが自動生成されます。
テキストに対して「ポジティブ」か「ネガティブ」かのlabelのついたデータです。
image.png

この@Jungobuさんの記事を参考にカスタムモデルを作ります

CSVをJSONに変換します。labelsは事前に配列に変換しておきます。

学習データをJSONファイルとして保存
def prepare_data(df):
    # textカラムと分類カテゴリの*labels*が必要
    df_out = df[['text', 'labels']].reset_index(drop=True)
    # labels列は配列でなければなりません (1つしかない場合でも同様)
    df_out['labels'] = df_out['labels'].map(lambda label: [label,])
    return df_out
    
train_df = prepare_data(df_1)
train_json_file = './train_data.json'
train_df.to_json(train_json_file, orient='records')

以下のコードでSlateのカスタム学習モデルを作成します。pretrained-model_slate.153m.distilled_many_transformer_multilingual_uncasedをベースの学習済みモデルとして選んでいます。他にも事前学習済みのモデルがあるので、用途に応じて選ぶことができます。
ここはnum_train_epochs=25の設定にもよりますが、それなりに時間がかかります。私がテストしたときには約15分かかりました。

Slateのカスタム学習モデルを作成
import watson_nlp

from watson_nlp.blocks.classification.transformer import Transformer
from watson_core.data_model.streams.resolver import DataStreamResolver


# 学習データからデータストリームを作成
data_stream_resolver = DataStreamResolver(target_stream_type=list, expected_keys={'text': str, 'labels': list})
train_stream = data_stream_resolver.as_data_stream(train_json_file)

# 学習済みのSlateモデルをロード
pretrained_model_resource = watson_nlp.load('pretrained-model_slate.153m.distilled_many_transformer_multilingual_uncased')

# Slateのカスタムモデルを作成。学習回数はnum_train_cpochsで指定
classification_model = Transformer.train(train_stream, pretrained_model_resource, num_train_epochs=25)

カスタムモデルで分類をテストしてみます。

Sカスタムモデルのテスト
text = 'ディスプレイは色鮮やかで、映画やゲームを楽しむのに最適です。'
slate_preds = classification_model.run(text)
slate_preds

うまくポジティブに分類されています。

{
  "classes": [
    {
      "class_name": "ポジティブ",
      "confidence": 0.9874120950698853
    },
    {
      "class_name": "ネガティブ",
      "confidence": 0.012587935663759708
    }
  ],
  "producer_id": {
    "name": "Transformer-based Text Classifier",
    "version": "0.0.1"
  }
}

3. 関数のデプロイ

3-1. 環境設定

先につくったAPIキーとWMLのエンドポイントを使って、APIクライアントを作ります。
エンドポイントの情報は以下にあります。今回はtokyoのWatson Machine Learningサービスのデプロイメントスペースを使ったのでtokyoのエンドポイントを選びました。

APIクライアント作成
api_key = 'PASTE YOUR API_KEY HERE'
#url = 'PASTE YOUR ENDPOINT HERE'
# tokyo Public endpoint
url = 'https://jp-tok.ml.cloud.ibm.com'
space_id = 'PASTE YOUR SPACE ID HERE'

from ibm_watsonx_ai import APIClient
from ibm_watsonx_ai import Credentials

#APIキーを使用してクライアントを作成する
credentials = Credentials(
    api_key = api_key,
    url= url
)

client = APIClient(credentials)

次にPython関数をデプロイするデプロイメント・スペースを指定します。
先ほど作ったデプロイメント・スペースのGUIDを入力します。
デプロイメントスペースのAPIクライアントを作ります。

デプロイメント・スペースの指定
client_space = APIClient(credentials, space_id = space_id)

3-2. モデルのシリアライズと保存

classification_modelをpickleでシリアライズします。

カスタムモデルをpickle化
import pickle
modelpickle='classification_model.pickle'

with open(modelpickle', 'wb') as f:
    pickle.dump(classification_model, f)

client_space.data_assets.createでデプロイメント・スペースに保存します。

デプロイメントスペースに保存
input_assest_detail=client_space.data_assets.create(name=modelpickle,file_path=modelpickle)

以下のようにデプロイメント・スペースに保存されます。
image.png

以下でアセットIDを取得します。

Asset_idを取得
print(input_assest_detail['metadata']['asset_id'])
結果
c7acd4e6-a65c-401e-9240-d14675ddfc49

3-3. 関数の作成

この記事を参考にして、関数でラッピングして、デプロイします。

  • APIClientでWMLのデプロイメントスペースに接続しています。
  • modelpickle_assest_idはハードコードするか、client_space.data_assets.list().query('NAME== @modelpickle')['ASSET_ID'][0]で名前をつかって取得します。
  • client_space.data_assets.downloadでデプロイメントスペースからカスタムモデルをpickleでダウンロードします。
  • classified_model = pickle.load(f)でモデルをロードします。
  • def score(payload)で関数を定義して、classified_model.runでカスタムモデルで分類結果を取得しています。
Python関数の定義
def classifyContext():
    import watson_nlp
    import os
    import pickle

    api_key = 'PASTE YOUR PLATFORM API KEY HERE'
    url = 'PASTE YOUR ENDPOINT HERE'
    #url = 'https://jp-tok.ml.cloud.ibm.com'
    space_id = 'PASTE YOUR SPACE ID HERE'

    modelpickle='classification_model.pickle'
    #modelpickle_assest_id='c7acd4e6-a65c-401e-9240-d14675ddfc49'
    
    
    # watsonxクライアントの接続
    from ibm_watsonx_ai import APIClient
    from ibm_watsonx_ai import Credentials
    credentials = Credentials(
        api_key = api_key,
        url= url
    )

    client_space = APIClient(credentials, space_id = space_id)
    # modelのpickleのIDを名前から取得
    modelpickle_assest_id=client_space.data_assets.list().query('NAME== @modelpickle')['ASSET_ID'][0]
    # デプロイメントスペースからダウンロード
    client_space.data_assets.download(modelpickle_assest_id,modelpickle)
    
    #ダウンロード確認
    if(os.path.isfile(modelpickle) == True):
         print('Download OK')
    else:
         print('Download Failed')
    

    # pickleからモデルを復元
    with open(modelpickle, 'rb') as f:
        classified_model = pickle.load(f)    
        
    # スコアリングファンクション
    def score(payload):
        #カスタムモデルでの分類
        c_prediction = classified_model.run(payload['input_data'][0]["values"][0][0])       
        return {'predictions': [c_prediction.to_dict()]}
       
    return score

WMLにデプロイする前にローカルでテストしてみます。

ファンクションのテスト
response = classifyContext()({
    "input_data": [{
        "values" :[["ディスプレイは色鮮やかで、映画やゲームを楽しむのに最適です。"]]
    }]
})
import pprint
pprint.pprint(response["predictions"])

ポジティブに分類できています。

結果
[{'classes': [{'class_name': 'ポジティブ', 'confidence': 0.9943501353263855},
              {'class_name': 'ネガティブ', 'confidence': 0.00564983207732439}],
  'producer_id': {'name': 'Transformer-based Text Classifier',
                  'version': '0.0.1'}}]

3-4. Python 関数のアップロード

作成したPython 関数classifyContextをDeployment Spaceにアップロードします。

まず、Python関数classifyContextを実行するソフトウェア仕様を選びます。
マニュアルに一覧があります。

ここでは、「NLP+DO Runtime23.1 on Python 3.10」のWatson Studioのランタイムをつかってモデルを作成したので、runtime-23.1-py3.10を使います。watson_nlpも含まれていました。ソフトウェア仕様のIDを取得します。

ソフトウェア仕様のIDを取得
sw_spec_uid = client.software_specifications.get_uid_by_name("runtime-23.1-py3.10")

関数my_deployable_functionをclient_space.repository.store_functionでデプロイメント・スペースに保存します。

関数を保存
meta_props = {
    client.repository.FunctionMetaNames.NAME: "Slate Test Simple",
    client.repository.FunctionMetaNames.SOFTWARE_SPEC_UID: sw_spec_uid
}

function_details = client_space.repository.store_function(meta_props=meta_props, function=classifyContext)
function_id = client_space.repository.get_function_id(function_details)

Webのデプロイメント・スペースの管理コンソールでみると「資産」タブに関数が登録されていることがわかります。

image.png

3-5. オンライン デプロイメントを作成する

client_space.deployments.createでオンラインデプロイメントを作成し、登録したPython関数をWebサービスとしてスコアリング実行可能にします。ここではHARDWARE_SPECSを選んでいます。「2 個の vCPU と 8 GB RAM」になります。スペックはここにのっています。

ファンクションをデプロイ
metadata = {
    client_space.deployments.ConfigurationMetaNames.NAME: "Deployment of function Slate Test Simple",
    client_space.deployments.ConfigurationMetaNames.HARDWARE_SPEC: { 'name': 'S'},  
    client_space.deployments.ConfigurationMetaNames.ONLINE: {}
}

function_deployment_details  = client_space.deployments.create(function_id, meta_props=metadata)

以下のように作成されました。これでWebサービスでのスコアリング実行が可能になりました。

結果
######################################################################################

Synchronous deployment creation for id: '8f82a5fd-d4a4-4dd7-9372-4d0fd0187dba' started

######################################################################################


initializing
Note: online_url and serving_urls are deprecated and will be removed in a future release. Use inference instead.
.....
ready


-----------------------------------------------------------------------------------------------
Successfully finished deployment creation, deployment_id='13c1791e-9460-4576-bffd-5893c89127c6'
-----------------------------------------------------------------------------------------------

Webのデプロイメント・スペースの管理コンソールでみると「デプロイメント」タブに関数が登録されていることがわかります。
image.png

デプロイメントIDを取得します。

デプロイメントIDの取得
deployment_id=function_deployment_details['metadata']['id']
print(deployment_id)
結果
13c1791e-9460-4576-bffd-5893c89127c6

Webのデプロイメント・スペースの管理コンソールではデプロイメントIDやソフトウェア仕様やハードウェア仕様も確認できます。
image.png

3-6. スコアリング実行

client_space.deployments.score メソッドを使用して、スコアリング レコードを Web サービス デプロイメントに送信できます。

スコアリング実行
scoring_payload = {
    "input_data": [{
        "values" :[["ディスプレイは色鮮やかで、映画やゲームを楽しむのに最適です。"]]
    }]
}

response = client_space.deployments.score(deployment_id, scoring_payload)
import pprint
pprint.pprint(response["predictions"])

以下のように結果を得ることができました。

結果
[{'classes': [{'class_name': 'ポジティブ', 'confidence': 0.9943501353263855},
              {'class_name': 'ネガティブ', 'confidence': 0.00564983207732439}],
  'producer_id': {'name': 'Transformer-based Text Classifier',
                  'version': '0.0.1'}}]

4 アプリからのスコアリング

pythonのアプリからも同様にスコアリング可能です。
ibm_watsonx_aiをpipで導入してください。

py -m pip install ibm_watsonx_ai

スコアリングのみを行うpythonコードは以下です。api_key, url, space_id, deployment_idを指定してください。

02ScoreSlateCustomModel.py
# 環境設定
import pprint
from ibm_watsonx_ai import Credentials
from ibm_watsonx_ai import APIClient
api_key = 'PASTE YOUR PLATFORM API KEY HERE'
url = 'PASTE YOUR ENDPOINT HERE'
#url = 'https://jp-tok.ml.cloud.ibm.com'

space_id = 'PASTE YOUR SPACE ID HERE'
deployment_id = 'PASTE YOUR DEPLOYMENT ID HERE'


# WMLへの接続
credentials = Credentials(
    api_key=api_key,
    url=url
)

client_space = APIClient(credentials, space_id=space_id)

# 分類したい文章
scoring_payload = {
    "input_data": [{
        "values": [["ディスプレイは色鮮やかで、映画やゲームを楽しむのに最適です。"]]
    }]
}

# 分類実行
response = client_space.deployments.score(deployment_id, scoring_payload)
pprint.pprint(response["predictions"])
結果例
PS python.exe c:/02ScoreSlateCustomModel.py
[{'classes': [{'class_name': 'ポジティブ', 'confidence': 0.9907686114311218},
              {'class_name': 'ネガティブ', 'confidence': 0.00923138577491045}],
  'producer_id': {'name': 'Transformer-based Text Classifier',
                  'version': '0.0.1'}}]

参考

IBMの基盤モデルSlateでカスタム分類モデルを試してみた #Watson-Studio - Qiita

Watson Machine LearningにPython関数をデプロイする #watsonx.ai - Qiita

独自のモデルの作成 — Docs | IBM watsonx

関数のデプロイ - Docs | IBM Cloud Pak for Data as a Service

Watson Machine Learning での Python 関数のデプロイ - Docs | IBM Cloud Pak for Data as a Service

4
1
1

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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?