FATE文档阅读笔记--NN模块教程

part1:Homo-NN 快速入门:二元分类任务


这是旁白翻译:

本教程可帮助您快速上手使用 Homo-NN。默认情况下,您可以按照与其他 FATE 算法组件相同的流程使用 Homo-NN 组件:使用 FATE 自带的 reader 和 transformer 接口输入表数据并转换数据格式,然后将数据输入算法组件。然后 NN 组件将使用您定义的模型、优化器和损失函数进行训练和模型聚合。

在FATE-1.10中,pipeline中的Homo-NN已经加入了对pytorch的支持,你可以效仿pytorch Sequential的使用方法,使用Pytorch内置的layers定义Sequential模型并提交模型,同时可以使用Pytorch自带的loss函数和optimizer。

以下是一个基础二分类任务Homo-NN任务,有两个客户端,party id分别为10000和9999,10000指定为服务端聚合模型。

关于示例代码的疑问:

##上传数据的代码##

from pipeline.backend.pipeline import PipeLine  # pipeline Class

# [9999(guest), 10000(host)] as client
# [10000(arbiter)] as server

guest = 9999
host = 10000
arbiter = 10000
pipeline_upload = PipeLine().set_initiator(role='guest', party_id=guest).set_roles(guest=guest, host=host, arbiter=arbiter)

partition = 4

# upload a dataset
path_to_fate_project = '../../../../'
guest_data = {"name": "breast_homo_guest", "namespace": "experiment"}
host_data = {"name": "breast_homo_host", "namespace": "experiment"}
pipeline_upload.add_upload_data(file="examples/data/breast_homo_guest.csv", # file in the example/data
                                table_name=guest_data["name"],             # table name
                                namespace=guest_data["namespace"],         # namespace
                                head=1, partition=partition)               # data info
pipeline_upload.add_upload_data(file="examples/data/breast_homo_host.csv", # file in the example/data
                                table_name=host_data["name"],             # table name
                                namespace=host_data["namespace"],         # namespace
                                head=1, partition=partition)               # data info


pipeline_upload.upload(drop=1)

问题 1:guest和host为什么要分开?9999和10000是通信端口号吗?

答:解释 guest 和 host 的概念:

在联邦学习中,guest 和 host 是两种不同的参与方角色。尽管它们都是客户端,但它们在数据的持有和使用上有不同的职责和数据集。

  • Guest:通常是发起方,拥有部分数据并发起联邦学习任务。
  • Host:通常是参与方,拥有另外一部分数据,参与到联邦学习任务中来。

为什么要分开:

这种分开使得在训练模型时,每个参与方都能持有不同的数据集,但仍能通过联邦学习技术共同训练一个全局模型。这符合联邦学习的核心思想:数据不动,模型动。也就是说,数据保持在本地,只有模型参数和中间计算结果在各参与方之间交换。

关于9999和10000:

这些数字并不是通信的端口号,而是参与方的唯一标识符(party ID)。在FATE中,每个参与方都有一个唯一的ID,用来标识不同的参与方。例如:

  • guest = 9999 表示 guest 参与方的ID是9999。
  • host = 10000 表示 host 参与方的ID是10000。
  • arbiter = 10000 表示 arbiter 参与方的ID是10000。

问题 2:为什么要有分区?分区是什么意思?

解释分区:

分区(partition)在这里是指对数据集进行分割以提高数据处理和训练的效率。在处理大规模数据时,将数据集分成多个小块(分区)可以使得数据处理和并行计算更加高效。

与横向联邦学习的关系:

在横向联邦学习中,参与方拥有的数据集通常是具有相同特征(即相同的列),但是不同的样本(即不同的行)。分区在这种情况下主要用于:

  1. 数据分片:将每个参与方的数据集分割成更小的部分,以便更高效地处理和传输。
  2. 并行计算:分区有助于在多个计算节点上并行处理数据,从而提高计算效率。

分区与参与方分组的区别:

