Skip to content
Open
Show file tree
Hide file tree
Changes from 180 commits
Commits
Show all changes
196 commits
Select commit Hold shift + click to select a range
de8a877
[WIP] Initial Feature Election algorithm version for Nnidia FLARE
christofilojohn Nov 2, 2025
bb3332f
[WIP] Readme mistake
christofilojohn Nov 2, 2025
345f430
Merge branch 'main' into main
christofilojohn Nov 4, 2025
f7ebada
Merge branch 'main' into main
chesterxgchen Nov 5, 2025
973b818
Merge branch 'main' into main
chesterxgchen Nov 6, 2025
9b53aad
Update examples/advanced/feature_election/requirements.txt
christofilojohn Nov 6, 2025
1144051
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Nov 6, 2025
ad4587a
Update nvflare/app_opt/feature_election/README.md
christofilojohn Nov 6, 2025
56a5c91
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Nov 6, 2025
cc50fbb
[WIP] comments cleanup
christofilojohn Nov 6, 2025
de4e8ff
[WIP] Implemented minor changes on imports and removing PPIMBC_Model.…
christofilojohn Nov 6, 2025
e63ab36
[WIP] Clarification, extra variable k - partition index in controller
christofilojohn Nov 6, 2025
cdf7372
[WIP] Another import restructure
christofilojohn Nov 7, 2025
93de00b
Removed redundant components, added apache licence files
christofilojohn Nov 7, 2025
eff32d3
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Nov 7, 2025
5e15d7b
Merge branch 'main' into main
christofilojohn Nov 8, 2025
10a5c26
Update examples/advanced/feature_election/flare_deployment.py
christofilojohn Nov 8, 2025
1adb62a
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Nov 8, 2025
454551c
Update examples/advanced/feature_election/flare_deployment.py
christofilojohn Nov 8, 2025
49ffa97
Pyimpetus cleanup on executor.py
christofilojohn Nov 8, 2025
53015da
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 8, 2025
b8453dd
Remove unused imports, per greptile suggestions
christofilojohn Nov 8, 2025
9b534e1
Minor cleanup, following greptile comments
christofilojohn Nov 8, 2025
f736c22
feature election masks now work with both True/False and 1/0 format, …
christofilojohn Nov 8, 2025
5030be8
comment on feature election global mask process
christofilojohn Nov 8, 2025
1418fd6
Skip PyImpetus test if the dependency is not installed
christofilojohn Nov 8, 2025
7df272f
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Nov 10, 2025
f052099
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Nov 10, 2025
e7e4af1
Executor minor cleanup, with fixed imports
christofilojohn Nov 10, 2025
f184c15
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 10, 2025
aed3826
Update examples/advanced/feature_election/flare_deployment.py
christofilojohn Nov 10, 2025
ac2012f
Update nvflare/app_opt/feature_election/README.md
christofilojohn Nov 10, 2025
ea22b32
moved import to top
christofilojohn Nov 10, 2025
bd0a6d9
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 10, 2025
e8bc20c
Update examples/advanced/feature_election/flare_deployment.py
christofilojohn Nov 10, 2025
07c2e53
Requirements newline
christofilojohn Nov 10, 2025
b8b292c
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 10, 2025
3a0580e
fixed path on README
christofilojohn Nov 10, 2025
60c413b
added empty init file to test folder for proper python packaging
christofilojohn Nov 19, 2025
31f0792
Merge branch 'main' into main
christofilojohn Nov 19, 2025
812a1ae
Moved tests inside feature election package
christofilojohn Nov 19, 2025
a0cc193
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 19, 2025
6223d6f
Update examples/advanced/feature_election/flare_deployment.py
christofilojohn Nov 19, 2025
f93c677
fixed boolean type safety errors, removed redundant installation note…
christofilojohn Nov 19, 2025
6f3de84
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 19, 2025
449a1ea
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Nov 19, 2025
0dace50
cleanup of imports
christofilojohn Nov 19, 2025
f78857c
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 19, 2025
9197f4f
Update examples/advanced/feature_election/flare_deployment.py
christofilojohn Nov 19, 2025
3140b3d
removed empty line
christofilojohn Nov 19, 2025
a464527
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 19, 2025
c2df497
cleanup, removed installation notes which was redundant
christofilojohn Nov 19, 2025
22f2f24
Merge branch 'main' into main
christofilojohn Nov 20, 2025
d00a48d
Merge branch 'main' into main
christofilojohn Nov 20, 2025
c34e384
fixed readme greptile recommendations
christofilojohn Nov 20, 2025
757e7a1
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 20, 2025
3eb7645
Merge branch 'main' into main
christofilojohn Nov 20, 2025
acde3a5
Merge branch 'main' into main
christofilojohn Nov 21, 2025
e86b2a5
Merge branch 'main' into main
christofilojohn Nov 22, 2025
687a253
fixed load_client_data mistake, Improved more accurate README file
christofilojohn Nov 22, 2025
5f5ebcc
changed evaluate_model method to public
christofilojohn Nov 22, 2025
5923d66
Reformatted files based on CONTRIBUTING.md
christofilojohn Nov 22, 2025
984991e
Update examples/advanced/feature_election/flare_deployment.py
christofilojohn Nov 22, 2025
c2a3552
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Nov 22, 2025
74e136b
documentation changes
christofilojohn Nov 22, 2025
b7f9b95
Merge branch 'main' into main
christofilojohn Nov 24, 2025
a208bb3
Merge branch 'main' into main
christofilojohn Nov 24, 2025
24847fa
Merge branch 'main' into main
chesterxgchen Nov 24, 2025
05616fb
cleanup on text, comments, newlines
christofilojohn Nov 24, 2025
1cd10c9
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Nov 24, 2025
1f67a56
Merge branch 'main' into main
christofilojohn Dec 1, 2025
faf9122
New setup based on guidelines, new documentation, tests files where t…
christofilojohn Dec 3, 2025
f01a759
All tests -of feature election- passing, black, isort-check, flake8 f…
christofilojohn Dec 3, 2025
544e084
All tests -of feature election- passing, black, isort-check, flake8 f…
christofilojohn Dec 3, 2025
fd5151e
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Dec 3, 2025
faab2c9
Merge branch 'main' into main
christofilojohn Dec 3, 2025
4a878ab
Update examples/advanced/feature_election/prepare_data.py
christofilojohn Dec 6, 2025
5f66d1d
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Dec 6, 2025
a9a7fab
Update examples/advanced/feature_election/job.py
christofilojohn Dec 6, 2025
a9b6b73
fixed syntax error caused and detected by greptile
christofilojohn Dec 9, 2025
a3feea6
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Dec 9, 2025
c597736
Made perform_feature_selection public
christofilojohn Dec 9, 2025
6545c6f
fixed job error caused by accepting greptile suggestion
christofilojohn Dec 9, 2025
77bd655
added weight check
christofilojohn Dec 9, 2025
cb58bc8
fixed aggregation to be weighted or uniform(unweighted), cleanup
christofilojohn Dec 9, 2025
21da09f
small changes based on the comments
christofilojohn Dec 9, 2025
f8aa068
Merge branch 'main' into main
christofilojohn Dec 9, 2025
39b9e6c
Merge branch 'main' into main
chesterxgchen Dec 11, 2025
3a9e2f1
Tests passing now, ran black, isort, flake8
christofilojohn Dec 11, 2025
30ec62e
Merge branch 'main' into main
christofilojohn Dec 12, 2025
e93465b
Merge branch 'main' into main
christofilojohn Dec 17, 2025
e4b43f3
Merge branch 'main' into main
chesterxgchen Dec 18, 2025
da4b922
implemented recommended changes, fixed pyimpetus test
christofilojohn Dec 18, 2025
97f4a9b
greptile fixes
christofilojohn Dec 18, 2025
7fd2a84
minor fixes, xscaled on fallback, proper runtime error formatting
christofilojohn Dec 18, 2025
dd8ae6d
Merge branch 'main' into main
chesterxgchen Dec 22, 2025
f3c3f7a
Get the number of features from the first response (init as None)
christofilojohn Dec 22, 2025
c3d0c51
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Dec 22, 2025
27be5ea
Merge branch 'main' into main
chesterxgchen Dec 29, 2025
f114b2e
fix suggested by greptile, passing test locally
christofilojohn Dec 31, 2025
19de535
Merge branch 'main' into main
chesterxgchen Jan 5, 2026
3c230f0
Merge branch 'main' into main
chesterxgchen Jan 10, 2026
1abfb49
Update tests/unit_test/app_opt/feature_election/__init__.py
christofilojohn Jan 11, 2026
f0f11e9
Update examples/advanced/feature_election/prepare_data.py
christofilojohn Jan 11, 2026
f51a693
Changes to fix some of the problems reported by gereptile
christofilojohn Jan 11, 2026
9f60109
implemented fallback for stratification edge cases, greptile suggestion
christofilojohn Jan 11, 2026
3a34b95
Merge branch 'main' into main
chesterxgchen Jan 13, 2026
da5c022
Merge branch 'main' into main
chesterxgchen Jan 14, 2026
407149b
Update examples/advanced/feature_election/client.py
christofilojohn Jan 16, 2026
ca20211
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Jan 16, 2026
86cff18
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Jan 16, 2026
4c842bd
Update examples/advanced/feature_election/client.py
christofilojohn Jan 16, 2026
fdfb496
remove greptile repeated comment
christofilojohn Jan 16, 2026
0783a0b
Update examples/advanced/feature_election/prepare_data.py
christofilojohn Jan 16, 2026
a0a08c0
Update nvflare/app_opt/feature_election/feature_election.py
christofilojohn Jan 16, 2026
c521e8e
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Jan 16, 2026
83617f7
black, isort, flake8
christofilojohn Jan 16, 2026
8c67bab
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Jan 16, 2026
37184a4
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Jan 16, 2026
53a0805
Update examples/advanced/feature_election/client.py
christofilojohn Jan 16, 2026
ace7511
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Jan 16, 2026
f9f472f
Update examples/advanced/feature_election/prepare_data.py
christofilojohn Jan 16, 2026
f65ad9e
Merge branch 'main' into main
christofilojohn Jan 16, 2026
10b340c
removed comment
christofilojohn Jan 18, 2026
84e285d
isort, flake
christofilojohn Jan 18, 2026
9841718
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Jan 18, 2026
cfe6c0e
fixed greptile indentation error
christofilojohn Jan 18, 2026
f390823
Merge branch 'main' into main
christofilojohn Jan 20, 2026
f5f22fd
Update examples/advanced/feature_election/client.py
christofilojohn Jan 20, 2026
4a0e62b
Update examples/advanced/feature_election/client.py
christofilojohn Jan 20, 2026
9e0f94e
Update examples/advanced/feature_election/client.py
christofilojohn Jan 20, 2026
4736cbc
Update examples/advanced/feature_election/client.py
christofilojohn Jan 20, 2026
2a0e8fb
Update examples/advanced/feature_election/client.py
christofilojohn Jan 20, 2026
2fad48d
Performance fix, no need to wait 5 seconds
christofilojohn Jan 20, 2026
d0f8b6b
switched to Logreg library with warm start
christofilojohn Jan 20, 2026
74d64b4
Update examples/advanced/feature_election/client.py
christofilojohn Jan 20, 2026
c45244f
add helper function to reduce duplicate code
christofilojohn Jan 20, 2026
6ba0985
Merge branch 'main' into main
chesterxgchen Jan 20, 2026
c3054f1
fixed duplicate code caused by greptile
christofilojohn Jan 20, 2026
6390639
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Jan 20, 2026
ac50839
Merge branch 'main' into main
chesterxgchen Jan 24, 2026
9a231c8
Merge branch 'main' into main
chesterxgchen Jan 31, 2026
efd1c86
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Jan 31, 2026
62e08da
remove quick_eval paraeter
christofilojohn Jan 31, 2026
2663ed7
applied suggestion, wrapped in list
christofilojohn Jan 31, 2026
bbb028d
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Jan 31, 2026
22aa0d1
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Jan 31, 2026
7b66621
cleeanup of logic
christofilojohn Jan 31, 2026
0ce7b8d
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Jan 31, 2026
60858b4
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Jan 31, 2026
eef674c
black, isort formatting
christofilojohn Jan 31, 2026
f999797
copyright 2026, save json data correctly
christofilojohn Jan 31, 2026
8d5b305
Update nvflare/app_opt/feature_election/controller.py
christofilojohn Jan 31, 2026
5e350ec
switched aggregate_selections to public method
christofilojohn Jan 31, 2026
bb28066
change freedom degree threshold
christofilojohn Jan 31, 2026
b6b229b
fix logic based on old greptile correction
christofilojohn Jan 31, 2026
27d7577
numpy arrays are converted to lists before sending via Shareable
christofilojohn Jan 31, 2026
65f82ff
black, isort
christofilojohn Jan 31, 2026
35fce0e
Added warning log and continue for clarity.
christofilojohn Jan 31, 2026
9487a91
Update nvflare/app_opt/feature_election/executor.py
christofilojohn Jan 31, 2026
4dd8528
greptile logical suggestion
christofilojohn Jan 31, 2026
839b3b6
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Jan 31, 2026
fc4efde
multi-class fix for _coef
christofilojohn Jan 31, 2026
3529255
Update examples/advanced/feature_election/client.py
christofilojohn Jan 31, 2026
32452dd
fixed oversight/bug
christofilojohn Jan 31, 2026
86ec33e
added data checks based on greptile suggestions
christofilojohn Jan 31, 2026
0562a57
applied suggested fix
christofilojohn Jan 31, 2026
2ca280a
added suggested validation
christofilojohn Jan 31, 2026
1baf452
isort, black
christofilojohn Jan 31, 2026
d9d0fa6
copyright
christofilojohn Jan 31, 2026
e98c664
Update tests/unit_test/app_opt/feature_election/__init__.py
christofilojohn Jan 31, 2026
602eb6b
2026
christofilojohn Jan 31, 2026
d25fefa
documented binary and multi-class better
christofilojohn Feb 4, 2026
ddd1c23
added constant to remove hardcoded value
christofilojohn Feb 4, 2026
75c76b9
added IEEE citation
christofilojohn Feb 8, 2026
ebff608
Merge branch 'main' into main
christofilojohn Feb 8, 2026
aaebd7e
Merge branch 'main' into main
chesterxgchen Feb 20, 2026
eb27498
Update nvflare/app_opt/feature_election/README.md
christofilojohn Feb 20, 2026
877c3a1
Update nvflare/app_opt/feature_election/README.md
christofilojohn Feb 20, 2026
c427b7a
fix the reported bug, isort, black, flake passed
christofilojohn Feb 20, 2026
8679934
Merge branch 'main' into main
chesterxgchen Mar 13, 2026
6156359
Update examples/advanced/feature_election/prepare_data.py
christofilojohn Mar 13, 2026
0c4c8fb
Fixed the found errors, tests passing
christofilojohn Mar 13, 2026
525e08b
simulate election fixed to match flower implementation, it was evalua…
christofilojohn Mar 13, 2026
ba76410
Update nvflare/app_opt/feature_election/README.md
christofilojohn Mar 13, 2026
a06f4f5
Minor fixes for errors I found locally, to avoid greptile errors
christofilojohn Mar 13, 2026
ec9613f
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Mar 13, 2026
e24cdfe
numpy 2.0 ready code
christofilojohn Mar 13, 2026
1221f29
black fix
christofilojohn Mar 13, 2026
549a65d
Update nvflare/app_opt/feature_election/README.md
christofilojohn Mar 13, 2026
ce1e8bc
serialization fixed - greptile suggestion
christofilojohn Mar 13, 2026
41188db
fix greptile general review issues by changing Pyimpetus handling
christofilojohn Mar 13, 2026
4dd84f2
moved/merged readme as suggested
christofilojohn Mar 13, 2026
2b8dfed
Merge branch 'main' into main
chesterxgchen Mar 13, 2026
b19a911
updated README to better match the new standards
christofilojohn Mar 13, 2026
3d409f8
Merge branch 'main' of https://github.com/christofilojohn/NVFlare
christofilojohn Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions examples/advanced/feature_election/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Feature Election Examples

