Skip to content

Conversation

@francordel
Copy link

Issue

Closes #6043.


Description

Flower currently lacks a robust aggregation strategy to defend against poisoning attacks in Federated Learning.
When malicious clients send corrupted model updates, the standard FedAvg aggregation can be heavily compromised, leading to a significant degradation in global model performance.


Related issues/PRs

  • Enables the new baseline proposed in #6039.

Proposal

Implement FedRDF (Robust and Dynamic Aggregation Function) — a strategy that defends against poisoning attacks through adaptive, frequency-domain aggregation.

Explanation

FedRDF introduces the following improvements:

  1. Adaptive aggregation: Detects poisoning using the Kolmogorov–Smirnov test for skewness in client updates.
  2. FFT-based robust aggregation: When anomalies are detected, transforms client updates to the frequency domain using the Discrete Fourier Transform (DFT), selects dominant components, and filters outliers before reconstructing the update via inverse FFT.
  3. Configurable threshold: The threshold parameter controls the robustness–efficiency trade-off.
    • threshold ≤ 0: Always uses FFT-based robust aggregation.
    • threshold > 0: Switches adaptively based on detected skewness.
  4. Layer-wise processing: Performs robust aggregation on each model layer individually for fine-grained resilience.

Implementation Details

  • Inherits from FedAvg.
  • Overrides aggregate_fit() to perform adaptive, DFT-based aggregation.
  • Adds threshold parameter for dynamic switching.
  • Fully compatible with Flower’s existing strategy API.

Testing

  • 10 unit tests implemented and passing.
  • Validated against a 30% poisoning attack scenario.
  • Result: FedRDF maintained a distance to benign clients of 0.012, compared to 29.971 for FedAvg (≈2500× more robust).

Reference

E. Mármol Campos, A. González-Vidal, J. L. Hernández-Ramos, and A. Skarmeta,
"FedRDF: A Robust and Dynamic Aggregation Function Against Poisoning Attacks in Federated Learning",
IEEE Transactions on Emerging Topics in Computing, vol. 13, no. 1, pp. 48–67, 2025.
DOI: 10.1109/TETC.2024.3474484