分区并不是将参与方分组,而是将每个参与方的数据集分割成多个部分。例如,如果你有一个很大的CSV文件,它可能会被分成4个小的部分来处理。在联邦学习中,参与方分组通常指的是将参与方分成若干组以执行不同的任务,而分区只是针对单个参与方的数据处理策略。

问题3:guest 和 host 的角色及数量还有自定义party_id

guest 和 host 的角色:

  • Guest:发起联邦学习任务的客户端,通常只有一个。
  • Host:参与联邦学习任务的客户端,可以有多个。

自定义 party_id

party_id 的设置:

  • 你可以自由设置参与方的 party_id,只要确保每个 party_id 是唯一的。
  • 例如,你可以设置一个 guest 的 party_id 为 123,并且设置两个 host 的 party_id 分别为 246 和 135。

##上传数据示例流程##: 

假设你有两个数据文件breast_homo_guest.csvbreast_homo_host.csv,它们分别包含guest和host的训练数据。这些数据文件的路径是examples/data/,并且你希望将这些数据上传到联邦学习平台上进行后续的训练。

  1. 导入必要的库:
    from pipeline.backend.pipeline import PipeLine
  2. 定义参与方ID:

    guest = 9999
    host = 10000
    arbiter = 10000
  3. 创建并配置流水线:

    pipeline_upload = PipeLine().set_initiator(role='guest', party_id=guest).set_roles(guest=guest, host=host, arbiter=arbiter)
    #.set_initiator()定义发起任务者和对应id
    #.set_roles(guest=guest, host=host, arbiter=arbiter)定义各个角色
  4. 设置数据分区:

    partition = 4
    
  5. 定义数据表信息:

    guest_data = {"name": "breast_homo_guest", "namespace": "experiment"}
    host_data = {"name": "breast_homo_host", "namespace": "experiment"}
  6. 添加数据上传任务:

    pipeline_upload.add_upload_data(file="examples/data/breast_homo_guest.csv", table_name=guest_data["name"], namespace=guest_data["namespace"], head=1, partition=partition)
    pipeline_upload.add_upload_data(file="examples/data/breast_homo_host.csv", table_name=host_data["name"], namespace=host_data["namespace"], head=1, partition=partition)
  7. 执行数据上传任务:

    pipeline_upload.upload(drop=1)

 这段代码成功执行后,breast_homo_guest.csvbreast_homo_host.csv中的数据将被上传到联邦学习平台上,准备进行后续的训练和分析。

关于执行训练的代码:

##编写 Pipeline 脚本并执行的代码##

# torch
import torch as t
from torch import nn

# pipeline
from pipeline.component.homo_nn import HomoNN, TrainerParam  # HomoNN Component, TrainerParam for setting trainer parameter
from pipeline.backend.pipeline import PipeLine  # pipeline class
from pipeline.component import Reader, DataTransform, Evaluation # Data I/O and Evaluation
from pipeline.interface import Data  # Data Interaces for defining data flow

#我们看看它的参数
print(HomoNN.__doc__)

'''

    Parameters
    ----------
    name, name of this component
    trainer, trainer param
    dataset, dataset param
    torch_seed, global random seed
    loss, loss function from fate_torch
    optimizer, optimizer from fate_torch
    model, a fate torch sequential defining the model structure

'''
#务必执行这一行代码,因为该函数可以修改torch的一些类,以便您在脚本中定义的torch层、顺序、优化器和损失函数可以被管道解析和提交
from pipeline import fate_torch_hook
t = fate_torch_hook(t)

#Pipeline
#创建一个管道对象 pipeline,并设置角色(发起者、参与者、仲裁者)及其对应的 ID
# create a pipeline to submitting the job
guest = 9999
host = 10000
arbiter = 10000
pipeline = PipeLine().set_initiator(role='guest', party_id=guest).set_roles(guest=guest, host=host, arbiter=arbiter)

