FedModelKit 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,140 @@
1
+ """
2
+ Model upload example script.
3
+
4
+ To run this code you need to install pytorch library, you can find it at this link: https://pytorch.org/get-started/locally/
5
+ """
6
+ from FedModelKit import FederatedModel, submit_fl_model
7
+
8
+ # Create your custom function defining a PyTorch-based model and returning its instance
9
+ def create_local_learner():
10
+ import pandas as pd
11
+ from torch import nn, optim
12
+ from torch.utils.data import DataLoader, Dataset
13
+ import torch
14
+ import flwr
15
+
16
+ from src.utils import Utils # Dependency script stored inside the src directory
17
+
18
+ class CustomLocalLearner(nn.Module):
19
+ def __init__(self, input_size: int) -> None:
20
+ super(CustomLocalLearner, self).__init__()
21
+ self.linear = nn.Linear(input_size, 3)
22
+ self.softmax = nn.Softmax(dim=1)
23
+ self.loss_fn = nn.CrossEntropyLoss()
24
+ self.optimizer = optim.Adam(self.parameters(), lr=0.001)
25
+
26
+ def _forward(self, x):
27
+ x = self.linear(x)
28
+ return self.softmax(x)
29
+
30
+ def get_parameters(self) -> flwr.common.ParametersRecord:
31
+ return Utils.pytorch_to_parameter_record(self.state_dict())
32
+
33
+ def set_parameters(self, parameters: flwr.common.ParametersRecord) -> None:
34
+ self.load_state_dict(Utils.parameters_to_pytorch_state_dict(parameters))
35
+
36
+ def prepare_data(self, data: pd.DataFrame) -> None:
37
+ class IrisDataset(Dataset):
38
+ def __init__(self, dataframe: pd.DataFrame) -> None:
39
+ self.dataframe = dataframe
40
+ self.dataframe.loc[:, "class"] = dataframe.loc[:, "class"].replace(
41
+ {"Iris-setosa": 0, "Iris-versicolor": 1, "Iris-virginica": 2}
42
+ )
43
+
44
+ def __getitem__(self, idx: int):
45
+ x = self.dataframe.iloc[idx, :-1].to_numpy("float32")
46
+ y = torch.tensor(self.dataframe.iloc[idx, -1], dtype=torch.long)
47
+ return x, y
48
+
49
+ def __len__(self) -> int:
50
+ return len(self.dataframe)
51
+
52
+ dataset = IrisDataset(data)
53
+ dataloader = DataLoader(dataset, batch_size=32)
54
+ self.dataloader = dataloader
55
+
56
+ def train_round(self) -> flwr.common.MetricsRecord:
57
+ loss = torch.tensor(0.0)
58
+ for batch in self.dataloader:
59
+ x, y = batch
60
+ self.optimizer.zero_grad()
61
+ y_hat = self._forward(x)
62
+ loss = self.loss_fn(y_hat, y)
63
+ loss.backward()
64
+ self.optimizer.step()
65
+
66
+ return flwr.common.MetricsRecord({"loss": loss.item()})
67
+
68
+ def evaluate(self) -> flwr.common.MetricsRecord:
69
+ correct = 0
70
+ total = 0
71
+ with torch.no_grad():
72
+ for batch in self.dataloader:
73
+ x, y = batch
74
+ y_hat = self._forward(x)
75
+ _, predicted = torch.max(y_hat, 1)
76
+ total += y.size(0)
77
+ correct += (predicted == y).sum().item()
78
+ return flwr.common.MetricsRecord({"accuracy": correct / total})
79
+
80
+ return CustomLocalLearner(4)
81
+
82
+
83
+ # Create your custom function defining an aggregation strategy and returning its instance
84
+ def create_aggregator():
85
+ from collections import OrderedDict
86
+ import numpy as np
87
+ import flwr
88
+ from typing import Optional
89
+
90
+ from src.utils import Utils # Dependency script stored inside the src directory #type: ignore[import]
91
+
92
+ class CustomAggregator:
93
+
94
+ def aggregate_parameters(self, results: list[flwr.common.ParametersRecord], config: Optional[flwr.common.ConfigsRecord]=None
95
+ ) -> flwr.common.ParametersRecord:
96
+ parameters = [Utils.parameters_to_dict(param) for param in results]
97
+ keys = parameters[0].keys()
98
+ result = OrderedDict()
99
+ for key in keys:
100
+ # Init array
101
+ this_array: np.ndarray = np.zeros_like(parameters[0][key])
102
+ for p in parameters:
103
+ this_array += p[key]
104
+ result[key] = this_array / len(results)
105
+ return Utils.dict_to_parameter_record(result)
106
+
107
+ def aggregate_metrics(self, results: list[flwr.common.MetricsRecord], config: Optional[flwr.common.ConfigsRecord]=None) -> flwr.common.MetricsRecord:
108
+ keys = results[0].keys()
109
+ result = OrderedDict()
110
+ for key in keys:
111
+ # Init array
112
+ cumsum = 0.0
113
+ for m in results:
114
+ if not isinstance(m[key], (int, float)):
115
+ raise ValueError(
116
+ f"flwr.common.MetricsRecord value type not supported: {type(m[key])}"
117
+ )
118
+ cumsum += m[key] # type: ignore
119
+ result[key] = cumsum / len(results)
120
+ return flwr.common.MetricsRecord(result)
121
+
122
+ return CustomAggregator()
123
+
124
+
125
+ if __name__ == "__main__":
126
+ # Create FederatedModel with custom aggregator and local learner
127
+ federated_model = FederatedModel(create_local_learner=create_local_learner,
128
+ model_name="your_model_name",
129
+ create_aggregator=create_aggregator,
130
+ aggregator_name="custom_aggregator")
131
+
132
+ # Submit the FederatedModel to the Federated Platform Model Catalogue with credentials and experiment name
133
+ submit_fl_model(federated_model,
134
+ platform_url="your_platform_url",
135
+ username="your_username",
136
+ password="your_password",
137
+ experiment_name="your_experiment_name",
138
+ disease="AML",
139
+ trained=False
140
+ )