Checklist

  • Implement proposed change.
  • Write tests (10 unit tests, all passing).
  • Update documentation.
  • Make CI checks pass.
  • Ping maintainers on Slack (channel #contributions).

Any other comments?

Files changed:

  • framework/py/flwr/server/strategy/fedrdf.py (371 lines) — strategy implementation.
  • framework/py/flwr/server/strategy/fedrdf_test.py (228 lines) — test suite.
  • framework/py/flwr/server/strategy/__init__.py (2 lines) — added FedRDF export.

@jafermarq
Copy link
Member

Hey @francordel , thanks for opening the PR! We recently migrated all strategies to https://github.com/adap/flower/tree/main/framework/py/flwr/serverapp/strategy and make use of the Message abstraction instead of FitIns/Res etc. Could you update the strategy in that way? Also, because scipy is not a package that comes with Flower, we'll need to put the import in a try/except. Or is there a way to use ks_2samp without introducing a new dependency?

@github-actions github-actions bot added the Contributor Used to determine what PRs (mainly) come from external contributors. label Oct 22, 2025
@WilliamLindskog
Copy link
Member

Hi @francordel,

just checking in here to see if there are any questions from your end re Javier's above comments. Please let us know by when you aim to continue working on this PR.

Best regards,
William

@francordel
Copy link
Author

francordel commented Dec 9, 2025

Hi @WilliamLindskog,
yes, I’m still on it. I had to pause for a few weeks due to other deadlines, but I’m back now. I’m addressing Javier’s feedback (moving FedRDF to the new ServerApp/Message-based pattern without initialize_parameters, handling the scipy import, and tightening the tests). I’ll push updates and respond to the open comments today or in the next few days. Thanks for your patience.

Addresses review feedback from PR adap#6044 by @danieljanes:
"We recently migrated all strategies to serverapp/strategy and make use
of the Message abstraction instead of FitIns/Res etc. Could you update
the strategy in that way? Also, because scipy is not a package that comes
with Flower, we'll need to put the import in a try/except."

Migration implementation:
- Moved from server/strategy to serverapp/strategy
- Replaced FitIns/FitRes with Message abstraction (Iterable[Message])
- Use ArrayRecord/MetricRecord instead of Parameters/Metrics
- Updated aggregate_train/aggregate_evaluate signatures for Message API
- Wrapped scipy import in try/except with HAS_SCIPY flag (lines 31-37)
- Added ImportError in __init__ with installation instructions (lines 133-137)
- Migrated all unit tests to new API

Performance optimization:
During migration testing, discovered critical bottleneck in _compute_skewness
that made threshold > 0 functionality impractical:
- Sample max 100 weight positions instead of testing all positions
- Reduces K-S test complexity from O(n_parameters * 100) to O(100 * 100)
- Enables practical use of adaptive FedAvg/FFT switching
- Threshold=0.5 now completes in ~97s vs hanging indefinitely

Scipy dependency handling:
Import wrapped in try/except block with HAS_SCIPY flag. Strategy __init__
raises ImportError with clear message if scipy not installed, directing
users to install scipy>=1.7.0.

Files changed:
- framework/py/flwr/serverapp/strategy/fedrdf.py (new, migrated + optimized)
- framework/py/flwr/serverapp/strategy/fedrdf_test.py (new, migrated)
- framework/py/flwr/serverapp/strategy/__init__.py (add FedRDF export)
- framework/py/flwr/server/strategy/__init__.py (remove old export)
- framework/py/flwr/server/strategy/fedrdf.py (deleted)
- framework/py/flwr/server/strategy/fedrdf_test.py (deleted)

Testing:
- All unit tests passing in new location
- Threshold functionality verified working (0.0, 0.5, 1.0 tested)
- ImportError raised correctly when scipy not available

Related: PR adap#6044
@francordel
Copy link
Author

francordel commented Dec 10, 2025

Good evening @jafermarq @WilliamLindskog !
I have addressed the comments:
feat(strategy): Migrate FedRDF to serverapp/strategy with Message API

Addresses review feedback from PR #6044 by @danieljanes:
"We recently migrated all strategies to serverapp/strategy and make use
of the Message abstraction instead of FitIns/Res etc. Could you update
the strategy in that way? Also, because scipy is not a package that comes
with Flower, we'll need to put the import in a try/except."

Migration implementation:

  • Moved from server/strategy to serverapp/strategy
  • Replaced FitIns/FitRes with Message abstraction (Iterable[Message])
  • Use ArrayRecord/MetricRecord instead of Parameters/Metrics
  • Updated aggregate_train/aggregate_evaluate signatures for Message API
  • Wrapped scipy import in try/except with HAS_SCIPY flag (lines 31-37)
  • Added ImportError in init with installation instructions (lines 133-137)
  • Migrated all unit tests to new API

Performance optimization:
During migration testing, discovered critical bottleneck in _compute_skewness
that made threshold > 0 functionality impractical:

  • Sample max 100 weight positions instead of testing all positions
  • Reduces K-S test complexity from O(n_parameters * 100) to O(100 * 100)
  • Enables practical use of adaptive FedAvg/FFT switching
  • Threshold=0.5 now completes in ~97s vs hanging indefinitely

Scipy dependency handling:
Import wrapped in try/except block with HAS_SCIPY flag. Strategy init
raises ImportError with clear message if scipy not installed, directing
users to install scipy>=1.7.0.

Files changed:

  • framework/py/flwr/serverapp/strategy/fedrdf.py (new, migrated + optimized)
  • framework/py/flwr/serverapp/strategy/fedrdf_test.py (new, migrated)
  • framework/py/flwr/serverapp/strategy/init.py (add FedRDF export)
  • framework/py/flwr/server/strategy/init.py (remove old export)
  • framework/py/flwr/server/strategy/fedrdf.py (deleted)
  • framework/py/flwr/server/strategy/fedrdf_test.py (deleted)

Testing:

  • All unit tests passing in new location
  • Threshold functionality verified working (0.0, 0.5, 1.0 tested)
  • ImportError raised correctly when scipy not available

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Contributor Used to determine what PRs (mainly) come from external contributors.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for dynamic robust aggregation using spectral similarity (FedRDF)

3 participants