# read uploaded dataset
#定义两个数据集,分别属于 guest 和 host。
#使用 Reader 组件读取这些数据集。
train_data_0 = {"name": "breast_homo_guest", "namespace": "experiment"}
train_data_1 = {"name": "breast_homo_host", "namespace": "experiment"}
reader_0 = Reader(name="reader_0")
reader_0.get_party_instance(role='guest', party_id=guest).component_param(table=train_data_0)
reader_0.get_party_instance(role='host', party_id=host).component_param(table=train_data_1)


# The transform component converts the uploaded data to the DATE standard format
#使用 DataTransform 组件将上传的数据转换为 DATE 标准格式。
data_transform_0 = DataTransform(name='data_transform_0')
data_transform_0.get_party_instance(
    role='guest', party_id=guest).component_param(
    with_label=True, output_format="dense")
data_transform_0.get_party_instance(
    role='host', party_id=host).component_param(
    with_label=True, output_format="dense")

"""
Define Pytorch model/ optimizer and loss
创建一个简单的神经网络模型,包含一个线性层和一个 sigmoid 激活函数。
定义损失函数为二元交叉熵损失 BCELoss。
使用 Adam 优化器。
"""
model = nn.Sequential(
    nn.Linear(30, 1),
    nn.Sigmoid()
)
loss = nn.BCELoss()
optimizer = t.optim.Adam(model.parameters(), lr=0.01)


"""
Create Homo-NN Component
创建 HomoNN 组件,并设置模型、损失函数、优化器和训练参数。
使用 TrainerParam 传递参数给 fedavg_trainer,包括训练轮数(epochs)、批次大小(batch_size)和验证频率(validation_freqs)。
"""
nn_component = HomoNN(name='nn_0',
                      model=model, # set model
                      loss=loss, # set loss
                      optimizer=optimizer, # set optimizer
                      # Here we use fedavg trainer
                      # TrainerParam passes parameters to fedavg_trainer, see below for details about Trainer
                      trainer=TrainerParam(trainer_name='fedavg_trainer', epochs=3, batch_size=128, validation_freqs=1),
                      torch_seed=100 # random seed
                      )

# define work flow
#将各个组件添加到管道中,定义数据的流向。
#编译并执行管道。
pipeline.add_component(reader_0)
pipeline.add_component(data_transform_0, data=Data(data=reader_0.output.data))
pipeline.add_component(nn_component, data=Data(train_data=data_transform_0.output.data))
pipeline.add_component(Evaluation(name='eval_0'), data=Data(data=nn_component.output.data))

pipeline.compile()
pipeline.fit()

问题1:关于管道的定义

在 FATE 中,管道(Pipeline)用于定义和管理联邦学习的整个工作流。每个工作流都需要一个独立的管道对象来组织和调度各个组件。通常情况下,在一个脚本中,一个管道对象只需要定义一次,并用于管理整个工作流。

guest = 9999 host = 10000 arbiter = 10000 pipeline = PipeLine().set_initiator(role='guest', party_id=guest).set_roles(guest=guest, host=host, arbiter=arbiter)
  • set_initiator(role, party_id):设置发起方角色和 ID。
  • set_roles(guest=guest, host=host, arbiter=arbiter):设置联邦学习中各个角色及其对应的 ID。

问题2:Reader 组件

Reader 组件用于读取数据。reader_0Reader 组件的一个实例,用于读取上传的数据集。

reader_0 = Reader(name="reader_0") 
reader_0.get_party_instance(role='guest', party_id=guest).component_param(table=train_data_0) 
reader_0.get_party_instance(role='host', party_id=host).component_param(table=train_data_1)
  • Reader(name="reader_0"):创建一个名为 reader_0Reader 组件实例。
  • get_party_instance(role, party_id):获取指定角色和 ID 的实例。
  • component_param(table=train_data):设置数据表的参数,其中 table 是一个字典,包含数据表的名称和命名空间。

问题3:数据转换组件