Examples demonstrating federated feature selection using NVIDIA FLARE.

## Quick Start

Run the synthetic data example with auto-tuning:

```bash
python job.py --num-clients 3 --auto-tune --fs-method mutual_info
```

## Files

| File | Description |
|------|-------------|
| `job.py` | Main entry point - creates and runs FL job |
| `client.py` | Client-side executor with synthetic data loading |
| `server.py` | Server configuration helpers |

## Usage

### Basic Run

```bash
python job.py --num-clients 3 --num-rounds 5
```

### With Auto-tuning

```bash
python job.py --num-clients 3 --auto-tune --tuning-rounds 4
```

### Different Feature Selection Methods

```bash
# Lasso (default)
python job.py --fs-method lasso

# Mutual Information
python job.py --fs-method mutual_info

# Random Forest
python job.py --fs-method random_forest

# Elastic Net
python job.py --fs-method elastic_net
```

### Custom synthetic dataset configuration

```bash
python job.py \
--n-samples 2000 \
--n-features 200 \
--n-informative 40 \
--n-redundant 60 \
--split-strategy dirichlet
```

## Parameters

| Parameter | Default | Description |
|-----------|---------|-------------|
| `--num-clients` | 3 | Number of federated clients |
| `--num-rounds` | 5 | FL training rounds |
| `--freedom-degree` | 0.5 | Feature inclusion threshold (0-1) |
| `--auto-tune` | False | Enable freedom degree optimization |
| `--tuning-rounds` | 4 | Rounds for auto-tuning |
| `--fs-method` | lasso | Feature selection method |
| `--split-strategy` | stratified | Data splitting strategy |
| `--n-samples` | 1000 | Total synthetic samples |
| `--n-features` | 100 | Number of features |
| `--workspace` | /tmp/nvflare/feature_election | Simulator workspace |

