使用FATE進行圖片識別的深度神經網絡聯邦學習

*本文做者系VMware雲原生實驗室工程師 彭路html

FATE(Federated AI Technology Enabler)是聯邦機器學習技術的一個框架,其旨在提供安全的計算框架來支持聯邦 AI 生態。FATE 實現了基於同態加密和多方計算(MPC)的安全計算協議,它支持聯邦學習架構和各類機器學習算法的安全計算,包括邏輯迴歸、基於樹的算法、深度學習和轉移學習。python

聯邦機器學習又名聯邦學習、聯合學習與聯盟學習,它能有效幫助多個機構在知足用戶隱私保護、數據安全和相關法規的要求下,進行數據使用和機器學習建模,消除因爲行業競爭、隱私安全與行政手續等問題帶來的數據孤島,讓以數據爲基礎的機器學習順利進行。mysql

KubeFATE支持經過Docker Compose和Kubernetes進行FATE部署。咱們建議使用Docker Compose安裝快速開發和學習FATE集羣,同時使用Kubernetes安裝生產環境。linux

深度神經網絡(DNN)是在輸入和輸出層之間具備多層的人工神經網絡(ANN)。git

本文以經典的神經網絡MNIST爲例子,展現聯邦學習版的深度神經網絡訓練過程。咱們使用KubeFATE快速進行FATE框架的部署。由於模擬聯邦學習的雙方,咱們須要準備兩臺Ubuntu的機器(物理機或虛擬機)。github

一.安裝docker和docker-compose
Ubuntu 安裝docker:
redis

$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

安裝docker-compose:算法

$ sudo curl -L 
https://github.com/docker/compose/releases/download/1.23.2/docker-compo
se-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

二.安裝KubeFATE
學習環境推薦使用Docker方式部署。使用Docker方式部署分爲兩步,先根據parties.conf配置文件生成docker-compose文件。經過scp把docker-compose文件複製到目標機器上,而後經過ssh命令登陸到目標機器並運「docker-compose up」。
sql

選擇兩臺機器其中之一做爲部署機。docker

1.在KubeFATE的release頁面下載軟件包kubefate-docker-compose.tar.gz並解壓:

$ wget 
https://github.com/FederatedAI/KubeFATE/releases/download/v1.3.0-a/kubefate-docker-compose.tar.gz

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

2.進入docker-deploy/ 目錄,修改parties.conf文件:

$ cd docker-deploy
$ vi parties.conf

parties.conf:

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

說明:
user:兩臺目標機器的用戶id,建議用戶root或權限合適的用戶。
dir:目標機器上存放docker-compose文件的目錄。
partylist:FATE集羣的party列表。這裏是兩方,用數字表示。
partyiplist:FATE訓練集羣的IP地址,與partylist對應,例如上例id爲10000的訓練集羣ip地址是10.160.175.20。注意這裏要替換成你準備的兩臺機器對應的IP。
servingiplist:FATE在線推理集羣的IP地址,與partylist對應,能夠和訓練集羣在一臺機器上,也能夠單獨是一臺機器。本文裏訓練集羣和在線推理集羣使用同一臺機器。
exchangeip:多於兩方部署的時候推薦使用exchange模式。Exchange是一個集中交換數據的節點,記錄了全部party的IP地址,每一個party只須要知道exchange節點的IP地址就可交換數據。本文是兩方直連,全部不填寫exchange。

3.生成部署FATE的docker-compose文件

$ bash generate_config.sh

命令會在outputs文件夾下面生成對應的壓縮包:confs-<partyID>.tar和serving-<partyID>.tar。

4.部署FATE

$ bash docker_deploy.sh all

由於用到了scp和ssh命令,因此運行這條命令的時候須要輸入密碼。爲了方即可以在部署機和目標機之間作免密碼處理。

兩臺機器在互聯網可用環境下,Docker會自動下載FATE須要的鏡像。若是是沒有互聯網的環境,參考Github上使用離線鏡像文章使用離線鏡像文章。
https://github.com/FederatedAI/KubeFATE/tree/master/registry

5.免密處理(可選)
用10.160.175.20做爲部署機,須要能夠免密碼登陸本機和10.160.162.5 (目標機)。

生成ssh key:

$ ssh-keygen -t rsa

一直回車便可,會在~/.ssh/目錄下生成一個id_rsa.pub文件。分別在兩個機器的~/.ssh/目錄下新建一個authorized_keys文件,並把剛剛生成id_rsa.pub的內容填寫進去。

6.驗證是否部署成功。分別登陸兩臺機器運行如下命令來驗證:

$ docker ps

CONTAINER ID    IMAGE                                       ...
11e86440c02d    redis:5                                     ...
16570fa47d36    federatedai/serving-server:1.2.2-release    ...
b64b251e9515    federatedai/serving-proxy:1.2.2-release     ...
75603d077a94    federatedai/fateboard:1.3.0-release         ...
38cb63178b79    federatedai/python:1.3.0-release            ...
80876768cd35    federatedai/roll:1.3.0-release              ...
955bab0ae542    federatedai/meta-service:1.3.0-release      ...
89928bf28b37    federatedai/egg:1.3.0-release               ...
63e4ae852d0d    mysql:8                                     ...
3cc1a4709765    federatedai/proxy:1.3.0-release             ...
0e1d945b852c    federatedai/federation:1.3.0-release        ...
f51e2e77af88    redis:5                                     ...

