Renset Classification on CIFAR 10¶
In this example, we show you how to use torchvision model to make a federated classification task
Dataset: CIFAR 10¶
You can download the CIFAR-10 dataset through this link:
The origin CIFAR-10 is from:
For the convinence of demonstrate, our clients will use same dataset
Local Test¶
Firstly we locally test our model and dataset. If it works, we can submit a federated task.
In [7]:
Copied!
from pipeline.component.nn import save_to_fate
from pipeline.component.nn import save_to_fate
In [8]:
Copied!
%%save_to_fate model resnet.py
# model
import torch as t
from torch import nn
from torchvision.models import resnet18, ResNet18_Weights
class Resnet(nn.Module):
def __init__(self, ):
super(Resnet, self).__init__()
self.resnet = resnet18()
self.classifier = t.nn.Linear(1000, 10)
self.softmax = nn.Softmax(dim=1)
def forward(self, x):
if self.training:
return self.classifier(self.resnet(x))
else:
return self.softmax(self.classifier(self.resnet(x)))
%%save_to_fate model resnet.py
# model
import torch as t
from torch import nn
from torchvision.models import resnet18, ResNet18_Weights
class Resnet(nn.Module):
def __init__(self, ):
super(Resnet, self).__init__()
self.resnet = resnet18()
self.classifier = t.nn.Linear(1000, 10)
self.softmax = nn.Softmax(dim=1)
def forward(self, x):
if self.training:
return self.classifier(self.resnet(x))
else:
return self.softmax(self.classifier(self.resnet(x)))
In [9]:
Copied!
model = Resnet()
print(model)
model = Resnet()
print(model)
Resnet( (resnet): ResNet( (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False) (layer1): Sequential( (0): BasicBlock( (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (1): BasicBlock( (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (layer2): Sequential( (0): BasicBlock( (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (layer3): Sequential( (0): BasicBlock( (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (layer4): Sequential( (0): BasicBlock( (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (avgpool): AdaptiveAvgPool2d(output_size=(1, 1)) (fc): Linear(in_features=512, out_features=1000, bias=True) ) (classifier): Linear(in_features=1000, out_features=10, bias=True) (softmax): Softmax(dim=1) )
In [10]:
Copied!
# read dataset
from federatedml.nn.dataset.image import ImageDataset
ds = ImageDataset()
ds.load('../../../../examples/data/cifar10/train/')
# read dataset
from federatedml.nn.dataset.image import ImageDataset
ds = ImageDataset()
ds.load('../../../../examples/data/cifar10/train/')
In [11]:
Copied!
ds[0][0].shape
ds[0][0].shape
Out[11]:
torch.Size([3, 32, 32])
In [12]:
Copied!
# local test
import torch as t
from federatedml.nn.homo.trainer.fedavg_trainer import FedAVGTrainer
trainer = FedAVGTrainer(epochs=1, batch_size=1024, data_loader_worker=4)
trainer.set_model(model)
optimizer = t.optim.Adam(model.parameters(), lr=0.001)
loss = t.nn.CrossEntropyLoss()
trainer.local_mode() # set local mode
trainer.train(ds, None, optimizer, loss)
# local test
import torch as t
from federatedml.nn.homo.trainer.fedavg_trainer import FedAVGTrainer
trainer = FedAVGTrainer(epochs=1, batch_size=1024, data_loader_worker=4)
trainer.set_model(model)
optimizer = t.optim.Adam(model.parameters(), lr=0.001)
loss = t.nn.CrossEntropyLoss()
trainer.local_mode() # set local mode
trainer.train(ds, None, optimizer, loss)
Submit a federated task¶
In [18]:
Copied!
import torch as t
from torch import nn
from pipeline import fate_torch_hook
from pipeline.component import HomoNN
from pipeline.backend.pipeline import PipeLine
from pipeline.component import Reader, Evaluation, DataTransform
from pipeline.interface import Data, Model
fate_torch_hook(t)
import os
fate_project_path = os.path.abspath('../../../../')
guest = 10000
host = 9999
pipeline = PipeLine().set_initiator(role='guest', party_id=guest).set_roles(guest=guest, host=host,
arbiter=host)
data_0 = {"name": "cifar10", "namespace": "experiment"}
data_path = fate_project_path + '/examples/data/cifar10/train'
pipeline.bind_table(name=data_0['name'], namespace=data_0['namespace'], path=data_path)
pipeline.bind_table(name=data_0['name'], namespace=data_0['namespace'], path=data_path)
import torch as t
from torch import nn
from pipeline import fate_torch_hook
from pipeline.component import HomoNN
from pipeline.backend.pipeline import PipeLine
from pipeline.component import Reader, Evaluation, DataTransform
from pipeline.interface import Data, Model
fate_torch_hook(t)
import os
fate_project_path = os.path.abspath('../../../../')
guest = 10000
host = 9999
pipeline = PipeLine().set_initiator(role='guest', party_id=guest).set_roles(guest=guest, host=host,
arbiter=host)
data_0 = {"name": "cifar10", "namespace": "experiment"}
data_path = fate_project_path + '/examples/data/cifar10/train'
pipeline.bind_table(name=data_0['name'], namespace=data_0['namespace'], path=data_path)
pipeline.bind_table(name=data_0['name'], namespace=data_0['namespace'], path=data_path)
Out[18]:
{'namespace': 'experiment', 'table_name': 'cifar10'}
In [19]:
Copied!
reader_0 = Reader(name="reader_0")
reader_0.get_party_instance(role='guest', party_id=guest).component_param(table=data_0)
reader_0.get_party_instance(role='host', party_id=host).component_param(table=data_0)
reader_1 = Reader(name="reader_1")
reader_1.get_party_instance(role='guest', party_id=guest).component_param(table=data_0)
reader_1.get_party_instance(role='host', party_id=host).component_param(table=data_0)
reader_0 = Reader(name="reader_0")
reader_0.get_party_instance(role='guest', party_id=guest).component_param(table=data_0)
reader_0.get_party_instance(role='host', party_id=host).component_param(table=data_0)
reader_1 = Reader(name="reader_1")
reader_1.get_party_instance(role='guest', party_id=guest).component_param(table=data_0)
reader_1.get_party_instance(role='host', party_id=host).component_param(table=data_0)
In [20]:
Copied!
from pipeline.component.homo_nn import DatasetParam, TrainerParam
model = t.nn.Sequential(
t.nn.CustModel(module_name='resnet', class_name='Resnet')
)
nn_component = HomoNN(name='nn_0',
model=model,
loss=t.nn.CrossEntropyLoss(),
optimizer = t.optim.Adam(lr=0.001, weight_decay=0.001),
dataset=DatasetParam(dataset_name='image'), # 使用自定义的dataset
trainer=TrainerParam(trainer_name='fedavg_trainer', epochs=10, batch_size=1024, data_loader_worker=8),
torch_seed=100
)
from pipeline.component.homo_nn import DatasetParam, TrainerParam
model = t.nn.Sequential(
t.nn.CustModel(module_name='resnet', class_name='Resnet')
)
nn_component = HomoNN(name='nn_0',
model=model,
loss=t.nn.CrossEntropyLoss(),
optimizer = t.optim.Adam(lr=0.001, weight_decay=0.001),
dataset=DatasetParam(dataset_name='image'), # 使用自定义的dataset
trainer=TrainerParam(trainer_name='fedavg_trainer', epochs=10, batch_size=1024, data_loader_worker=8),
torch_seed=100
)
In [21]:
Copied!
pipeline.add_component(reader_0)
pipeline.add_component(reader_1)
pipeline.add_component(nn_component, data=Data(train_data=reader_0.output.data, validate_data=reader_1.output.data))
pipeline.add_component(Evaluation(name='eval_0', eval_type='multi'), data=Data(data=nn_component.output.data))
pipeline.add_component(reader_0)
pipeline.add_component(reader_1)
pipeline.add_component(nn_component, data=Data(train_data=reader_0.output.data, validate_data=reader_1.output.data))
pipeline.add_component(Evaluation(name='eval_0', eval_type='multi'), data=Data(data=nn_component.output.data))
Out[21]:
<pipeline.backend.pipeline.PipeLine at 0x7fbaf1e66b80>
In [23]:
Copied!
pipeline.compile()
pipeline.compile()
Out[23]:
<pipeline.backend.pipeline.PipeLine at 0x7fbaf1e66b80>
In [ ]:
Copied!
pipeline.fit() # submit pipeline here
pipeline.fit() # submit pipeline here
Last update:
2023-01-03