## Customization

### Using Your Own Data

Modify `client.py` to load your data instead of synthetic data:

```python
class MyDataExecutor(FeatureElectionExecutor):
def _load_data_if_needed(self, fl_ctx):
if self._data_loaded:
return

# Load your data
X_train, y_train = load_my_data(self.client_id)
self.set_data(X_train, y_train)
self._data_loaded = True
```

### Exporting Job Configuration

```bash
python job.py --export-dir ./exported_jobs
```

This creates FLARE job configs that can be deployed to production.
195 changes: 195 additions & 0 deletions examples/advanced/feature_election/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Client-side script for Feature Election example.

This script demonstrates how to set up client data for the
FeatureElectionExecutor from nvflare.app_opt.feature_election.
"""

import logging
import re
from typing import Optional

from prepare_data import load_client_data

from nvflare.apis.fl_context import FLContext
from nvflare.app_opt.feature_election.executor import FeatureElectionExecutor

logger = logging.getLogger(__name__)


def get_executor(
client_id: int,
num_clients: int,
fs_method: str = "lasso",
eval_metric: str = "f1",
data_root: Optional[str] = None,
split_strategy: str = "stratified",
n_samples: int = 1000,
n_features: int = 100,
n_informative: int = 20,
n_redundant: int = 30,
) -> FeatureElectionExecutor:
"""
Create and configure a FeatureElectionExecutor with data.

