使用KubeFATE快速部署聯邦學習實驗開發環境(二)

在前面的文章中,我們介紹過如何使用KubeFATE來部署一個單節點的FATE聯邦學習集羣。在真實的應用場景中,聯邦學習往往需要多個參與方聯合起來一起完成任務。基於此,本文將講述如何通過KubeFATE和Docker-Compose來部署兩個參與方的FATE集羣,並在集羣上運行一些簡單的測試以驗證其功能的完整性。

FATE集羣的組網方式

聯邦學習的訓練任務需要多方參與,如圖1所示,每一個party node都是一方,並且每個party node都有各自的一套FATE集羣。而party node和party node之間的發現方式有兩種。分別是點對點和星型。默認情況下,使用KubeFATE部署的多方集羣會通過點對點的方式組網,但KubeFATE也可以單獨部署Exchange服務以支持星型組網。

部署兩方訓練的集羣

使用KubeFATE和Docker-Compose部署兩方訓練的集羣

KubeFATE的使用分成兩部分,第一部分是生成FATE集羣的啓動文件(docker-compose.yaml),第二個部分是通過docker-compose的方式去啓動FATE集羣。從邏輯上可將進行這兩部分工作的機器分別稱爲部署機和目標機器。

目標

兩個可以互通的FATE實例,每個實例均包括FATE所有組件,實例分別部署在不同的兩臺機器上。

準備工作

1、兩個主機(物理機或者虛擬機,Ubuntu或Centos7系統,允許以root用戶登錄);
2、所有主機安裝Docker 版本 : 18+;
3、所有主機安裝Docker-Compose 版本: 1.24+;
4、部署機可以聯網,所以主機相互之間可以網絡互通;
5、運行機已經下載FATE 的各組件鏡像

Docker的安裝以及FATE鏡像的下載請參考前文,接下來我們將把兩臺主機劃分爲workspace1和workspace2。其中workspace1既作爲部署機也作爲目標機,而workspace2則作爲目標機,每個機器運行一個FATE實例。這裏兩臺主機的IP分別爲192.168.7.1和192.168.7.2。用戶需要根據實際情況做出修改。具體部署架構如圖2所示。

以下操作需在workspace1上並以root用戶進行。

下載並解壓Kubefate1.3的kubefate-docker-compose.tar.gz資源包

# curl -OL
https://github.com/FederatedAI/KubeFATE/releases/download/v1.3.0/kubefate-docker-compose.tar.gz

# tar -xzf kubefate-docker-compose.tar.gz

定義需要部署的實例數目

進入docker-deploy目錄
# cd docker-deploy/

編輯parties.conf如下
# vi parties.conf 

user=root                                   
dir=/data/projects/fate                     
partylist=(10000 9999)                      
partyiplist=(192.168.7.1 192.168.7.2)       
servingiplist=(192.168.7.1 192.168.7.2)     
exchangeip=  

根據以上定義party 10000的集羣將部署在workspace1上,而party 9999的集羣將部署在workspace2上。

執行生成集羣啓動文件腳本

# bash generate_config.sh 

執行啓動集羣腳本

# bash docker_deploy.sh all

命令輸入後需要用戶輸入4次root用戶的密碼 

驗證集羣基本功能

# docker exec -it confs-10000_python_1 bash

# cd /data/projects/fate/python/examples/toy_example

# python run_toy_example.py 10000 9999 1

如果測試通過,屏幕將顯示類似如下消息:

"2019-08-29 07:21:25,353 - secure_add_guest.py[line:96] - INFO: begin to init parameters of secure add example guest"
"2019-08-29 07:21:25,354 - secure_add_guest.py[line:99] - INFO: begin to make guest data"
"2019-08-29 07:21:26,225 - secure_add_guest.py[line:102] - INFO: split data into two random parts"
"2019-08-29 07:21:29,140 - secure_add_guest.py[line:105] - INFO: share one random part data to host"
"2019-08-29 07:21:29,237 - secure_add_guest.py[line:108] - INFO: get share of one random part data from host"
"2019-08-29 07:21:33,073 - secure_add_guest.py[line:111] - INFO: begin to get sum of guest and host"
"2019-08-29 07:21:33,920 - secure_add_guest.py[line:114] - INFO: receive host sum from guest"
"2019-08-29 07:21:34,118 - secure_add_guest.py[line:121] - INFO: success to calculate secure_sum, it is 2000.0000000000002"

驗證Serving-Service功能

以下內容將會對部署好的兩個FATE集羣進行簡單的訓練和推理測試。訓練所用到的數據集是”breast”,其中”breast”按列分爲”breast_a”和”breast_b”兩部分,參與訓練的host方持有”breast_a”,而guest方則持有”breast_b”。guest和host將聯合起來對數據集進行一個異構的邏輯迴歸訓練。最後當訓練完成後還會將得到的模型推送到FATE Serving作在線推理。

以下操作在workspace1上進行:

進入python容器

# docker exec -it confs-10000_python_1 bash

進入fate_flow目錄

# cd fate_flow

修改examples/upload_host.json

# vi examples/upload_host.json
{
  "file": "examples/data/breast_a.csv",
  "head": 1,
  "partition": 10,
  "work_mode": 1,
  "namespace": "fate_flow_test_breast",
  "table_name": "breast"
}

把“breast_a.csv”上傳到系統中

# python fate_flow_client.py -f upload -c examples/upload_host.json 

以下操作在workspace2上進行:

進入python容器

# docker exec -it confs-9999_python_1 bash

進入fate_flow目錄

# cd fate_flow

修改examples/upload_guest.json

