このチュートリアルでは、ユーザーがデータを共有することなく、異なるユーザーからのデータで機械学習モデルをトレーニングすることを目的としたFederated Learningの使用方法を示します。 このステップは、UI と XGBoost フレームワークを使用するロー・コード環境で実行されます。 UCI: Adult - Predict income データセットを使って、訓練されたモデルは、国勢調査データに基づいて、所得が$50K/yrを超えるかどうかを予測する。 このデータセットは「国勢調査所得」データセットとしても知られている。
このチュートリアルでは、以下のタスクを実行します:
- タスク 1: 管理者として Federated Learning を開始する
- タスク 2: パーティとしてモデルをトレーニングする
- タスク3: モデルを保存してオンラインで展開する
- タスク4:モデルの採点
注:
- これは、UI 主導の統合学習エクスペリメントを実行するためのステップバイステップ・チュートリアルです。 API 駆動型アプローチのコード・サンプルを確認するには、 統合学習 XGBoost サンプルにアクセスしてください。
- このチュートリアルでは、 admin は統合学習エクスペリメントを開始するユーザーを指し、 party は、管理者によってエクスペリメントが開始された後にモデル結果を送信した 1 人以上のユーザーを指します。 チュートリアルは管理者と複数のパーティーが実行できますが、1 人のユーザーが管理者とパーティーの両方としてフル・スルーを実行することもできます。 より簡潔に説明するために、下記のチュートリアルでは、1 つのデータ・セットのみが 1 つのパーティーによって実行依頼されます。 管理者およびパーティーについて詳しくは、 用語を参照してください。
前提条件
確認するPythonバージョン
管理者と同じ Python バージョンを使用していることを確認してください。 別の Python バージョンを使用すると、互換性の問題が発生する可能性があります。 さまざまなフレームワークと互換性のある Python のバージョンについては、 フレームワークと Python バージョンの互換性を参照してください。
プロジェクトを開きます
既存の プロジェクト を使用するか、新規プロジェクトを作成します。 少なくとも管理者権限が必要です。
watsonx.aiRuntime サービスをプロジェクトに関連付けます。
- プロジェクトで、 「管理」>「サービス」&「統合」をクリックします。
- 「サービスの関連付け」をクリックします。
- リストから'watsonx.aiランタイムインスタンスを選択し、'アソシエイトをクリックします。インスタンスをセットアップするためにインスタンスを持っていない場合は、'新サービスをクリックします。
タスク 1: フェデレーテッド ラーニングを開始する
このセクションでは、Federated Learning 実験を作成、構成、開始します。
タスク1a:フェデレーテッドラーニング実験アセットを作成する
プロジェクトで、資産プロジェクトのタブ。
クリック新しいアセット > 分散データでモデルをトレーニングフェデレーテッド ラーニング実験アセットを作成します。
エクスペリメントの 「名前」 と、オプションで説明を入力します。
機械学習インスタンスの選択」で、関連するwatsonx.aiRuntime インスタンスを確認します。 関連するwatsonx.aiRuntime インスタンスが表示されない場合は、以下の手順に従ってください:
「 Machine Learning サービス・インスタンスの関連付け」をクリックします。
既存のインスタンスを選択して 「関連付け」をクリックするか、 新規サービスを作成します。
再ロード をクリックして、関連付けられたサービスを表示します。
次へ をクリックします。
タスク1b:実験を設定する
「構成」 ページで、 「ハードウェア仕様」を選択します。
「機械学習フレームワーク (Machine learning framework)」 ドロップダウンで、 「scikit-learn」を選択します。
「モデル・タイプ」には、 「XGBoost」を選択します。
「Fusion method」で、 「XGBoost classification fusion」を選択します。
次へ をクリックします。
タスク1c:ハイパーパラメータを定義する
「巡回」 フィールドの値を
5
に設定します。残りのフィールドについては、デフォルト値を受け入れます。
次へ をクリックします。
タスク1d:リモートトレーニングシステムを選択する
「新規システムの追加」をクリックします。
リモート トレーニング システムの名前を入力します。
「許可された ID」の下で、エクスペリメントに参加するユーザーを選択し、 「追加」をクリックします。 この Federated Experiment Training インスタンスには、参加者として許可される ID をいくつでも追加できます。 このチュートリアルでは、自分だけを選択します。
許可されるIDはプロジェクトの協力者であり、少なくとも管理者許可。 使用するリモート・パーティーごとにこのステップを繰り返して、さらにシステムを追加します。完了したら、 システムの追加をクリックしてください。
「リモート・トレーニング・システムの選択 (Select remote training systems)」 ページに戻り、システムが選択されていることを確認してから、 「次へ」をクリックします。
タスク1e:設定を確認する
設定を確認し、 作成をクリックしてください。
状況を監視します。 統合学習エクスペリメントの開始時の状況は 保留中 です。 エクスペリメントでパーティーが接続する準備ができると、状況が セットアップ - リモート・システム待ちに変わります。 数分間かかることがあります。
クリックセットアップ情報を表示パーティ構成と、リモート パーティで実行できるパーティ コネクタ スクリプトをダウンロードします。
作成した各リモートトレーニングシステムの横にある設定のダウンロードアイコンをクリックします。 パーティ コネクタ スクリプトを次の名前でマシン上のディレクトリに保存します。
remote-test-system-configuration.py
「完了」をクリックします。
進捗状況を確認する
次の画像は、「リモート システムを待機中」というステータスの実験を示しています。
タスク 2: パーティとしてモデルをトレーニングする
モデルをトレーニングするには、データ セットをダウンロードし、Python スクリプトを編集して実行する必要があります。 モデルをパーティとしてトレーニングするには、次の手順に従います。
タスク2a:データセットとスクリプトをダウンロードする
新しいローカルディレクトリを作成し、ダウンロードしたパーティコネクタスクリプトをタスクに移動します。 1e新しいディレクトリに。
以下のファイルをファイル名を右クリックしてダウンロードし、リンクを名前を付けて保存。 パーティー・コネクター・スクリプトと同じディレクトリーに保存します。
パーティコネクタスクリプトがあることを確認してください。アダルトデータ セット、データ ハンドラー、およびログ構成ファイルを同じディレクトリに保存します。 ディレクトリ内のファイルを一覧表示すると、次のファイルが表示されます。
adult.csv adult_sklearn_data_handler.py remote-test-system-configuration.py log_config.yaml
タスク2b: watsonx.aiランタイムのインストール
Windowsを使用している場合、またはLinux、 走る
pip install 'ibm_watsonx_ai[fl-rt23.1-py3.10]'
。MシリーズCPUとCondaを搭載したMac OSを使用している場合は、インストールスクリプトそして実行する
./install_fl_rt23.1_macos.sh <name for new conda environment>
。
タスク2c:パーティコネクタスクリプトを編集して実行する
パーティコネクタファイルを編集し、remote-test-systm-configuration.py
、次の変更を加えます。
Python ファイルの 2 行目に次のコードを追加します。
log_config_path = "log_config.yaml"
資格情報を入力します。リモート トレーニング システムで定義されたユーザーの API キーを貼り付けます。 API キーをお持ちでない場合は、IBM CloudAPI keys ページに移動し、Create API key をクリックしてフィールドに入力し、Create をクリックします。
のためにパーティーメタデータフィールドに、名前、パス、および情報を指定します。これは次の JSON テキストのようになります。
party_metadata = { wml_client.remote_training_systems.ConfigurationMetaNames.DATA_HANDLER: { "info": {"txt_file": "./adult.csv"}, "name": "AdultSklearnDataHandler", "path": "./adult_sklearn_data_handler.py" } }
ここで、
name
: データ・ハンドラーに定義されたクラス名。path
: データ・ハンドラーが配置されている場所のパスです。info
: ローカル・データ・セットのファイル・タイプまたはデータ・セットのパスのキーと値のペアを作成します。
パーティコネクタスクリプトを保存します。
パーティコネクタスクリプトを以下のいずれかで実行する。
python
またはpython3
インストールされているものによって異なります。python remote-test-system-configuration.py
UI から、統合学習エクスペリメントの状況をモニターできます。 参加しているすべてのパーティーがアグリゲーターに接続すると、アグリゲーターはローカル・モデルのトレーニングとグローバル・モデルの更新を容易にします。 その状況は トレーニングです。 ユーザー・インターフェースから統合学習エクスペリメントの状況をモニターできます。 訓練が完了すると、パーティーはReceived STOP message
パーティーで。 これで、トレーニングされたモデルを保存し、それをスペースにデプロイできます。
進捗状況を確認する
次の画像は完了した実験を示しています。
タスク3: モデルを保存してオンラインで展開する
このセクションでは、トレーニングしたモデルを保存してデプロイする方法について説明します。
タスク3a:モデルを保存する
- 完了したFederated Learning実験で、集計を保存。
- 上の集約モデルをプロジェクトに保存する画面で、モデルの名前を入力します。 クリック作成する。
- モデルが作成されたという通知が表示されたら、クリックします。プロジェクトで見る。 通知を見逃した場合は、プロジェクト名をクリックしてアセット タブに戻り、モデル名をクリックして表示します。
タスク3b:モデルをスペースに昇格する
- 「モデル」 セクションで、モデルをクリックしてその詳細ページを表示します。
- 配備スペースへのプロモーション' をクリックする。
- 選択してくださいターゲットスペースリストから選択するか、新しいデプロイメント スペースを作成します。
選択する新しいデプロイメントスペースを作成する。
デプロイメント スペースの名前を入力します。
ストレージ サービスを選択します。
機械学習サービスを選択します。
「作成」 をクリックします。
デプロイメント スペースが作成されたら、ウィンドウを閉じます。
- 「プロモート後にスペース内のモデルに移動」 オプションを選択します。
- プロモートをクリックします。
タスク3c:オンライン展開を作成して表示する
- モデルがデプロイメント・スペース内に表示されたら、 新規デプロイメントをクリックしてください。
- デプロイメント・タイプとして オンライン を選択してください。
- デプロイメントの名前を指定します。
- 「作成」 をクリックします。
- 展開ステータスが変わるまで待ちます展開済みをクリックし、デプロイメント名をクリックします。
- アプリケーションでこのデプロイメントを使用するためのエンドポイントとコード スニペットを表示します。
進捗状況を確認する
次の画像はオンライン展開を示しています。
タスク4:モデルの採点
このセクションでは、Python関数を作成し、採点データをトレーニング時と同じフォーマットで処理する方法を学びます。 比較のために、私たちが作成したPython関数を呼び出して、生のデータセットも採点します。
Python スクリプトを作成し、ローカルでスクリプトを実行することもできますし、Jupyterノートブックを作成し、ノートブックでコードを実行することもできます。
環境の セットアップ
このコードでは、必要なライブラリーとパッケージをインポートし、機械学習APIクライアントにアクセスするための認証情報を設定する。
# import the library and package and set the credentials
from ibm_watsonx_ai import APIClient
wml_credentials = {
"url": "https://us-south.ml.cloud.ibm.com",
"apikey": "<insert-api-key-here>"
}
client = APIClient(wml_credentials)
client.set.default_space('<insert-deployment-space-id-here>')
software_spec_id = client.software_specifications.get_id_by_name('default_py3.10')
- IBM Cloud API キーを
apikey
フィールドに貼り付けます。 - 配置スペースIDを貼り付ける。 以下の手順に従って、配置スペース ID を検索してください。
- デプロイメント・スペースに移動します。
- 展開スペースを開く。
- 「管理」 タブをクリックします。
- スペースGUIDをコピーし、コードの
<insert-deployment-space-id-here>
の場所に貼り付けます。
データセットをロードする
このコードは、リソース・ハブに格納されているデータセットを読み込む。
# read the data set
import pandas as pd
import io
import requests
url = "https://api.dataplatform.cloud.ibm.com/v2/gallery-assets/entries/5fcc01b02d8f0e50af8972dc8963f98e/data"
s = requests.get(url).content
adult_csv = pd.read_csv(io.StringIO(s.decode('utf-8')))
adult_csv.head(5)
トレーニングデータセットの作成
このコードでは、データセットから無作為に10行を選んで採点する。
# choose 10 random rows for the test data set
training_data = adult_csv.sample(n=10)
training_data.head(10)
トレーニングデータを準備する関数を定義する
このコードでは、採点データを生のフォーマットでロードし、トレーニング時とまったく同じようにデータを処理する関数を定義している。 そして、処理されたデータを採点する
このコードは、成人のトレーニングデータとテストデータに対して以下の前処理を行う:
以下の特徴を削除する:ワーククラス」、「fnlwgt」、「学歴」、「婚姻状況」、「職業」、「人間関係」、「キャピタル・ゲイン」、「キャピタル・ロス」、「週労働時間」、「出身国」
地図
- 'race'、'sex'、'class'の値を0/1にする
- 白人」: 1、「アメリカ・インディアン・エスキモー」: 0、「アジア・パック・アイスランダー」:0, ' 黒人':0, ' その他': 0
- 男性」:1, ' 女性 ':0
詳細はKamiran, F. and Calders, T. Data preprocessing techniques for classification without discriminationを参照のこと
年齢'と'学歴'カラムを値に基づいて複数のカラムに分割する
# define the preprocess function to prepare the data for scoring
def preprocess(training_data):
if len(training_data.columns)==15:
# drop 'fnlwgt' column
training_data = training_data.drop(training_data.columns[2], axis='columns')
training_data.columns = ['age',
'workclass',
'education',
'education-num',
'marital-status',
'occupation',
'relationship',
'race',
'sex',
'capital-gain',
'capital-loss',
'hours-per-week',
'native-country',
'class']
# filter out columns unused in training, and reorder columns
training_dataset = training_data[['race', 'sex', 'age', 'education-num', 'class']]
# map 'sex' and 'race' feature values based on sensitive attribute privileged/unpriveleged groups
training_dataset['sex'] = training_dataset['sex'].map({
' Female': 0,
' Male': 1
})
training_dataset['race'] = training_dataset['race'].map({
' Asian-Pac-Islander': 0,
' Amer-Indian-Eskimo': 0,
' Other': 0,
' Black': 0,
' White': 1
})
# map 'class' values to 0/1 based on positive and negative classification
training_dataset['class'] = training_dataset['class'].map({' <=50K': 0, ' >50K': 1})
training_dataset['age'] = training_dataset['age'].astype(int)
training_dataset['education-num'] = training_dataset['education-num'].astype(int)
# split age column into category columns
for i in range(8):
if i != 0:
training_dataset['age' + str(i)] = 0
for index, row in training_dataset.iterrows():
if row['age'] < 20:
training_dataset.loc[index, 'age1'] = 1
elif ((row['age'] < 30) & (row['age'] >= 20)):
training_dataset.loc[index, 'age2'] = 1
elif ((row['age'] < 40) & (row['age'] >= 30)):
training_dataset.loc[index, 'age3'] = 1
elif ((row['age'] < 50) & (row['age'] >= 40)):
training_dataset.loc[index, 'age4'] = 1
elif ((row['age'] < 60) & (row['age'] >= 50)):
training_dataset.loc[index, 'age5'] = 1
elif ((row['age'] < 70) & (row['age'] >= 60)):
training_dataset.loc[index, 'age6'] = 1
elif row['age'] >= 70:
training_dataset.loc[index, 'age7'] = 1
# split age column into multiple columns
training_dataset['ed6less'] = 0
for i in range(13):
if i >= 6:
training_dataset['ed' + str(i)] = 0
training_dataset['ed12more'] = 0
for index, row in training_dataset.iterrows():
if row['education-num'] < 6:
training_dataset.loc[index, 'ed6less'] = 1
elif row['education-num'] == 6:
training_dataset.loc[index, 'ed6'] = 1
elif row['education-num'] == 7:
training_dataset.loc[index, 'ed7'] = 1
elif row['education-num'] == 8:
training_dataset.loc[index, 'ed8'] = 1
elif row['education-num'] == 9:
training_dataset.loc[index, 'ed9'] = 1
elif row['education-num'] == 10:
training_dataset.loc[index, 'ed10'] = 1
elif row['education-num'] == 11:
training_dataset.loc[index, 'ed11'] = 1
elif row['education-num'] == 12:
training_dataset.loc[index, 'ed12'] = 1
elif row['education-num'] > 12:
training_dataset.loc[index, 'ed12more'] = 1
training_dataset.drop(['age', 'education-num'], axis=1, inplace=True)
# move class column to be last column
label = training_dataset['class']
training_dataset.drop('class', axis=1, inplace=True)
training_dataset['class'] = label
return training_dataset
トレーニングデータを処理する
このコードでは、プリプロセス関数を使ってデータを準備する。
# use the preprocess function to prepare the data
processed_dataset = preprocess(training_data)
# drop class column
processed_dataset.drop('class', inplace=True, axis='columns')
processed_dataset.head(10)
採点用データペイロードの作成
このコードで得点データセットが作成される。
# create data payload for scoring
fields = processed_dataset.columns.values.tolist()
values = processed_dataset.values.tolist()
scoring_dataset = {client.deployments.ScoringMetaNames.INPUT_DATA: [{'fields': fields, 'values': values}]}
import json
print("Scoring data: ")
scoring_formatted = json.dumps(scoring_dataset, indent=2)
print(scoring_formatted)
モデルを採点する
このコードでは、scoring_datasetを使ってモデルにスコアリングのリクエストを送ります。 このコードには、オンライン配備IDを含める必要があります。 以下の手順に従って、オンライン配備IDを検索してください。
- デプロイメント・スペースに移動します。
- 展開スペースを開く。
- デプロイメント タブをクリックしてください。
- オンライン配備を開きます。
- 情報ペインで、デプロイメントIDをコピーし、下のセルの
<insert-your-online-deployment-id-here>
の代わりに貼り付けます。
# score data
prediction = client.deployments.score('<insert-your-online-deployment-id-here>', scoring_dataset)
print("Predictions and probabilities: ")
prediction_formatted = json.dumps(prediction, indent=2)
print(prediction_formatted)
進捗状況を確認する
以下の画像は、完了したスコアリング・リクエストからの予測値と確率を示している
今後のステップ
カスタマイズされた独自の統合エクスペリメントを作成する準備ができたら、 統合学習エクスペリメントの作成の手順の概要を参照してください。
親トピック: 統合学習のチュートリアルとサンプル