Skip to content

Commit

Permalink
Merge branch 'develop' into torch-update
Browse files Browse the repository at this point in the history
  • Loading branch information
tanwarsh authored Jan 22, 2025
2 parents 58b3a4e + cafc558 commit a414b22
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ def __prune_poisoned_models(num_layers, total_number_of_clients, own_client_inde

ac_e = AgglomerativeClustering(n_clusters=2, distance_threshold=None,
compute_full_tree=True,
affinity="euclidean", memory=None,
metric="euclidean", memory=None,
connectivity=None,
linkage='single',
compute_distances=True).fit(cluster_input)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,8 @@
" state_dicts = [model.state_dict() for model in models]\n",
" state_dict = new_model.state_dict()\n",
" for key in models[1].state_dict():\n",
" state_dict[key] = np.sum(\n",
" [state[key] for state in state_dicts], axis=0\n",
" ) / len(models)\n",
" state_dict[key] = torch.from_numpy(\n",
" np.average([state[key].numpy() for state in state_dicts], axis=0))\n",
" new_model.load_state_dict(state_dict)\n",
" return new_model\n",
"\n",
Expand Down Expand Up @@ -558,8 +557,7 @@
" exclude=[\"private\"],\n",
" )\n",
"\n",
" # @collaborator # Uncomment if you want ro run on CPU\n",
" @collaborator(num_gpus=1) # Assuming GPU(s) is available on the machine\n",
" @collaborator\n",
" def train(self):\n",
" self.collaborator_name = self.input\n",
" print(20 * \"#\")\n",
Expand Down Expand Up @@ -669,7 +667,7 @@
"\n",
" ac_e = AgglomerativeClustering(n_clusters=2, distance_threshold=None,\n",
" compute_full_tree=True,\n",
" affinity=\"euclidean\", memory=None, connectivity=None,\n",
" metric=\"euclidean\", memory=None, connectivity=None,\n",
" linkage='single',\n",
" compute_distances=True).fit(binary_votes)\n",
" ac_e_labels: list = ac_e.labels_.tolist()\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,8 @@ def FedAvg(models): # NOQA: N802
state_dicts = [model.state_dict() for model in models]
state_dict = new_model.state_dict()
for key in models[1].state_dict():
state_dict[key] = np.sum(
[state[key] for state in state_dicts], axis=0
) / len(models)
state_dict[key] = torch.from_numpy(
np.average([state[key].numpy() for state in state_dicts], axis=0))
new_model.load_state_dict(state_dict)
return new_model

Expand Down Expand Up @@ -316,8 +315,7 @@ def start(self):
exclude=["private"],
)

# @collaborator # Uncomment if you want ro run on CPU
@collaborator(num_gpus=1) # Assuming GPU(s) is available on the machine
@collaborator
def train(self):
self.collaborator_name = self.input
print(20 * "#")
Expand Down Expand Up @@ -428,7 +426,7 @@ def defend(self, inputs):

ac_e = AgglomerativeClustering(n_clusters=2, distance_threshold=None,
compute_full_tree=True,
affinity="euclidean", memory=None, connectivity=None,
metric="euclidean", memory=None, connectivity=None,
linkage='single',
compute_distances=True).fit(binary_votes)
ac_e_labels: list = ac_e.labels_.tolist()
Expand Down
27 changes: 26 additions & 1 deletion openfl-tutorials/experimental/workflow/CrowdGuard/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,29 @@ We implemented a simple scaling-based poisoning attack to demonstrate the effect

For the local validation in CrowdGuard, each client uses its local dataset to obtain the hidden layer outputs for each local model. Then it calculates the Euclidean and Cosine Distance, before applying a PCA. Based on the first principal component, CrowdGuard employs several statistical tests to determine whether poisoned models remain and removes the poisoned models using clustering. This process is repeated until no more poisoned models are detected before sending the detected poisoned models to the server. On the server side, the votes of the individual clients are aggregated using a stacked-clustering scheme to prevent malicious clients from manipulating the aggregation process through manipulated votes. The client-side validation as well as the server-side operations, are executed with SGX to prevent privacy attacks.

[1] Rieger, P., Krauß, T., Miettinen, M., Dmitrienko, A., & Sadeghi, A. R. CrowdGuard: Federated Backdoor Detection in Federated Learning. NDSS 2024.
[1] Rieger, P., Krauß, T., Miettinen, M., Dmitrienko, A., & Sadeghi, A. R. CrowdGuard: Federated Backdoor Detection in Federated Learning. NDSS 2024.

## Running the CIFAR-10 demo script
The demo script requires a dedicated allocation of at least 18GB of RAM to run without issues.

1) Create a Python virtual environment for better isolation
```shell
python -m venv venv
source venv/bin/activate
```
2) Install OpenFL from the latest sources
```shell
git clone https://github.com/securefederatedai/openfl.git && cd openfl
pip install -e .
```
3) Install the requirements for Workflow API
```shell
cd openfl-tutorials/experimental/workflow
pip install -r workflow_interface_requirements.txt
```
4) Start the training script<br/>
Note that the number of training rounds can be adjusted via the `--comm_round` parameter:
```shell
cd CrowdGuard
python cifar10_crowdguard.py --comm_round 5
```

0 comments on commit a414b22

Please sign in to comment.