Cloud Pak for Data as a Service の Federated Learning: Remote Training System へトレーニング参加者の許可IPアドレスを構成する

## 本記事の目的

本記事では、IBM Cloud上で提供される Cloud Pak for Data as a Service を対象に、
Watson Studio および Machine learning サービスを使用した Federated Learning 機能で、
トレーニング参加者が使用する許可IPアドレスを構成する方法を紹介します。

## 1. 許可IPアドレスの構成方法

モデルのトレーニング参加者を定義するコンポーネント、`Remote Training System(RTS)`へ、`ホワイトリスト方式`で構成します。
許可IPアドレスには、トレーニング機能(Party)から統合機能(Aggregator)へのインターネット経由での通信に使用される`グローバルIPアドレス`を使用してください。

本記事では、RTSの定義サンプルと、許可IPアドレス構成時の挙動を示します。

参考資料：Creating a Federated Learning experiment > Step 2: Create the remote training system
https://dataplatform.cloud.ibm.com/docs/content/wsj/analyze-data/fl-start.html?audience=wdp&locale=en#rts

Federated Learning機能利用時の一連の手順につきましては、別記事をご参照ください。

[IBM Cloud の Watson Studio と Watson Machine learningサービスで、Federated Learningを動かす（API編）](https://qiita.com/1000aki/items/f6200c75e2d710fa2718)
[IBM Cloud の Watson Studio と Watson Machine learningサービスで、Federated Learningを動かす（UI編）](https://qiita.com/1000aki/items/5e5290a7665d63e96727)


### API(Python SDK)の使用

まず、トレーニング機能を実行する環境のグローバルIPアドレスを確認します。

```python:グローバルIPアドレスの確認
import requests
res = requests.get('http://inet-ip.info/ip')
print(res.text)
```
```text:出力例
52.117.xxx.xx
```

`Remote Training System(RTS)`の作成時、`allowed_ips`オプションにて調べたIPアドレスを指定します。
指定可能なIPアドレスの表記は、`個別のIPアドレス`または`CIDR形式`です。カンマ区切りで、複数のIPアドレスを指定することも可能です。

:::note info
`allowed_ips`オプションを使用しない場合、すべてのIPアドレスが許可されます。
:::

```python:RTSの作成
my_ips = ["52.117.xxx.xx"]
wml_remote_training_system_asset_one_def = Template("""
{
"name": "Remote Party 1",
"project_id": "$projectId",
"description": "Sample Remote Training System",
"tags": [ "$tag" ],
"organization": {
    "name": "IBM",
    "region": "US"
},
"allowed_identities": [
    {
    "id": "$userID",
    "type": "user",
    "allowed_ips":"$allowedIps"
    }
],
"remote_admin": {
    "id": "$userID",
    "type": "user"
}
}
""").substitute(userID = CLOUD_USERID,
                projectId = PROJECT_ID,
                allowedIps = my_ips,
                tag = RTS_TAG)


wml_remote_training_system_one_resp = requests.post(WML_SERVICES_URL + "/ml/v4/remote_training_systems", 
                                                    headers={"Content-Type": "application/json",
                                                            "Authorization": token}, 
                                                    params={"version": API_VERSION,
                                                            "project_id": PROJECT_ID}, 
                                                    data=wml_remote_training_system_asset_one_def, 
                                                    verify=False)

print(wml_remote_training_system_one_resp)
status_json = json.loads(wml_remote_training_system_one_resp.content.decode("utf-8"))
print("Create remote training system response : "+ json.dumps(status_json, indent=4))

wml_remote_training_system_one_asset_uid = json.loads(wml_remote_training_system_one_resp.content.decode("utf-8"))["metadata"]["id"]
print("Remote Training System id: %s" % wml_remote_training_system_one_asset_uid)
```

### UIの使用

統合学習エクスペリメントを作成する流れで、`Remote Training System(RTS)`を新規作成するこができます。
その際、許可ユーザーIDに対し、`IPアドレスの構成`を行います。
設定可能なIPアドレスの表記形式は、個別のIPアドレスまたはCIDR形式です。カンマ区切りで、複数のIPアドレスを設定可能です。

:::note info
`IPアドレスの構成`を使用しない場合、すべてのIPアドレスが許可されます。
:::

- リモート・トレーニング・システムの作成画面で、`許可されたID`を指定後、「構成」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237849/cc7ea469-f6ed-7653-ddde-78e55b3b4a7b.png)

- 許可されたIDをチェック後、ユーザーに対して許可するIPアドレスを入力し、保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237849/3b128446-c049-d028-ac35-2f5bbf10e8f9.png)