DataTransform 组件用于转换数据格式,例如将数据转换为稠密格式(dense format)。

data_transform_0 = DataTransform(name='data_transform_0') 
data_transform_0.get_party_instance(role='guest', party_id=guest).component_param(with_label=True, output_format="dense") 
data_transform_0.get_party_instance(role='host', party_id=host).component_param(with_label=True, output_format="dense")
  • DataTransform(name='data_transform_0'):创建一个名为 data_transform_0DataTransform 组件实例。
  • get_party_instance(role, party_id):获取指定角色和 ID 的实例。
  • component_param(with_label=True, output_format="dense"):设置数据转换的参数,其中 with_label=True 表示数据包含标签,output_format="dense" 表示输出数据格式为稠密格式。

问题4:工作流定义和编译

在定义工作流和编译阶段,使用 pipeline.add_component() 方法将各个组件添加到管道中,并使用 pipeline.compile() 编译管道,最后使用 pipeline.fit() 执行管道。

pipeline.add_component(reader_0)
pipeline.add_component(data_transform_0, data=Data(data=reader_0.output.data))
pipeline.add_component(nn_component, data=Data(train_data=data_transform_0.output.data))
pipeline.add_component(Evaluation(name='eval_0'), data=Data(data=nn_component.output.data))
pipeline.compile()
pipeline.fit()
  • pipeline.add_component(component, data=Data(data=previous_component.output.data)):将组件添加到管道中,并定义数据流向。其中 data 参数用于指定数据来源。

    • reader_0:数据读取组件。
    • data_transform_0:数据转换组件,数据来源于 reader_0 的输出。
    • nn_component:神经网络组件,数据来源于 data_transform_0 的输出。
    • Evaluation(name='eval_0'):评估组件,数据来源于 nn_component 的输出。
  • pipeline.compile():编译管道,生成工作流图,准备执行。

  • pipeline.fit():执行管道,开始训练和评估模型。

##上传代码示例##:

import torch as t
from torch import nn
from pipeline.component.homo_nn import HomoNN, TrainerParam
from pipeline.backend.pipeline import PipeLine
from pipeline.component import Reader, DataTransform, Evaluation
from pipeline.interface import Data
from pipeline import fate_torch_hook

t = fate_torch_hook(t)

guest = 9999
host = 10000
arbiter = 10000
pipeline = PipeLine().set_initiator(role='guest', party_id=guest).set_roles(guest=guest, host=host, arbiter=arbiter)

train_data_0 = {"name": "breast_homo_guest", "namespace": "experiment"}
train_data_1 = {"name": "breast_homo_host", "namespace": "experiment"}
reader_0 = Reader(name="reader_0")
reader_0.get_party_instance(role='guest', party_id=guest).component_param(table=train_data_0)
reader_0.get_party_instance(role='host', party_id=host).component_param(table=train_data_1)

data_transform_0 = DataTransform(name='data_transform_0')
data_transform_0.get_party_instance(role='guest', party_id=guest).component_param(with_label=True, output_format="dense")
data_transform_0.get_party_instance(role='host', party_id=host).component_param(with_label=True, output_format="dense")

model = nn.Sequential(
    nn.Linear(30, 1),
    nn.Sigmoid()
)
loss = nn.BCELoss()
optimizer = t.optim.Adam(model.parameters(), lr=0.01)

nn_component = HomoNN(name='nn_0',
                      model=model,
                      loss=loss,
                      optimizer=optimizer,
                      trainer=TrainerParam(trainer_name='fedavg_trainer', epochs=3, batch_size=128, validation_freqs=1),
                      torch_seed=100
                      )

pipeline.add_component(reader_0)
pipeline.add_component(data_transform_0, data=Data(data=reader_0.output.data))
pipeline.add_component(nn_component, data=Data(train_data=data_transform_0.output.data))
pipeline.add_component(Evaluation(name='eval_0'), data=Data(data=nn_component.output.data))

pipeline.compile()
pipeline.fit()

