MEDfl 2.0.10.dev7__tar.gz → 2.0.10.dev9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/xgboost/server.py +1 -1
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/client.py +46 -0
- medfl-2.0.10.dev9/MEDfl/rw/holdout.py +864 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/server.py +37 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/strategy.py +39 -6
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/xgboost/client.py +62 -1
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/xgboost/strategy.py +46 -9
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/PKG-INFO +1 -1
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/medfl.egg-info/PKG-INFO +1 -1
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/medfl.egg-info/SOURCES.txt +3 -1
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/setup.py +1 -1
- medfl-2.0.10.dev9/tests/test_rw_holdout.py +171 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/LICENSE +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/client.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/dynamicModal.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/federated_dataset.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/flpipeline.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/model.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/params.yaml +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/params_optimiser.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/plot.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/server.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/shap/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/shap/aggregation.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/shap/config.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/shap/explainer.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/shap/xgboost_explainer.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/strategy.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/utils.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/xgboost/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/xgboost/client.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/xgboost/config.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/xgboost/data.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/xgboost/metrics.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/xgboost/serialization.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/LearningManager/xgboost/strategy.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/NetManager/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/NetManager/database_connector.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/NetManager/dataset.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/NetManager/flsetup.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/NetManager/net_helper.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/NetManager/net_manager_queries.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/NetManager/network.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/NetManager/node.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/model.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/xgboost/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/xgboost/config.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/xgboost/data.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/xgboost/metrics.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/rw/xgboost/serialization.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/scripts/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/scripts/base.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/MEDfl/scripts/create_db.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/README.md +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/alembic/__init__.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/alembic/env.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/medfl.egg-info/dependency_links.txt +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/medfl.egg-info/requires.txt +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/medfl.egg-info/top_level.txt +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/setup.cfg +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/tests/test_dataset.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/tests/test_federated_dataset.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/tests/test_flpipeline.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/tests/test_flsetup.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/tests/test_network.py +0 -0
- {medfl-2.0.10.dev7 → medfl-2.0.10.dev9}/tests/test_node.py +0 -0
|
@@ -12,6 +12,7 @@ from sklearn.metrics import accuracy_score, roc_auc_score
|
|
|
12
12
|
from sklearn.model_selection import train_test_split
|
|
13
13
|
from MEDfl.rw.model import Net # votre définition de modèle
|
|
14
14
|
from MEDfl.LearningManager.shap import LocalPyTorchSHAPExplainer
|
|
15
|
+
from MEDfl.rw.holdout import run_local_holdout
|
|
15
16
|
import socket
|
|
16
17
|
import platform
|
|
17
18
|
import psutil
|
|
@@ -77,6 +78,10 @@ class FlowerClient(fl.client.NumPyClient):
|
|
|
77
78
|
Comma-separated list of IDs (or line numbers) to use as test set.
|
|
78
79
|
seed : int, optional
|
|
79
80
|
Random seed used for splits. Default is ``42``.
|
|
81
|
+
holdout_path : str, optional
|
|
82
|
+
Path to a local holdout CSV, never used for training. When the server
|
|
83
|
+
enables the federated holdout test, the final global model is tested
|
|
84
|
+
on it after the last round. Default is ``None`` (no holdout).
|
|
80
85
|
"""
|
|
81
86
|
def __init__(
|
|
82
87
|
self,
|
|
@@ -89,6 +94,7 @@ class FlowerClient(fl.client.NumPyClient):
|
|
|
89
94
|
id_col=None,
|
|
90
95
|
test_ids=None,
|
|
91
96
|
seed=42,
|
|
97
|
+
holdout_path=None,
|
|
92
98
|
):
|
|
93
99
|
self.server_address = server_address
|
|
94
100
|
self.dp_config = dp_config
|
|
@@ -97,6 +103,8 @@ class FlowerClient(fl.client.NumPyClient):
|
|
|
97
103
|
self.id_col = id_col
|
|
98
104
|
self.test_ids = test_ids
|
|
99
105
|
self.seed = seed
|
|
106
|
+
# read only when the server asks for the holdout test (features/target come from the server)
|
|
107
|
+
self.holdout_path = holdout_path
|
|
100
108
|
|
|
101
109
|
# Load the CSV once; actual column selection happens on first fit using server config
|
|
102
110
|
self._df = pd.read_csv(data_path)
|
|
@@ -585,10 +593,48 @@ class FlowerClient(fl.client.NumPyClient):
|
|
|
585
593
|
flush=True,
|
|
586
594
|
)
|
|
587
595
|
|
|
596
|
+
# ---------------------------------------------------------------
|
|
597
|
+
# Final-round federated holdout test
|
|
598
|
+
#
|
|
599
|
+
# Same final global parameters as SHAP above, tested on the local
|
|
600
|
+
# holdout file. Rows with missing feature values are dropped since
|
|
601
|
+
# the network cannot predict them.
|
|
602
|
+
# ---------------------------------------------------------------
|
|
603
|
+
if bool(config.get("holdout_enabled", False)):
|
|
604
|
+
metrics.update(
|
|
605
|
+
run_local_holdout(
|
|
606
|
+
config=config,
|
|
607
|
+
holdout_path=self.holdout_path,
|
|
608
|
+
features=self.effective_features,
|
|
609
|
+
target=self.effective_target,
|
|
610
|
+
predict=self._predict_probabilities,
|
|
611
|
+
client_id=socket.gethostname(),
|
|
612
|
+
drop_missing_features=True,
|
|
613
|
+
validation=self._validation_predictions,
|
|
614
|
+
)
|
|
615
|
+
)
|
|
616
|
+
|
|
588
617
|
print(f"Evaluation metrics: {metrics}")
|
|
589
618
|
|
|
590
619
|
return float(avg_loss), len(self.test_loader.dataset), metrics
|
|
591
620
|
|
|
621
|
+
def _predict_probabilities(self, X):
|
|
622
|
+
"""Positive-class probabilities of the current model for a feature array."""
|
|
623
|
+
self.model.eval()
|
|
624
|
+
with torch.no_grad():
|
|
625
|
+
logits = self.model(torch.tensor(X, dtype=torch.float32))
|
|
626
|
+
return torch.sigmoid(logits.reshape(-1)).cpu().numpy()
|
|
627
|
+
|
|
628
|
+
def _validation_predictions(self):
|
|
629
|
+
"""(y_true, y_prob) of the validation split, for the optimized holdout threshold."""
|
|
630
|
+
if self.val_loader is None:
|
|
631
|
+
return np.empty((0,)), np.empty((0,))
|
|
632
|
+
y_parts, prob_parts = [], []
|
|
633
|
+
for X_batch, y_batch in self.val_loader:
|
|
634
|
+
y_parts.append(y_batch.cpu().numpy().reshape(-1))
|
|
635
|
+
prob_parts.append(self._predict_probabilities(X_batch.cpu().numpy()))
|
|
636
|
+
return np.concatenate(y_parts), np.concatenate(prob_parts)
|
|
637
|
+
|
|
592
638
|
def get_properties(self, config):
|
|
593
639
|
hostname = socket.gethostname()
|
|
594
640
|
os_type = platform.system()
|