三.準備數據集
本文使用MNIST數據集,MNIST是手寫數字識別的數據集。從kaggle下載csv格式的數據集。

FATE訓練時須要數據集有id,MNIST數據集裏有6w條數據,模擬橫向聯邦學習,把數據集分爲兩個各有3w條記錄的數據集。

$ awk -F'\t' -v OFS=',' '   NR == 1 {print "id",$0; next}   {print (NR-1),$0}' mnist_train.csv > mnist_train_with_id.csv

這句話是在第一行最前面加上id,第二行開始加序號,並用逗號做爲分隔符。

$ sed -i "s/label/y/g" mnist_train_with_id.csv

將表頭的label替換成y,在FATE裏label的名字一般爲y。

split -l 30001 mnist_train_with_id.csv mnist_train_3w.csv

將mnist_train_with_id.csv分割,每個文件有30001行(一行標題和30000行數據)。會生成兩個文件:mnist_train_3w.csvaa和mnist_train_3w.csvab。將兩個文件重命名:

$ mv mnist_train_3w.csvaa mnist_train_3w_a.csv
$ mv mnist_train_3w.csvab mnist_train_3w_b.csv
$ sed -i "`cat -n mnist_train_3w_a.csv |head -n 1`" mnist_train_3w_b.csv

將mnist_train_3w_a.csv文件的第一行(csv的表頭)插入mnist_train_3w_b.csv的最前面。這樣咱們就獲得了兩個有表頭和id的數據集,各有30000條數據。

分別將兩個文件拷貝到兩臺機器上的/data/projects/fate/confs-<partyID>/shared_dir/examples/data目錄裏。

Shared_dir目錄是本地文件系統和docker容器中文件系統的共享目錄,使容器能夠訪問宿主機的文件。

四,準備FATE Pipeline
本文在FATE裏使用Keras運行DNN,參考文章

1.    準備Keras模型:
進入guest方(本文選用9999做爲guest)的python容器:

$ docker exec -it confs-9999_python_1 bash

進入Python解釋器:

$ python

構建一個Keras模型:

>>>import keras
>>>from keras.models import Sequential
>>>from keras.layers import Dense, Dropout, Flatten
>>>model = Sequential()
>>>model.add(Dense(512,activation='relu',input_shape=(784,)))
>>>model.add(Dense(256,activation='relu'))
>>>model.add(Dense(10,activation='softmax'))

獲得json格式的模型:

>>>json = model.to_json()
>>>print(json)

{"class_name""Sequential""config": {"name""sequential_1""layers": [{"class_name""Dense""config": {"name""dense_1""trainable"true"batch_input_shape": [null784], "dtype""float32""units"512"activation""relu""use_bias"true"kernel_initializer": {"class_name""VarianceScaling""config": {"scale"1.0"mode""fan_avg""distribution""uniform""seed"null}}, "bias_initializer": {"class_name""Zeros""config": {}}, "kernel_regularizer"null"bias_regularizer"null"activity_regularizer"null"kernel_constraint"null"bias_constraint"null}}, {"class_name""Dense""config": {"name""dense_2""trainable"true"units"256"activation""relu""use_bias"true"kernel_initializer": {"class_name""VarianceScaling""config": {"scale"1.0"mode""fan_avg""distribution""uniform""seed"null}}, "bias_initializer": {"class_name""Zeros""config": {}}, "kernel_regularizer"null"bias_regularizer"null"activity_regularizer"null"kernel_constraint"null"bias_constraint"null}}, {"class_name""Dense""config": {"name""dense_3""trainable"true"units"10"activation""softmax""use_bias"true"kernel_initializer": {"class_name""VarianceScaling""config": {"scale"1.0"mode""fan_avg""distribution""uniform""seed"null}}, "bias_initializer": {"class_name""Zeros""config": {}}, "kernel_regularizer"null"bias_regularizer"null"activity_regularizer"null"kernel_constraint"null"bias_constraint"null}}]}, "keras_version""2.2.4""backend""tensorflow"}

2.    修改test_homo_nn_keras_temperate.json

vi examples/federatedml-1.x-examples/homo_nn/test_homo_nn_keras_temperate.json 

將剛剛輸出的json格式的模型替換到algorithm_parameters. homo_nn_0.$nn_define位置。

將work_mode設置爲1,將guest設置爲9999,host和arbiter爲10000,將