总结一下流程就是,

完整的工作流程如下:

  1. 上传数据。
  2. 引入必要的包。
  3. 指定参与方和服务器。
  4. 定义管道。
  5. 使用 Reader 组件读取数据集。
  6. 使用 DataTransform 组件转换数据格式。
  7. 定义 CNN 模型。
  8. 使用 HomoNN 组件进行横向联邦学习。
  9. 将所有组件添加到流水线中。
  10. 编译并执行流水线。

关于读取结果的代码

##获取结果的代码##

#获取组件的输出--预测分数
pipeline.get_component('nn_0').get_output_data()
#获取组建的输出--总体输出
pipeline.get_component('nn_0').get_summary()

这个好理解,没啥问题

关于TrainerParam 训练器参数和训练器

在这个版本中,Homo-NN的训练逻辑和联邦聚合逻辑都实现在 Trainer 类中。fedavg_trainer 是 FATE Homo-NN 的默认 Trainer,实现了标准的 fedavg 算法。而 TrainerParam 的作用是:

  • 使用 trainer_name='{模块名称}' 指定要使用的训练器。训练器位于 federatedml.nn.homo.trainer 目录中,因此您可以自定义自己的训练器。有关自定义训练器的教程将有专门的章节
  • 其余参数将传递给训练器的 __init__() 接口

我们可以在FATE中查看fedavg_trainer的参数,这些可用的参数都可以填在TrainerParam中。

from federatedml.nn.homo.trainer.fedavg_trainer import FedAVGTrainer
'''
查看 FedAVGTrainer 的文档,了解可用的参数。提交任务时,这些参数可以通过 TrainerParam 传递
'''

print(FedAVGTrainer.__doc__)

'''
 Parameters
    ----------
    epochs: int >0, epochs to train
    batch_size: int, -1 means full batch
    secure_aggregate: bool, default is True, whether to use secure aggregation. if enabled, will add random number
                            mask to local models. These random number masks will eventually cancel out to get 0.
    weighted_aggregation: bool, whether add weight to each local model when doing aggregation.
                         if True, According to origin paper, weight of a client is: n_local / n_global, where n_local
                         is the sample number locally and n_global is the sample number of all clients.
                         if False, simply averaging these models.

    early_stop: None, 'diff' or 'abs'. if None, disable early stop; if 'diff', use the loss difference between
                two epochs as early stop condition, if differences < tol, stop training ; if 'abs', if loss < tol,
                stop training
    tol: float, tol value for early stop

    aggregate_every_n_epoch: None or int. if None, aggregate model on the end of every epoch, if int, aggregate
                             every n epochs.
    cuda: bool, use cuda or not
    pin_memory: bool, for pytorch DataLoader
    shuffle: bool, for pytorch DataLoader
    data_loader_worker: int, for pytorch DataLoader, number of workers when loading data
    validation_freqs: None or int. if int, validate your model and send validate results to fate-board every n epoch.
                      if is binary classification task, will use metrics 'auc', 'ks', 'gain', 'lift', 'precision'
                      if is multi classification task, will use metrics 'precision', 'recall', 'accuracy'
                      if is regression task, will use metrics 'mse', 'mae', 'rmse', 'explained_variance', 'r2_score'
    checkpoint_save_freqs: save model every n epoch, if None, will not save checkpoint.
    task_type: str, 'auto', 'binary', 'multi', 'regression'
               this option decides the return format of this trainer, and the evaluation type when running validation.
               if auto, will automatically infer your task type from labels and predict results.
    
'''

至此,总结一下全流程。

1、选择合适的数据集,并进行处理上传

2、将上传的数据集以及客户端服务端还有pipeline定义,然后进行训练集划分和验证集的划分

3、定义reader实例进行读取数据

4、定义DataTransform实例进行数据格式的转换

5、定义NN模型,超参数

6、应用HomoNN

7、然后将所有组件上传pipeline

8、编译并运行

9、查看结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值