Defenses (PPFL techniques)¶
Defenses are hook plugins (fltest/defenses/) that subclass PPFLBaseClass. Declare them
in a config:
defenses:
- {name: <defense>, params: {...}}
Two flavors compose through the same hooks:
- Client-side perturbation acts at
after_client_trainon one client's update. - Robust aggregation acts at
before_aggregateby replacing the set of updates the backend will average.
Catalog¶
| Name | Type | Hook | Key params |
|---|---|---|---|
gradient_noise |
DP-style clip + Gaussian noise | after_client_train |
clip_norm (1.0), sigma (0.01) |
norm_clip |
update-norm clipping | after_client_train |
clip_norm (1.0) |
krum |
robust aggregation (select) | before_aggregate |
num_byzantine (1) |
trimmed_mean |
robust aggregation (coordinate trim) | before_aggregate |
trim (1) |
median |
robust aggregation (coordinate median) | before_aggregate |
— |
How each works¶
gradient_noise — clips the client's update delta (relative to the current global
model) to clip_norm, then adds N(0, sigma²). The user-space analogue of DP-SGD's
per-update clipping + noise. Sweep sigma to chart the privacy/utility trade-off (the
project's Pitfall-4).
norm_clip — clips the update delta's L2 norm to clip_norm without noise. Limits the
magnitude a malicious client can inject (mitigates scaled poisoning / sign-flip).
krum — selects the single client update closest to its n − f − 2 nearest neighbours
(the most "agreed upon"), robust to up to f = num_byzantine adversaries.
trimmed_mean — for each coordinate, drops the trim largest and smallest values
across clients, then averages the rest.
median — coordinate-wise median across client updates. Simple and strong against a
Byzantine minority.
Backend support
Client-side and robust-aggregation defenses run on the reference and Flower backends. NVFlare runs clients in separate processes, so it does not apply client-side hooks (it's used for cross-framework parity of vanilla FedAvg).
Worked example: defeating a backdoor¶
examples/configs/defense_robust.yaml — two of six clients run a strong backdoor;
median aggregation rejects the poisoned updates:
| Defense | attack_success_rate | accuracy |
|---|---|---|
| none | 0.80 | 0.90 |
median |
0.03 | 0.90 |
norm_clip (clip_norm 0.5) |
0.67 | 0.86 |
attacks: [{name: backdoor, params: {infection_rate: 0.8, patch_size: 5}, target_clients: [0, 1]}]
defenses: [{name: median}]
metrics: [accuracy, loss, per_client]
Sweep a defense parameter (metamorphic)¶
defenses: [{name: gradient_noise, params: {clip_norm: 1.0, sigma: 0.05}}]
testing:
metamorphic:
- {relation: dp_noise, parameter: defense.sigma, values: [0.0, 0.05, 0.1, 0.2], metric: accuracy}
More noise should not increase accuracy (utility non-increasing). See Metamorphic testing.
To add your own defense, see Port your attacks & defenses.