# vi examples/upload_guest.json
{
  "file": "examples/data/breast_b.csv",
  "head": 1,
  "partition": 10,
  "work_mode": 1,
  "namespace": "fate_flow_test_breast",
  "table_name": "breast"
}

把“breast_b.csv”上傳到系統中

# python fate_flow_client.py -f upload -c examples/upload_guest.json 

修改examples/test_hetero_lr_job_conf.json

# vi examples/test_hetero_lr_job_conf.json
{
    "initiator": {
        "role": "guest",
        "party_id": 9999
    },
    "job_parameters": {
        "work_mode": 1
    },
    "role": {
        "guest": [9999],
        "host": [10000],
        "arbiter": [10000]
    },
    "role_parameters": {
        "guest": {
            "args": {
                "data": {
                    "train_data": [{"name": "breast", "namespace": "fate_flow_test_breast"}]
                }
            },
            "dataio_0":{
                "with_label": [true],
                "label_name": ["y"],
                "label_type": ["int"],
                "output_format": ["dense"]
            }
        },
        "host": {
            "args": {
                "data": {
                    "train_data": [{"name": "breast", "namespace": "fate_flow_test_breast"}]
                }
            },
             "dataio_0":{
                "with_label": [false],
                "output_format": ["dense"]
            }
        }
    },
    ....
}

提交任務對上傳的數據集進行訓練

# python fate_flow_client.py -f submit_job -d examples/test_hetero_lr_job_dsl.json -c examples/test_hetero_lr_job_conf.json

輸出結果:

{
    "data": {
        "board_url": "http://fateboard:8080/index.html#/dashboard?job_id=202003060553168191842&role=guest&party_id=9999",
        "job_dsl_path": "/data/projects/fate/python/jobs/202003060553168191842/job_dsl.json",
        "job_runtime_conf_path": "/data/projects/fate/python/jobs/202003060553168191842/job_runtime_conf.json",
        "logs_directory": "/data/projects/fate/python/logs/202003060553168191842",
        "model_info": {
            "model_id": "arbiter-10000#guest-9999#host-10000#model",
            "model_version": "202003060553168191842"
        }
    },
    "jobId": "202003060553168191842",
    "retcode": 0,
    "retmsg": "success"
}

訓練好的模型會存儲在EGG節點中,模型可通過在上述輸出中的“model_id” 和 “model_version” 來定位。FATE Serving的加載和綁定模型操作都需要用戶提供這兩個值。

查看任務狀態直到”f_status”爲success,把上一步中輸出的“jobId”方在“-j”後面。

# python fate_flow_client.py -f query_task -j 202003060553168191842 | grep f_status

output:

    "f_status": "success",
    "f_status": "success",

修改加載模型的配置,把上一步中輸出的“model_id”和“model_version”與文件中的進行替換。

# vi examples/publish_load_model.json
{
    "initiator": {
        "party_id": "9999",
        "role": "guest"
    },
    "role": {
        "guest": ["9999"],
        "host": ["10000"],
        "arbiter": ["10000"]
    },
    "job_parameters": {
        "work_mode": 1,
        "model_id": "arbiter-10000#guest-9999#host-10000#model",
        "model_version": "202003060553168191842"
    }
}

加載模型

# python fate_flow_client.py -f load -c examples/publish_load_model.json

修改綁定模型的配置, 替換“model_id”和“model_version”,並給“service_id”賦值“test”。其中“service_id”是推理服務的標識,該標識與一個模型關聯。用戶向FATE Serving發送請求時需要帶上“service_id”,這樣FATE Serving纔會知道用哪個模型處理用戶的推理請求。

# vi examples/bind_model_service.json
{
    "service_id": "test",
    "initiator": {
        "party_id": "9999",
        "role": "guest"
    },
    "role": {
        "guest": ["9999"],
        "host": ["10000"],
        "arbiter": ["10000"]
    },
    "job_parameters": {
        "work_mode": 1,
        "model_id": "arbiter-10000#guest-9999#host-10000#model",
        "model_version": "202003060553168191842"
    }
}

綁定模型

# python fate_flow_client.py -f bind -c examples/bind_model_service.json

在線測試,通過curl發送以下信息到192.168.7.2:8059/federation/v1/inference

curl -X POST -H 'Content-Type: application/json' -d ' {"head":{"serviceId":"test"},"body":{"featureData": {"x0": 0.254879,"x1": -1.046633,"x2": 0.209656,"x3": 0.074214,"x4": -0.441366,"x5": -0.377645,"x6": -0.485934,"x7": 0.347072,"x8": -0.287570,"x9": -0.733474}}' 'http://192.168.7.2:8059/federation/v1/inference'

輸出結果:

{"flag":0,"data":{"prob":0.30684422824464636,"retmsg":"success","retcode":0}

若輸出結果如上所示,則驗證了serving-service的功能是正常的。上述結果說明有以上特徵的人確診概率爲30%左右。

刪除部署

如果需要刪除部署,則在部署機器上運行以下命令可以停止所有FATE集羣:

# bash docker_deploy.sh --delete all

如果想要徹底刪除在運行機器上部署的FATE,可以分別登錄節點,然後運行命令:

# cd /data/projects/fate/confs-<id>/ # the id of party
# docker-compose down
# rm -rf ../confs-<id>/ 

KubeFATE開源項目:

https://github.com/FederatedAI/KubeFATE

FATE開源項目:

https://github.com/FederatedAI/FATE

作者介紹:

彭路,VMware 雲原生實驗室工程師,FATE/KubeFATE 項目貢獻者。

相關文章:

《用 FATE 進行圖片識別的聯邦學習實踐》
《使用 KubeFATE 快速部署聯邦學習實驗開發環境(一)》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章