- `1つの許可されたIDに対して構成済み`であることを確認し、追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237849/b7c7cb00-5162-a78d-1c7c-4443e52e2774.png)


- 「システムの追加」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237849/a9d10782-f550-9dfc-2c83-0985b3550b4f.png)


## 2. 許可IPアドレス構成時の挙動

トレーニング参加者として、Partyを実行します。

### 未許可IPアドレスからトレーニング起動

トレーニング機能を実行する環境にて、IPアドレスを確認します。

```python:グローバルIPアドレスの確認
import requests
res = requests.get('http://inet-ip.info/ip')
print(res.text)
```
```text:出力例
169.61.xxx.xx
```

`Remote Training System(RTS)`で、未許可のIPアドレスを使用します。
トレーニング機能(Party)の起動後、`FLException`が発生し、トレーニングが停止しました。

```python:トレーニング機能の起動
party.run(aggregator_id=TRAINING_ID, asynchronous=False)
```
```text:エラー発生時の出力例
Loading py39-tf27-pt110-sk10 environment..
2022-04-20T11:31:59.709Z | 1.0.204 | INFO | ibmfl.util.config                                  | No model config provided for this setup.
2022-04-20T11:31:59.752Z | 1.0.204 | INFO | ibmfl.util.config                                  | No metrics config provided for this setup.
2022-04-20T11:31:59.754Z | 1.0.204 | INFO | ibmfl.util.config                                  | No evidencia recordeer config provided for this setup.

2022-04-20T11:32:21.306Z | 1.0.204 | INFO | ibmfl.party.party                                  | Party initialization successful
2022-04-20T11:32:21.306Z | 1.0.204 | INFO | ibmfl.party.party                                  | Party not registered yet.
2022-04-20T11:32:21.306Z | 1.0.204 | INFO | ibmfl.party.party                                  | Registering party...
2022-04-20T11:32:22.521Z | 1.0.204 | INFO | ibmfl.connection.websockets_connection             | Received Heartbeat from Aggregator
2022-04-20T11:32:22.530Z | 1.0.204 | INFO | ibmfl.connection.websockets_connection             | Authorization Error. Please verify ip address, training ID, RTS, project permission and token
2022-04-20T11:32:22.532Z | 1.0.204 | ERROR | ibmfl.party.party                                  | Registration Failed: Failure status from aggregator
2022-04-20T11:32:22.533Z | 1.0.204 | ERROR | ibmfl.party.party                                  | No Detail Provided
2022-04-20T11:32:22.534Z | 1.0.204 | INFO | ibmfl.party.party                                  | Party stop successful
2022-04-20T11:32:22.547Z | 1.0.204 | INFO | ibmfl.connection.websockets_connection             | ConnectionClosedError encountered.
---------------------------------------------------------------------------
FLException                               Traceback (most recent call last)
/opt/conda/envs/Python-3.9/lib/python3.9/site-packages/ibm_watson_machine_learning/party_wrapper.py in run(self, aggregator_id, asynchronous, verify)
    262                 self.connection = self.Party.connection
--> 263                 self.start()
    264             else:

/opt/conda/envs/Python-3.9/lib/python3.9/site-packages/ibm_watson_machine_learning/party_wrapper.py in start(self)
    185     def start(self):
--> 186         self.Party.start()
    187 

/opt/conda/envs/Python-3.9/lib/python3.9/site-packages/ibm_watson_machine_learning/libs/ibmfl/py38-tf24-pt17-sk23/ibmfl/party/party.py in start(self)
    263                 self.stop_connection()
--> 264                 raise FLException(
    265                     "Error occurred while registering party. ")

FLException: Error occurred while registering party. 

During handling of the above exception, another exception occurred:

FLException                               Traceback (most recent call last)
/tmp/wsuser/ipykernel_154/1372079034.py in <module>
----> 1 party.run(aggregator_id=TRAINING_ID, asynchronous=False)

/opt/conda/envs/Python-3.9/lib/python3.9/site-packages/ibm_watson_machine_learning/party_wrapper.py in run(self, aggregator_id, asynchronous, verify)
    272                 logger.info("The training finishes with %s status" % state)
    273         except FLException as ex:
--> 274             raise FLException(str(ex))
    275         except Exception as ex:
    276             logger.info("The party failed to start training")

FLException: Error occurred while registering party. 
```

