聯邦學習實戰-2-用FATE從零實現橫向邏輯回歸
文章目錄

一、安裝FATE平臺
三、利用FATE構建橫向聯邦學習Pipeline
3.1 數據轉換輸入
3.2 模型訓練
3.2.1 DSL配置文件
3.2.2 運行配置 Submit Runtime Conf
3.2.3 提交參數,訓練模型
3.3 評估模型
3.4 多參與方環境配置
四、Tips
4.1. 重新啟動fate-flow和fateboard
4.2. ‘NoneType’ object has no attribute ‘count’
4.3. list index out of range
四、Tips
4.1. 重新啟動fate-flow和fateboard
4.2. ‘NoneType’ object has no attribute ‘count’
4.3. list index out of range
一、安裝FATE平臺
FATE是微眾銀行開源的聯邦學習框架
官方地址:https://fate.fedai.org 文檔:https://fate.readthedocs.io/en/latest/_build_temp/standalone-deploy/doc/Fate-standalone_deployment_guide_zh.html https://github.com/FederatedAI/Practicing-Federated-Learning/tree/main/chapter05_FATE_HFL
1
2
3
4
5
注意:書本使用的FATE是1.4.0版本,而我使用的是1.6.0版本(2021-8-13),文中的配置文件中的注釋在使用時要去除
采用在主機安裝FATE的安裝模式
官方文檔中的命令都是用sh運行,因為本機的環境不同,所以采用bash
wget https://webank-ai-1251170195.cos.ap-guangzhou.myqcloud.com/standalone_fate_master_1.6.0.tar.gz tar -xzvf standalone_fate_master_1.6.0.tar.gz cd standalone_fate_master_1.6.0 source bin/init_env.sh bash init.sh init
1
2
3
4
5
6
7
8
問題:service.sh: [[ not found 解決:修改init.sh文件中的sh命令為bash
1
2
3
測試:
cd standalone_fate_master_1.6.0 source bin/init_env.sh bash ./python/federatedml/test/run_test.sh
1
2
3
4
會輸出一系列的測試輸出,最終:
toy測試
python ./examples/toy_example/run_toy_example.py 10000 10000 0
1
運行起來之后可以看到:
控制臺(IP:8080):
安裝FATE-Client和FATE-Test
為方便使用FATE,我們提供了便捷的交互工具FATE-Client以及測試工具FATE-Test.
請在環境內使用以下指令安裝:
python -m pip install fate-client python -m pip install fate-test
1
2
二、切分數據集
數據集:威斯康星州臨床科學中心開源的乳腺癌腫瘤數據集
from sklearn.datasets import load_breast_cancer
為了模擬橫向聯邦建模的場景,我們首先在本地將乳腺癌數據集切分為特征相同的橫向聯邦形式,當前的breast數據集有569條樣本,我們將前面的469條作為訓練樣本,后面的100條作為評估測試樣本。
從469條訓練樣本中,選取前200條作為公司A的本地數據,保存為breast_1_train.csv,將剩余的269條數據作為公司B的本地數據,保存為breast_2_train.csv。
測試數據集可以不需要切分,兩個參與方使用相同的一份測試數據即可,文件命名為breast_eval.csv。
splitDataset.py
from sklearn.datasets import load_breast_cancer import pandas as pd breast_dataset = load_breast_cancer() breast = pd.DataFrame(breast_dataset.data, columns=breast_dataset.feature_names) breast = (breast-breast.mean())/(breast.std()) col_names = breast.columns.values.tolist() columns = {} for idx, n in enumerate(col_names): columns[n] = "x%d"%idx breast = breast.rename(columns=columns) breast['y'] = breast_dataset.target breast['idx'] = range(breast.shape[0]) idx = breast['idx'] breast.drop(labels=['idx'], axis=1, inplace = True) breast.insert(0, 'idx', idx) breast = breast.sample(frac=1) train = breast.iloc[:469] eval = breast.iloc[469:] breast_1_train = train.iloc[:200] breast_1_train.to_csv('breast_1_train.csv', index=False, header=True) breast_2_train = train.iloc[200:] breast_2_train.to_csv('breast_2_train.csv', index=False, header=True) eval.to_csv('breast_eval.csv', index=False, header=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
注意:官方地址中的csv文件是有問題的,要運行這個切割數據集自己生成新的數據集文件
三、利用FATE構建橫向聯邦學習Pipeline
用FATE構建橫向聯邦學習Pipeline,涉及到三個方面的工作:
數據轉換輸入
將數據文件(csv、txt)等轉換成為FATE獨有的基礎數據結構DTable,從而方便進一步的操作
模型訓練
FATE以模型訓練構建流水線pipeline
模型評估:(可選)
評估模型性能的手段
如果只使用框架自帶的模型,那么其實我們需要修改的就是配置文件即可
3.1 數據轉換輸入
新建一個項目目錄chapter05(我這里創建的叫chapter05因為對應書第五章內容,可自行修改)
將數據集放到該目錄下的data目錄中:
完成數據轉換,需要一個配置文件和一個啟動程序:
配置文件
upload_data.json文件編寫配置,內容為:
{ "file": "data/breast_1_train.csv", "head": 1, "partition": 16, "work_mode": 0, "table_name": "homo_breast_1_train", "namespace": "homo_host_breast_train" }
1
2
3
4
5
6
7
8
字段說明:
file: 數據文件路徑,相對于當前所在路徑
head: 指定數據文件是否包含表頭
partition: 指定用于存儲數據的分區數
work_mode: 指定工作模式,0代表單機版,1代表集群版
table_name:轉換為DTable格式的表名
namespace: DTable格式的表名對應的命名空間
backend: 指定后端,0代表EGGROLL, 1代表SPARK加RabbitMQ, 2代表SPARK加Pulsar (暫時未用到)
fate-flow上傳數據
使用fate-flow上傳數據。從FATE-1.5開始,推薦使用 FATE-Flow Client Command Line 執行FATE-Flow任務。
提示:
{ "retcode": 100, "retmsg": "Fate flow CLI has not been initialized yet or configured incorrectly. Please initialize it before using CLI at the first time. And make sure the address of fate flow server is configured correctly. The configuration file path is: /ai/xwj/federate_learning/fate_dir/standalone_fate_master_1.6.0/venv/lib/python3.6/site-packages/flow_client/settings.yaml." }
1
2
3
4
解決:先初始化flow
使用flow首先要初始化一下:
flow init文檔
Fate Flow 命令行初始化命令。用戶可選擇提供fate服務器配置文件路徑或指定fate服務器ip地址及端口進行初始化。注意:若用戶同時使用上述兩種方式進行初始化,CLI將優先讀取配置文件內容,而用戶所配置的服務器ip地址及端口信息將被忽略。
因為之前init命令直接已經啟動了flow,所以直接初始化即可
flow init --ip 127.0.0.1 --port 9380
1
{ "retcode": 0, "retmsg": "Fate Flow CLI has been initialized successfully." }
1
2
3
4
因為之前上傳命令會自動將原始的本地文件轉為DTable格式
flow data upload -c upload_data.json
1
注意,我使用的是新版本,新版本支持命令行直接使用
如果提示沒有flow命令,那么可能沒有使用提供的conda環境,解決如下:
source bin/init_env.sh
1
{ "data": { "board_url": "http://127.0.0.1:8080/index.html#/dashboard?job_id=202108151639113656812&role=local&party_id=0", "job_dsl_path": "/home/jiangbo/FATE/standalone_fate_master_1.6.0/jobs/202108151639113656812/job_dsl.json", "job_id": "202108151639113656812", "job_runtime_conf_on_party_path": "/home/jiangbo/FATE/standalone_fate_master_1.6.0/jobs/202108151639113656812/local/job_runtime_on_party_conf.json", "job_runtime_conf_path": "/home/jiangbo/FATE/standalone_fate_master_1.6.0/jobs/202108151639113656812/job_runtime_conf.json", "logs_directory": "/home/jiangbo/FATE/standalone_fate_master_1.6.0/logs/202108151639113656812", "model_info": { "model_id": "local-0#model", "model_version": "202108151639113656812" }, "namespace": "homo_host_breast_train", "pipeline_dsl_path": "/home/jiangbo/FATE/standalone_fate_master_1.6.0/jobs/202108151639113656812/pipeline_dsl.json", "table_name": "homo_breast_1_train", "train_runtime_conf_path": "/home/jiangbo/FATE/standalone_fate_master_1.6.0/jobs/202108151639113656812/train_runtime_conf.json" }, "jobId": "202108151639113656812", "retcode": 0, "retmsg": "success" }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
訪問board_url可以在瀏覽器中看到對應的詳情:
對于breast_2_train.csv以及測試集合同樣的過程:
測試集上傳到兩個參與方,并各自轉換為DTable格式
{ "file": "data/breast_2_train.csv", "head": 1, "partition": 16, "work_mode": 0, "table_name": "homo_breast_2_train", "namespace": "homo_guest_breast_train" } // host { "file": "data/breast_eval.csv", "head": 1, "partition": 16, "work_mode": 0, "table_name": "homo_breast_1_eval", "namespace": "homo_host_breast_eval" } // guest { "file": "data/breast_eval.csv", "head": 1, "partition": 16, "work_mode": 0, "table_name": "homo_breast_2_eval", "namespace": "homo_guest_breast_eval" }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
3.2 模型訓練
借助FATE,我們可以使用組件的方式來構建聯邦學習,而不需要用戶從新開始編碼,FATE構建聯邦學習Pipeline是通過自定義dsl和conf兩個配置文件來實現:
DSL 配置和運行配置 V1
dsl文件:用來描述任務模塊,將任務模塊以有向無環圖(DAG)的形式組合在一起。
conf文件:設置各個組件的參數,比如輸入模塊的數據表名;算法模塊的學習率、batch大小、迭代次數等。
我們本實驗使用的是模型:邏輯回歸
進入examples/dsl/v1/homo_logistic_regression文件夾中:
使用test_homolr_train_job_dsl.json、test_homolr_train_job_conf.json兩個文件來輔助構建橫向聯邦學習模型
3.2.1 DSL配置文件
為了讓任務模型的構建更加靈活,目前 FATE 使用了一套自定的領域特定語言 (DSL) 來描述任務。在 DSL 中,各種任務模塊(例如數據讀寫 data_io,特征工程 feature-engineering, 回歸 regression,分類 classification)可以通向一個有向無環圖 (DAG) 組織起來。通過各種方式,用戶可以根據自身的需要,靈活地組合各種算法模塊。
DSL 的配置文件采用 json 格式,實際上,整個配置文件就是一個 json 對象 (dict)。在這個 dict 的第一級是 “components”,用來表示這個任務將會使用到的各個模塊。用戶需要使用模塊名加數字 _num 作為對應模塊的 key,例如 dataio_0,并且數字應從 0 開始計數。
具體的參數見官方文檔連接(上面)
test_homolr_train_job_dsl.json:
定義了四個模塊已經構成了基本的聯邦學習流水線(feature_scale_0為1.6.0新增),可直接使用(復制一份)
{ "components" : { // 數據IO組件,用于將本地數據轉為DTable "dataio_0": { "module": "DataIO", "input": { "data": { "data": [ "args.train_data" ] } }, "output": { "data": ["train"], "model": ["dataio"] } }, // 特征工程模塊 "feature_scale_0": { "module": "FeatureScale", "input": { "data": { "data": [ "dataio_0.train" ] } }, "output": { "data": ["train"], "model": ["feature_scale"] } }, // 橫向邏輯回歸組件 "homo_lr_0": { "module": "HomoLR", "input": { "data": { "train_data": [ "feature_scale_0.train" ] } }, "output": { "data": ["train"], "model": ["homolr"] } }, // 模型評估組件,如果未提供測試數據集則自動使用訓練集 "evaluation_0": { "module": "Evaluation", "input": { "data": { "data": [ "homo_lr_0.train" ] } } } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
這里的args.train_data是根據下面的運行配置conf來的
其次配置文件之間的指定關系如下:
3.2.2 運行配置 Submit Runtime Conf
每個模塊都有不同的參數需要配置,不同的 party 對于同一個模塊的參數也可能有所區別。為了簡化這種情況,對于每一個模塊,FATE 會將所有 party 的不同參數保存到同一個運行配置文件(Submit Runtime Conf)中,并且所有的 party 都將共用這個配置文件。
除了 DSL 的配置文件之外,用戶還需要準備一份運行配置(Submit Runtime Conf)用于設置各個組件的參數。
test_homolr_train_job_conf.json 修改如下:
{ // 創始人 "initiator": { "role": "guest", "party_id": 10000 }, "job_parameters": { "work_mode": 0 // 0代表單機版,1代表集群版 }, // 所有參與此任務的角色 // 每一個元素代表一種角色以及承擔這個角色的party_id,是一個列表表示同一角色可能有多個實體ID "role": { "guest": [ 10000 ], "host": [ 10000 ], // 仲裁者 "arbiter": [ 10000 ] }, // 對于權限角色的進一步參數配置 "role_parameters": { "guest": { "args": { "data": { "train_data": [ { "name": "homo_breast_2_train", // 修改DTable的表名 "namespace": "homo_guest_breast_train" // 修改命名空間 } ] } }, "dataio_0": { "label_name": ["y"] // 添加標簽對應的列屬性名稱 } }, "host": { "args": { "data": { "train_data": [ { "name": "homo_breast_1_train", // 同理修改 "namespace": "homo_host_breast_train" } ] } }, "dataio_0": { "label_name": ["y"] // 添加標簽對應的列屬性名稱 }, "evaluation_0": { "need_run": [ false ] } } }, // 設置模型訓練的超參數信息 "algorithm_parameters": { "dataio_0": { "with_label": true, "label_name": "y", "label_type": "int", "output_format": "dense" }, "homo_lr_0": { "penalty": "L2", "optimizer": "sgd", "tol": 1e-05, "alpha": 0.01, "max_iter": 10, "early_stop": "diff", "batch_size": 500, "learning_rate": 0.15, "decay": 1, "decay_sqrt": true, "init_param": { "init_method": "zeros" }, "encrypt_param": { "method": null }, "cv_param": { "n_splits": 4, "shuffle": true, "random_seed": 33, "need_cv": false } } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
關于角色,解釋如下:
arbiter是用來輔助多方完成聯合建模的,它的主要作用是聚合梯度或者模型。比如縱向lr里面,各方將自己一半的梯度發送給arbiter,然后arbiter再聯合優化等等。
guest代表數據應用方。
host是數據提供方。
local是指本地任務, 該角色僅用于upload和download階段中。
3.2.3 提交參數,訓練模型
Job submit
介紹: 提交執行pipeline任務。
參數:
執行:
1
flow job submit -c test_homolr_train_job_conf.json -d test_homolr_train_job_dsl.json
1
注意:需要全部為勾號才說明運行成功
可以看到運行的結果:
3.3 評估模型
為了評估模型的效果,我們重新修改配置以檢查效果:
在上傳數據時,我們已經將兩個評估模型的數據上傳,并且轉換為DTable格式
現在我們修改dsl配置文件:
{ "components" : { "dataio_0": { "module": "DataIO", "input": { "data": { "data": [ "args.train_data" ] } }, "output": { "data": ["train"], "model": ["dataio"] } }, "dataio_1": { "module": "DataIO", "input": { "data": { "data": [ "args.eval_data" ] }, "model": ["dataio_0.dataio"] }, "output": { "data": ["eval_data"] } }, "feature_scale_0": { "module": "FeatureScale", "input": { "data": { "data": [ "dataio_0.train" ] } }, "output": { "data": ["train"], "model": ["feature_scale"] } }, "feature_scale_1": { "module": "FeatureScale", "input": { "data": { "data": [ "dataio_1.eval_data" ] } }, "output": { "data": ["eval_data"], "model": ["feature_scale"] } }, "homo_lr_0": { "module": "HomoLR", "input": { "data": { "train_data": [ // 注意這里是指定訓練數據 "feature_scale_0.train" ] } }, "output": { "data": [ "train" ], "model": ["homolr"] } }, "homo_lr_1": { "module": "HomoLR", "input": { "data": { "eval_data": [ // 注意:這里是指定評估數據 "feature_scale_1.eval_data" ] }, "model": [ // 這里指定好模型 "homo_lr_0.homolr" ] }, "output": { "data": [ "eval_data" ], "model": ["homolr"] } }, "evaluation_0": { "module": "Evaluation", "input": { "data": { "data": [ "homo_lr_0.train" ] } } }, "evaluation_1": { "module": "Evaluation", "input": { "data": { "data": [ "homo_lr_1.eval_data" // 指定評估數據集 ] } } } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
修改conf文件:
{ ... "role_parameters": { "guest": { "args": { "data": { "train_data": [ { "name": "homo_breast_2_train", "namespace": "homo_guest_breast_train" } ], "eval_data": [ // 添加測試集合 { "name": "homo_breast_2_eval", "namespace": "homo_guest_breast_eval" } ] } }, "dataio_0": { "label_name": ["y"] } }, "host": { "args": { "data": { "train_data": [ { "name": "homo_breast_1_train", "namespace": "homo_host_breast_train" } ], "eval_data": [ // 添加測試集合 { "name": "homo_breast_1_eval", "namespace": "homo_host_breast_eval" } ] } }, ... } }, .... }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
重新提交任務,查看結果:
flow job submit -c test_homolr_train_job_conf.json -d test_homolr_train_job_dsl.json
1
DAG圖:
3.4 多參與方環境配置
上面的方案中有兩個參與角色:
guest代表數據應用方。
host是數據提供方。
下面考慮更多的客戶端參與,修改conf文件中的role添加更多的參與方:
(這里為了方便起見,就不再對數據集根據不同的host進行進一步的劃分,測試集也是如此)
{ "initiator": { "role": "guest", "party_id": 10000 }, "job_parameters": { "work_mode": 0 }, "role": { "guest": [ 10000 ], "host": [ 10000, 10001, 10002 // 新建兩個Host ], "arbiter": [ 10000 ] }, "role_parameters": { "guest": { ... }, "host": { "args": { "data": { // 訓練數據、測試數據的list都要與上面的host的list大小一樣,一一對應 "train_data": [ { "name": "homo_breast_1_train", "namespace": "homo_host_breast_train" }, { "name": "homo_breast_1_train", "namespace": "homo_host_breast_train" }, { "name": "homo_breast_1_train", "namespace": "homo_host_breast_train" } ], "eval_data": [ { "name": "homo_breast_1_eval", "namespace": "homo_host_breast_eval" }, { "name": "homo_breast_1_eval", "namespace": "homo_host_breast_eval" }, { "name": "homo_breast_1_eval", "namespace": "homo_host_breast_eval" } ] } }, // dataio_0 標簽指定、測試集是否需要跑也是一樣,大小一致、一一對應 "dataio_0": { "label_name": ["y", "y", "y"] }, "evaluation_0": { "need_run": [ false, false, false ] } } }, ... }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
運行后效果如圖:
四、Tips
4.1. 重新啟動fate-flow和fateboard
在根目錄下
bash ./python/fate_flow/service.sh restart bash ./fateboard/service.sh restart
1
2
4.2. ‘NoneType’ object has no attribute ‘count’
解決:檢查conf中的配置name、namespace與upload的配置是否一一匹配
4.3. list index out of range
運行后效果如圖:
四、Tips
4.1. 重新啟動fate-flow和fateboard
在根目錄下
bash ./python/fate_flow/service.sh restart bash ./fateboard/service.sh restart
1
2
4.2. ‘NoneType’ object has no attribute ‘count’
解決:檢查conf中的配置name、namespace與upload的配置是否一一匹配
4.3. list index out of range
檢查數據集分割(樣本大?。┦欠裉幚砗?/p>
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。