{
    "initiator": {
        "role""guest",
        "party_id"9999
    },
    "job_parameters": {
        "work_mode"1
    },
    "role": {
        "guest": [
            9999
        ],
        "host": [
            10000
        ],
        "arbiter": [
            10000
        ]
    },

修改guest和host數據集的名字和命名空間,role_parameters. guest.args.data. train_data:

"name""homo_mnist_guest",
"namespace""homo_mnist_guest"

role_parameters. host.args.data. train_data:

"name""homo_mnist_host",
"namespace""homo_mnist_host"

3.    分別上傳host方(10000)和guest方(9999)數據
新建upload_data_guest.json

$ vi examples/federatedml-1.x-examples/homo_nn/upload_data_guest.json

{
    "file""examples/data/mnist_train_3w_b.csv",
    "head"1,
    "partition"10,
    "work_mode"1,
    "table_name""homo_mnist_guest",
    "namespace""homo_mnist_guest"
}

上傳數據到FATE:

$ python fate_flow/fate_flow_client.py -f upload -c examples/federatedml-1.x-examples/homo_nn/upload_data_guest.json

登錄到host(10000)機器的Python容器,並對應新建upload_data_host.json

$ docker exec -it confs-10000_python_1 bash
$ vi examples/federatedml-1.x-examples/homo_nn/upload_data_host.json

{
    "file""examples/data/mnist_train_3w_a.csv",
    "head"1,
    "partition"10,
    "work_mode"1,
    "table_name""homo_mnist_host",
    "namespace""homo_mnist_host"
}

上傳數據到FATE:

$ python fate_flow/fate_flow_client.py -f upload -c examples/federatedml-1.x-examples/homo_nn/upload_data_host.json

登陸到FateBoard能夠查看上傳任務狀況,FateBoard的地址是http://party-IP:8080,以下圖所示爲成功:
 
4.    用fate_flow運行DNN

FATE的訓練應該由guest方發起,因此咱們登陸到guest的Python容器:

$ docker exec -it confs-9999_python_1 bash

使用fate_flow運行DNN任務:

$ python fate_flow/fate_flow_client.py -f submit_job -c examples/federatedml-1.x-examples/homo_nn/test_homo_nn_keras_temperate.json -d examples/federatedml-1.x-examples/homo_nn/test_homo_nn_train_then_predict.json

獲得輸出:

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

model_id和model_version合起來是肯定一個模型的依據,下一步進行預測時候會用到。

登陸fateboard查看任務,下圖爲完成訓練:
 

五.使用模型預測
咱們用以前訓練的MNIST數據集來作預測,因此就不用再上傳數據了。

$ awk -F'\t' -v OFS=',' '   NR == 1 {print "id",$0; next}   {print (NR-1),$0}' mnist_test.csv > mnist_test_with_id.csv

$ sed -i "s/label/y/g" mnist_test_with_id.csv

1.    定義預測pipeline

預測也是由guest(9999)方發起,新建test_predict_conf.json

$ vi examples/federatedml-1.x-examples/homo_nn/test_predict_conf.json

{
    "initiator": {
        "role""guest",
        "party_id"9999
    },
    "job_parameters": {
        "work_mode"1,
        "job_type""predict",
        "model_id""arbiter-10000#guest-9999#host-10000#model",
        "model_version""202003191510586887818"
    },
    "role": {
        "guest": [9999],
        "host": [10000],
        "arbiter": [10000]
    },
    "role_parameters": {
        "guest": {
            "args": {
                "data": {
                    "eval_data": [{"name""homo_mnist_guest""namespace""homo_mnist_guest"}]
                }
            }
        },
        "host": {
            "args": {
                "data": {
                    "eval_data": [{"name""homo_mnist_host""namespace""homo_mnist_host"}]
                }
            }
        }
    }
}

job_parameters 裏面的model_id和model_version就是剛剛訓練時輸出裏面的,guest和host的數據的名字和命名空間都和訓練時一致。

2.    進行預測

$ python fate_flow/fate_flow_client.py -f submit_job -c examples/federatedml-1.x-examples/homo_nn/test_predict_conf.json

登陸Fateboard查看是否完成預測。

3.    下載預測結果

$ python fate_flow/fate_flow_client.py -f component_output_data -j 2020032001133193102117 -p 9999 -r guest -cpn homo_nn_1 -o examples/federatedml-1.x-examples/homo_nn

f:fate_flow的任務種類,component_output_data是獲取模塊輸出用的。
j:jobID,在剛剛預測時候輸出裏。
p:partyID,guest方是9999。
r:角色,guest。
cpn:模塊名稱,是訓練模型時pipeline(examples/federatedml-1.x-examples/homo_nn/test_homo_nn_train_then_predict.json)定義的,本次是homo_nn_1。
o是下載結果的輸出路徑。

運行完這條命令以後,會發現examples/federatedml-1.x-examples/homo_nn/目錄下多了一個job_2020032001133193102117_homo_nn_1_guest_9999_output_data目錄。

查看一下這個目錄裏面的內容:

ls job_2020032001133193102117_homo_nn_1_guest_9999_output_data

output_data.csv  output_data_meta.json

output_data.csv:預測的結果集。

output_data_meta.json:結果集的元數據,就是結果集表頭。

諮詢與KubeFATE相關問題可經過kubefate@vmware.com聯繫咱們。

相關文章
相關標籤/搜索