### 許可済IPアドレスからトレーニング起動

`Remote Training System(RTS)`で、許可リストに登録済みのIPアドレスを使用します。
トレーニング機能(Party)の起動後、統合機能(Aggregator)への通信が成功し、トレーニングが実行されました。

```python:トレーニング機能の起動
party.run(aggregator_id=TRAINING_ID, asynchronous=False)
```
```text:成功時の出力例
Loading py39-tf27-pt110-sk10 environment..
2022-04-20T11:43:39.787Z | 1.0.204 | INFO | ibmfl.util.config                                  | No model config provided for this setup.
2022-04-20T11:43:39.821Z | 1.0.204 | INFO | ibmfl.util.config                                  | No metrics config provided for this setup.
2022-04-20T11:43:39.823Z | 1.0.204 | INFO | ibmfl.util.config                                  | No evidencia recordeer config provided for this setup.

2022-04-20T11:44:06.401Z | 1.0.204 | INFO | ibmfl.party.party                                  | Party initialization successful
2022-04-20T11:44:06.402Z | 1.0.204 | INFO | ibmfl.party.party                                  | Party not registered yet.
2022-04-20T11:44:06.402Z | 1.0.204 | INFO | ibmfl.party.party                                  | Registering party...
2022-04-20T11:44:07.601Z | 1.0.204 | INFO | ibmfl.connection.websockets_connection             | Received Heartbeat from Aggregator
2022-04-20T11:44:08.670Z | 1.0.204 | INFO | ibmfl.party.party_protocol_handler                 | received a async request
2022-04-20T11:44:08.672Z | 1.0.204 | INFO | ibmfl.party.party                                  | No model package received from aggregator.
2022-04-20T11:44:08.672Z | 1.0.204 | INFO | ibmfl.party.party_protocol_handler                 | finished async request
2022-04-20T11:44:08.673Z | 1.0.204 | INFO | ibmfl.party.party_protocol_handler                 | Handling async request in a separate thread
2022-04-20T11:44:08.674Z | 1.0.204 | INFO | ibmfl.party.party                                  | Checking for model config in payload.
2022-04-20T11:44:08.677Z | 1.0.204 | INFO | ibmfl.party.party_protocol_handler                 | Received request from aggregator
2022-04-20T11:44:08.679Z | 1.0.204 | INFO | ibmfl.party.party                                  | {'cls_ref': <class 'ibmfl.model.xgb_fl_model.XGBClassifierFLModel'>, 'spec': {'global': {'learning_rate': 0.1, 'num_classes': 2, 'rounds': 3, 'num_parties': 1, 'perc_quorum': 1.0, 'max_timeout': 43200, 'loss': 'auto', 'max_iter': 3}}}

(略)

2022-04-20T11:45:09.783Z | 1.0.204 | INFO | ibmfl.party.training.local_training_handler        | {'acc': 0.7587901120835252, 'f1': 0.0, 'precision': 0.0, 'recall': 0.0, 'average precision': 0.24, 'roc auc': 0.5, 'negative log loss': 8.33}
2022-04-20T11:45:11.743Z | 1.0.204 | INFO | ibmfl.party.party_protocol_handler                 | Received request from aggregator
2022-04-20T11:45:11.745Z | 1.0.204 | INFO | ibmfl.party.party_protocol_handler                 | Received request in with message_type:  14
2022-04-20T11:45:11.747Z | 1.0.204 | INFO | ibmfl.party.party_protocol_handler                 | Received request in PH 14
2022-04-20T11:45:11.748Z | 1.0.204 | INFO | ibmfl.party.party_protocol_handler                 | received a STOP request

```

## 3. 関連資料

CP4DaaSのFederated Learningに関連する資料です。

製品資料：IBM Federated Learning
https://dataplatform.cloud.ibm.com/docs/content/wsj/analyze-data/fed-lea.html?audience=wdp&locale=en

APIドキュメント：Watson Machine Learning
https://cloud.ibm.com/apidocs/machine-learning-cp

Pythonライブラリ：ibm-watson-machine-learning
https://pypi.org/project/ibm-watson-machine-learning/