diff --git a/examples/flower-client/8b601bcb-0392-44c8-a2f2-2f77b13674d8.tgz b/examples/flower-client/8b601bcb-0392-44c8-a2f2-2f77b13674d8.tgz deleted file mode 100644 index 557fff559..000000000 Binary files a/examples/flower-client/8b601bcb-0392-44c8-a2f2-2f77b13674d8.tgz and /dev/null differ diff --git a/examples/flower-client/client275-20240423-182523/entrypoint.py b/examples/flower-client/client275-20240423-182523/entrypoint.py deleted file mode 100755 index e80e7d4b5..000000000 --- a/examples/flower-client/client275-20240423-182523/entrypoint.py +++ /dev/null @@ -1,107 +0,0 @@ -import os - -import fire -from flwr_client import app - -from fedn.utils.flowercompat.client_app_adapter import FlwrClientAppAdapter -from fedn.utils.helpers.helpers import get_helper, save_metadata, save_metrics - -HELPER_MODULE = "numpyhelper" -helper = get_helper(HELPER_MODULE) - -flwr_adapter = FlwrClientAppAdapter(app) - - -def _get_node_id(): - """Get client number from environment variable.""" - - number = os.environ.get("CLIENT_NUMBER", "0") - return int(number) - - -def save_parameters(out_path, parameters_np): - """Save model paramters to file. - - :param model: The model to serialize. - :type model: torch.nn.Module - :param out_path: The path to save to. - :type out_path: str - """ - helper.save(parameters_np, out_path) - - -def init_seed(out_path="../seed.npz"): - """Initialize seed model and save it to file. - - :param out_path: The path to save the seed model to. - :type out_path: str - """ - # This calls get_parameters in the flower client which needs to be implemented. - parameters_np = flwr_adapter.init_parameters(partition_id=_get_node_id(), config={}) - save_parameters(out_path, parameters_np) - - -def train(in_model_path, out_model_path): - """Complete a model update. - - Load model paramters from in_model_path (managed by the FEDn client), - perform a model update through the flower client, and write updated paramters - to out_model_path (picked up by the FEDn client). - - :param in_model_path: The path to the input model. - :type in_model_path: str - :param out_model_path: The path to save the output model to. - :type out_model_path: str - """ - parameters_np = helper.load(in_model_path) - - # Train on flower client - params, num_examples = flwr_adapter.train( - parameters=parameters_np, partition_id=_get_node_id(), config={} - ) - - # Metadata needed for aggregation server side - metadata = { - # num_examples are mandatory - "num_examples": num_examples, - } - - # Save JSON metadata file (mandatory) - save_metadata(metadata, out_model_path) - - # Save model update (mandatory) - save_parameters(out_model_path, params) - - -def validate(in_model_path, out_json_path, data_path=None): - """Validate model on the clients test dataset. - - :param in_model_path: The path to the input model. - :type in_model_path: str - :param out_json_path: The path to save the output JSON to. - :type out_json_path: str - :param data_path: The path to the data file. - :type data_path: str - """ - parameters_np = helper.load(in_model_path) - - loss, accuracy = flwr_adapter.evaluate(parameters_np, partition_id=_get_node_id(), config={}) - - # JSON schema - report = { - "test_loss": loss, - "test_accuracy": accuracy, - } - print(f"Loss: {loss}, accuracy: {accuracy}") - # Save JSON - save_metrics(report, out_json_path) - - -if __name__ == "__main__": - fire.Fire( - { - "init_seed": init_seed, - "train": train, - "validate": validate, - } - ) diff --git a/examples/flower-client/client275-20240423-182523/fedn.yaml b/examples/flower-client/client275-20240423-182523/fedn.yaml deleted file mode 100644 index 9fb33f18f..000000000 --- a/examples/flower-client/client275-20240423-182523/fedn.yaml +++ /dev/null @@ -1,8 +0,0 @@ -python_env: python_env.yaml -entry_points: - build: - command: python entrypoint.py init_seed - train: - command: python entrypoint.py train - validate: - command: python entrypoint.py validate \ No newline at end of file diff --git a/examples/flower-client/client275-20240423-182523/flwr_client.py b/examples/flower-client/client275-20240423-182523/flwr_client.py deleted file mode 100644 index 297df3ca7..000000000 --- a/examples/flower-client/client275-20240423-182523/flwr_client.py +++ /dev/null @@ -1,41 +0,0 @@ -"""Flower client code using the ClientApp abstraction. -Code adapted from https://github.com/adap/flower/tree/main/examples/app-pytorch. -""" - -from flwr.client import ClientApp, NumPyClient -from flwr_task import (DEVICE, Net, get_weights, load_data, set_weights, test, - train) - - -# Define FlowerClient and client_fn -class FlowerClient(NumPyClient): - def __init__(self, cid) -> None: - super().__init__() - self.net = Net().to(DEVICE) - self.trainloader, self.testloader = load_data( - partition_id=int(cid), num_clients=10 - ) - - def get_parameters(self, config): - return [val.cpu().numpy() for _, val in self.net.state_dict().items()] - - def fit(self, parameters, config): - set_weights(self.net, parameters) - train(self.net, self.trainloader, epochs=3) - return get_weights(self.net), len(self.trainloader.dataset), {} - - def evaluate(self, parameters, config): - set_weights(self.net, parameters) - loss, accuracy = test(self.net, self.testloader) - return loss, len(self.testloader.dataset), {"accuracy": accuracy} - - -def client_fn(cid: str): - """Create and return an instance of Flower `Client`.""" - return FlowerClient(cid).to_client() - - -# Flower ClientApp -app = ClientApp( - client_fn=client_fn, -) diff --git a/examples/flower-client/client275-20240423-182523/flwr_task.py b/examples/flower-client/client275-20240423-182523/flwr_task.py deleted file mode 100644 index dea53d9cc..000000000 --- a/examples/flower-client/client275-20240423-182523/flwr_task.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Flower client code for helper functions. -Code adapted from https://github.com/adap/flower/tree/main/examples/app-pytorch. -""" - -from collections import OrderedDict - -import torch -import torch.nn as nn -import torch.nn.functional as F -from flwr_datasets import FederatedDataset -from torch.utils.data import DataLoader -from torchvision.transforms import Compose, Normalize, ToTensor -from tqdm import tqdm - -DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") - - -class Net(nn.Module): - """Model (simple CNN adapted from 'PyTorch: A 60 Minute Blitz')""" - - def __init__(self) -> None: - super(Net, self).__init__() - self.conv1 = nn.Conv2d(3, 6, 5) - self.pool = nn.MaxPool2d(2, 2) - self.conv2 = nn.Conv2d(6, 16, 5) - self.fc1 = nn.Linear(16 * 5 * 5, 120) - self.fc2 = nn.Linear(120, 84) - self.fc3 = nn.Linear(84, 10) - - def forward(self, x: torch.Tensor) -> torch.Tensor: - x = self.pool(F.relu(self.conv1(x))) - x = self.pool(F.relu(self.conv2(x))) - x = x.view(-1, 16 * 5 * 5) - x = F.relu(self.fc1(x)) - x = F.relu(self.fc2(x)) - return self.fc3(x) - - -def load_data(partition_id, num_clients): - """Load partition CIFAR10 data.""" - fds = FederatedDataset(dataset="cifar10", partitioners={"train": num_clients}) - partition = fds.load_partition(partition_id) - # Divide data on each node: 80% train, 20% test - partition_train_test = partition.train_test_split(test_size=0.2) - pytorch_transforms = Compose( - [ToTensor(), Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))] - ) - - def apply_transforms(batch): - """Apply transforms to the partition from FederatedDataset.""" - batch["img"] = [pytorch_transforms(img) for img in batch["img"]] - return batch - - partition_train_test = partition_train_test.with_transform(apply_transforms) - trainloader = DataLoader(partition_train_test["train"], batch_size=32, shuffle=True) - testloader = DataLoader(partition_train_test["test"], batch_size=32) - return trainloader, testloader - - -def train(net, trainloader, epochs): - """Train the model on the training set.""" - criterion = torch.nn.CrossEntropyLoss() - optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9) - for _ in range(epochs): - for batch in tqdm(trainloader, "Training"): - images = batch["img"] - labels = batch["label"] - optimizer.zero_grad() - criterion(net(images.to(DEVICE)), labels.to(DEVICE)).backward() - optimizer.step() - - -def test(net, testloader): - """Validate the model on the test set.""" - criterion = torch.nn.CrossEntropyLoss() - correct, loss = 0, 0.0 - with torch.no_grad(): - for batch in tqdm(testloader, "Testing"): - images = batch["img"].to(DEVICE) - labels = batch["label"].to(DEVICE) - outputs = net(images) - loss += criterion(outputs, labels).item() - correct += (torch.max(outputs.data, 1)[1] == labels).sum().item() - accuracy = correct / len(testloader.dataset) - return loss, accuracy - - -def get_weights(net): - return [val.cpu().numpy() for _, val in net.state_dict().items()] - - -def set_weights(net, parameters): - params_dict = zip(net.state_dict().keys(), parameters) - state_dict = OrderedDict({k: torch.tensor(v) for k, v in params_dict}) - net.load_state_dict(state_dict, strict=True) diff --git a/examples/flower-client/client275-20240423-182523/python_env.yaml b/examples/flower-client/client275-20240423-182523/python_env.yaml deleted file mode 100644 index 984a2e96d..000000000 --- a/examples/flower-client/client275-20240423-182523/python_env.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: flower-client -build_dependencies: - - pip - - setuptools - - wheel==0.37.1 -dependencies: - - torch==2.2.1 - - torchvision==0.17.1 - - fire==0.3.1 - - fedn[flower]==0.9.0 - - flwr-datasets[vision]==0.1.0 \ No newline at end of file diff --git a/examples/flower-client/client275-20240423-182644/entrypoint.py b/examples/flower-client/client275-20240423-182644/entrypoint.py deleted file mode 100755 index e80e7d4b5..000000000 --- a/examples/flower-client/client275-20240423-182644/entrypoint.py +++ /dev/null @@ -1,107 +0,0 @@ -import os - -import fire -from flwr_client import app - -from fedn.utils.flowercompat.client_app_adapter import FlwrClientAppAdapter -from fedn.utils.helpers.helpers import get_helper, save_metadata, save_metrics - -HELPER_MODULE = "numpyhelper" -helper = get_helper(HELPER_MODULE) - -flwr_adapter = FlwrClientAppAdapter(app) - - -def _get_node_id(): - """Get client number from environment variable.""" - - number = os.environ.get("CLIENT_NUMBER", "0") - return int(number) - - -def save_parameters(out_path, parameters_np): - """Save model paramters to file. - - :param model: The model to serialize. - :type model: torch.nn.Module - :param out_path: The path to save to. - :type out_path: str - """ - helper.save(parameters_np, out_path) - - -def init_seed(out_path="../seed.npz"): - """Initialize seed model and save it to file. - - :param out_path: The path to save the seed model to. - :type out_path: str - """ - # This calls get_parameters in the flower client which needs to be implemented. - parameters_np = flwr_adapter.init_parameters(partition_id=_get_node_id(), config={}) - save_parameters(out_path, parameters_np) - - -def train(in_model_path, out_model_path): - """Complete a model update. - - Load model paramters from in_model_path (managed by the FEDn client), - perform a model update through the flower client, and write updated paramters - to out_model_path (picked up by the FEDn client). - - :param in_model_path: The path to the input model. - :type in_model_path: str - :param out_model_path: The path to save the output model to. - :type out_model_path: str - """ - parameters_np = helper.load(in_model_path) - - # Train on flower client - params, num_examples = flwr_adapter.train( - parameters=parameters_np, partition_id=_get_node_id(), config={} - ) - - # Metadata needed for aggregation server side - metadata = { - # num_examples are mandatory - "num_examples": num_examples, - } - - # Save JSON metadata file (mandatory) - save_metadata(metadata, out_model_path) - - # Save model update (mandatory) - save_parameters(out_model_path, params) - - -def validate(in_model_path, out_json_path, data_path=None): - """Validate model on the clients test dataset. - - :param in_model_path: The path to the input model. - :type in_model_path: str - :param out_json_path: The path to save the output JSON to. - :type out_json_path: str - :param data_path: The path to the data file. - :type data_path: str - """ - parameters_np = helper.load(in_model_path) - - loss, accuracy = flwr_adapter.evaluate(parameters_np, partition_id=_get_node_id(), config={}) - - # JSON schema - report = { - "test_loss": loss, - "test_accuracy": accuracy, - } - print(f"Loss: {loss}, accuracy: {accuracy}") - # Save JSON - save_metrics(report, out_json_path) - - -if __name__ == "__main__": - fire.Fire( - { - "init_seed": init_seed, - "train": train, - "validate": validate, - } - ) diff --git a/examples/flower-client/client275-20240423-182644/fedn.yaml b/examples/flower-client/client275-20240423-182644/fedn.yaml deleted file mode 100644 index 9fb33f18f..000000000 --- a/examples/flower-client/client275-20240423-182644/fedn.yaml +++ /dev/null @@ -1,8 +0,0 @@ -python_env: python_env.yaml -entry_points: - build: - command: python entrypoint.py init_seed - train: - command: python entrypoint.py train - validate: - command: python entrypoint.py validate \ No newline at end of file diff --git a/examples/flower-client/client275-20240423-182644/flwr_client.py b/examples/flower-client/client275-20240423-182644/flwr_client.py deleted file mode 100644 index 297df3ca7..000000000 --- a/examples/flower-client/client275-20240423-182644/flwr_client.py +++ /dev/null @@ -1,41 +0,0 @@ -"""Flower client code using the ClientApp abstraction. -Code adapted from https://github.com/adap/flower/tree/main/examples/app-pytorch. -""" - -from flwr.client import ClientApp, NumPyClient -from flwr_task import (DEVICE, Net, get_weights, load_data, set_weights, test, - train) - - -# Define FlowerClient and client_fn -class FlowerClient(NumPyClient): - def __init__(self, cid) -> None: - super().__init__() - self.net = Net().to(DEVICE) - self.trainloader, self.testloader = load_data( - partition_id=int(cid), num_clients=10 - ) - - def get_parameters(self, config): - return [val.cpu().numpy() for _, val in self.net.state_dict().items()] - - def fit(self, parameters, config): - set_weights(self.net, parameters) - train(self.net, self.trainloader, epochs=3) - return get_weights(self.net), len(self.trainloader.dataset), {} - - def evaluate(self, parameters, config): - set_weights(self.net, parameters) - loss, accuracy = test(self.net, self.testloader) - return loss, len(self.testloader.dataset), {"accuracy": accuracy} - - -def client_fn(cid: str): - """Create and return an instance of Flower `Client`.""" - return FlowerClient(cid).to_client() - - -# Flower ClientApp -app = ClientApp( - client_fn=client_fn, -) diff --git a/examples/flower-client/client275-20240423-182644/flwr_task.py b/examples/flower-client/client275-20240423-182644/flwr_task.py deleted file mode 100644 index dea53d9cc..000000000 --- a/examples/flower-client/client275-20240423-182644/flwr_task.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Flower client code for helper functions. -Code adapted from https://github.com/adap/flower/tree/main/examples/app-pytorch. -""" - -from collections import OrderedDict - -import torch -import torch.nn as nn -import torch.nn.functional as F -from flwr_datasets import FederatedDataset -from torch.utils.data import DataLoader -from torchvision.transforms import Compose, Normalize, ToTensor -from tqdm import tqdm - -DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") - - -class Net(nn.Module): - """Model (simple CNN adapted from 'PyTorch: A 60 Minute Blitz')""" - - def __init__(self) -> None: - super(Net, self).__init__() - self.conv1 = nn.Conv2d(3, 6, 5) - self.pool = nn.MaxPool2d(2, 2) - self.conv2 = nn.Conv2d(6, 16, 5) - self.fc1 = nn.Linear(16 * 5 * 5, 120) - self.fc2 = nn.Linear(120, 84) - self.fc3 = nn.Linear(84, 10) - - def forward(self, x: torch.Tensor) -> torch.Tensor: - x = self.pool(F.relu(self.conv1(x))) - x = self.pool(F.relu(self.conv2(x))) - x = x.view(-1, 16 * 5 * 5) - x = F.relu(self.fc1(x)) - x = F.relu(self.fc2(x)) - return self.fc3(x) - - -def load_data(partition_id, num_clients): - """Load partition CIFAR10 data.""" - fds = FederatedDataset(dataset="cifar10", partitioners={"train": num_clients}) - partition = fds.load_partition(partition_id) - # Divide data on each node: 80% train, 20% test - partition_train_test = partition.train_test_split(test_size=0.2) - pytorch_transforms = Compose( - [ToTensor(), Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))] - ) - - def apply_transforms(batch): - """Apply transforms to the partition from FederatedDataset.""" - batch["img"] = [pytorch_transforms(img) for img in batch["img"]] - return batch - - partition_train_test = partition_train_test.with_transform(apply_transforms) - trainloader = DataLoader(partition_train_test["train"], batch_size=32, shuffle=True) - testloader = DataLoader(partition_train_test["test"], batch_size=32) - return trainloader, testloader - - -def train(net, trainloader, epochs): - """Train the model on the training set.""" - criterion = torch.nn.CrossEntropyLoss() - optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9) - for _ in range(epochs): - for batch in tqdm(trainloader, "Training"): - images = batch["img"] - labels = batch["label"] - optimizer.zero_grad() - criterion(net(images.to(DEVICE)), labels.to(DEVICE)).backward() - optimizer.step() - - -def test(net, testloader): - """Validate the model on the test set.""" - criterion = torch.nn.CrossEntropyLoss() - correct, loss = 0, 0.0 - with torch.no_grad(): - for batch in tqdm(testloader, "Testing"): - images = batch["img"].to(DEVICE) - labels = batch["label"].to(DEVICE) - outputs = net(images) - loss += criterion(outputs, labels).item() - correct += (torch.max(outputs.data, 1)[1] == labels).sum().item() - accuracy = correct / len(testloader.dataset) - return loss, accuracy - - -def get_weights(net): - return [val.cpu().numpy() for _, val in net.state_dict().items()] - - -def set_weights(net, parameters): - params_dict = zip(net.state_dict().keys(), parameters) - state_dict = OrderedDict({k: torch.tensor(v) for k, v in params_dict}) - net.load_state_dict(state_dict, strict=True) diff --git a/examples/flower-client/client275-20240423-182644/python_env.yaml b/examples/flower-client/client275-20240423-182644/python_env.yaml deleted file mode 100644 index 984a2e96d..000000000 --- a/examples/flower-client/client275-20240423-182644/python_env.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: flower-client -build_dependencies: - - pip - - setuptools - - wheel==0.37.1 -dependencies: - - torch==2.2.1 - - torchvision==0.17.1 - - fire==0.3.1 - - fedn[flower]==0.9.0 - - flwr-datasets[vision]==0.1.0 \ No newline at end of file diff --git a/examples/flower-client/e52af40d-6c0f-44f5-ac72-184ffa097855.tgz b/examples/flower-client/e52af40d-6c0f-44f5-ac72-184ffa097855.tgz deleted file mode 100644 index 883477695..000000000 Binary files a/examples/flower-client/e52af40d-6c0f-44f5-ac72-184ffa097855.tgz and /dev/null differ diff --git a/examples/flower-client/package.tgz b/examples/flower-client/package.tgz deleted file mode 100644 index 883477695..000000000 Binary files a/examples/flower-client/package.tgz and /dev/null differ diff --git a/examples/flower-client/seed.npz b/examples/flower-client/seed.npz deleted file mode 100644 index 5ed2a48cb..000000000 Binary files a/examples/flower-client/seed.npz and /dev/null differ