Args:
client_id: Client identifier (0 to num_clients-1)
num_clients: Total number of clients
fs_method: Feature selection method
eval_metric: Evaluation metric ('f1' or 'accuracy')
data_root: Optional path to pre-generated data
split_strategy: Data splitting strategy
n_samples: Samples per client for synthetic data
n_features: Number of features
n_informative: Number of informative features
n_redundant: Number of redundant features

Returns:
Configured FeatureElectionExecutor
"""
# Create executor
executor = FeatureElectionExecutor(
fs_method=fs_method,
eval_metric=eval_metric,
task_name="feature_election",
)

# Load data for this client
X_train, y_train, X_val, y_val, feature_names = load_client_data(
client_id=client_id,
num_clients=num_clients,
data_root=data_root,
split_strategy=split_strategy,
n_samples=n_samples,
n_features=n_features,
n_informative=n_informative,
n_redundant=n_redundant,
)

# Set data on executor
executor.set_data(
X_train=X_train,
y_train=y_train,
X_val=X_val,
y_val=y_val,
feature_names=feature_names,
)

logger.info(
f"Client {client_id} executor configured: "
f"{X_train.shape[0]} train, {X_val.shape[0]} val, "
f"{X_train.shape[1]} features, method={fs_method}"
)

return executor


class SyntheticDataExecutor(FeatureElectionExecutor):
"""
FeatureElectionExecutor with built-in synthetic data loading.

This executor automatically loads synthetic data based on
client_id extracted from the FL context.

Args:
fs_method: Feature selection method
eval_metric: Evaluation metric
num_clients: Total number of clients in federation
split_strategy: Data splitting strategy
n_samples: Samples per client
n_features: Number of features
n_informative: Number of informative features
n_redundant: Number of redundant features
n_repeated: Number of repeated features
"""

def __init__(
self,
fs_method: str = "lasso",
eval_metric: str = "f1",
num_clients: int = 3,
split_strategy: str = "stratified",
n_samples: int = 1000,
n_features: int = 100,
n_informative: int = 20,
n_redundant: int = 30,
n_repeated: int = 10,
task_name: str = "feature_election",
):
super().__init__(
fs_method=fs_method,
eval_metric=eval_metric,
task_name=task_name,
)
self.num_clients = num_clients
self.split_strategy = split_strategy
self.n_samples = n_samples
self.n_features = n_features
self.n_informative = n_informative
self.n_redundant = n_redundant
self.n_repeated = n_repeated
self._data_loaded = False

def _load_data_if_needed(self, fl_ctx: FLContext) -> None:
"""Load data based on client identity from FL context."""
if self._data_loaded:
return

# Extract client ID from site name
site_name = fl_ctx.get_identity_name()

try:
if site_name.startswith("site-"):
client_id = int(site_name.split("-")[1]) - 1
else:
match = re.search(r"\d+", site_name)
if match:
client_id = int(match.group()) - 1
else:
client_id = 0

# Validate range
if not (0 <= client_id < self.num_clients):
raise ValueError(
f"Extracted client_id {client_id} from '{site_name}' is out of range [0, {self.num_clients - 1}]"
)

except (ValueError, IndexError) as e:
logger.error(f"Failed to parse client_id from '{site_name}': {e}. Defaulting to client_id=0")
client_id = 0

# Load data using the parsed ID
X_train, y_train, X_val, y_val, feature_names = load_client_data(
client_id=client_id,
num_clients=self.num_clients,
split_strategy=self.split_strategy,
n_samples=self.n_samples,
n_features=self.n_features,
n_informative=self.n_informative,
n_redundant=self.n_redundant,
n_repeated=self.n_repeated,
)

self.set_data(X_train, y_train, X_val, y_val, feature_names)
self._data_loaded = True

logger.info(f"Successfully loaded synthetic data for {site_name} (client_id={client_id})")

def execute(self, task_name, shareable, fl_ctx, abort_signal):
"""Override execute to ensure data is loaded before processing."""
self._load_data_if_needed(fl_ctx)
return super().execute(task_name, shareable, fl_ctx, abort_signal)
Loading
Loading