This is the log of my server.py, all of which are 0 results and 2 failures
INFO :
INFO : [ROUND 1]
INFO : configure_fit: strategy sampled 2 clients (out of 2)
INFO : aggregate_fit: received 0 results and 2 failures
[Server] Round 1: 0 results, 2 failures
Round 1 evaluation loss: 2.3127, accuracy: 0.0989
INFO : fit progress: (1, 2.3127286434173584, {‘accuracy’: 0.09888888895511627}, 9.558189600007609)
INFO : configure_evaluate: strategy sampled 2 clients (out of 2)
INFO : aggregate_evaluate: received 0 results and 2 failures
INFO :
INFO : [ROUND 2]
INFO : configure_fit: strategy sampled 2 clients (out of 2)
INFO : aggregate_fit: received 0 results and 2 failures
[Server] Round 2: 0 results, 2 failures
Round 2 evaluation loss: 2.3127, accuracy: 0.0989
INFO : fit progress: (2, 2.3127286434173584, {‘accuracy’: 0.09888888895511627}, 9.695105200007674)
INFO : configure_evaluate: strategy sampled 2 clients (out of 2)
INFO : aggregate_evaluate: received 0 results and 2 failures
INFO :
INFO : [ROUND 3]
INFO : configure_fit: strategy sampled 2 clients (out of 2)
INFO : aggregate_fit: received 0 results and 2 failures
[Server] Round 3: 0 results, 2 failures
Round 3 evaluation loss: 2.3127, accuracy: 0.0989
INFO : fit progress: (3, 2.3127286434173584, {‘accuracy’: 0.09888888895511627}, 9.825406700008898)
INFO : configure_evaluate: strategy sampled 2 clients (out of 2)
INFO : aggregate_evaluate: received 0 results and 2 failures
…
I don’t know where the problem is… This is my server.py
import flwr as fl
import pandas as pd
import numpy as np
from model import dnn_model
from data_process import split_data
from flwr.common import parameters_to_ndarrays, FitIns, EvaluateIns
#split_data()
server_mean = np.load(“server_data/mean.npy”)
server_std = np.load(“server_data/std.npy”)
val_df = pd.read_csv(“server_data/val.csv”)
y_val = val_df[“Label”].values
x_val = val_df.drop(columns=[“Label”]).values.astype(np.float32)
x_val = (x_val - server_mean) / (server_std + 1e-6)
model = dnn_model()
class SaveClientsData(fl.server.strategy.FedAvg):
def init(self, model, val_data, Global_mean, Global_std, **kwargs):
super().init(**kwargs)
self.model = model
self.x_val, self.y_val = val_data
self.global_mean = Global_mean
self.global_std = Global_std
def configure_fit(self, server_round, parameters, client_manager):
config = {
"global_mean": self.global_mean.tolist(),
"global_std": self.global_std.tolist(),
}
allclients = client_manager.sample(
num_clients=self.min_fit_clients, min_num_clients=self.min_fit_clients
)
return [(client, FitIns(parameters, config)) for client in allclients]
def configure_evaluate(self, server_round, parameters, client_manager):
cfg = {
"global_mean": self.global_mean.tolist(),
"global_std": self.global_std.tolist(),
}
allclients = client_manager.sample(
num_clients=self.min_fit_clients, min_num_clients=self.min_fit_clients
)
return [(client, EvaluateIns(parameters, cfg)) for client in allclients]
def aggregate_fit(self, rnd, result, failure):
print(f"[Server] Round {rnd}: {len(result)} results, {len(failure)} failures")
if not result:
return None, {}
acc = []
for _, fit_res in result:
metrics = fit_res.metrics
if metrics and "accuracy" in metrics:
acc.append(metrics["accuracy"])
if acc:
print(f"Round {rnd} accuracies: {acc}")
return super().aggregate_fit(rnd, result, failure)
def evaluate(self, server_rnd, parameters, config=None):
weights = parameters_to_ndarrays(parameters)
self.model.set_weights(weights)
loss, accuracy = self.model.evaluate(x_val, y_val, verbose=0)
print(f"Round {server_rnd} evaluation loss: {loss:.4f}, accuracy: {accuracy:.4f}")
return loss, {"accuracy": accuracy}
print(“[Server] Waiting for clients to connect…”)
fl.server.start_server(
server_address=“0.0.0.0:8080”,
config=fl.server.ServerConfig(num_rounds=10, round_timeout=60),
strategy=SaveClientsData(
model = model,
val_data=(x_val, y_val),
Global_mean=server_mean,
Global_std=server_std,
min_fit_clients = 2,
min_evaluate_clients = 2,
min_available_clients = 2,
fraction_fit=1.0
)
)
And this is my client.py:
import flwr as fl
import pandas as pd
import numpy as np
from model import dnn_model
import argparse
class FlClient(fl.client.NumPyClient):
def init(self , client_num):
self.model = dnn_model()
self.client_num = client_num
self.load_data()
self.is_standardized = False
print(f"[Client {self.client_num}] Samples: {self.x_train.shape}, {self.y_train.shape}")
def load_data(self):
df = pd.read_csv(f'client_data/client_{self.client_num}.csv')
y = df["Label"].values
x = df.drop(columns=["Label", "Split"]).values.astype(np.float32)
is_split = df["Split"].values
self.x_train = x[is_split == "train"]
self.y_train = y[is_split == "train"]
self.x_test = x[is_split == "test"]
self.y_test = y[is_split == "test"]
def standardize(self, server_mean, server_std):
self.x_train = (self.x_train - server_mean) / server_std
self.x_test = (self.x_test - server_mean) / server_std
if np.any(np.isnan(self.x_train)) or np.any(np.isinf(self.x_train)):
print(f"[Client {self.client_num}] Data has NaN or inf after standardization")
self.is_standardized = True
def get_parameters(self, config):
return self.model.get_weights()
def __del__(self):
print(f"[Client {self.client_num}] shutting down")
def fit(self, parameters, config):
try:
print(f"[Client {self.client_num}] fit() triggered.")
print(f"Received parameters: {[w.shape for w in parameters]}")
print(f"Model expects: {[w.shape for w in self.model.get_weights()]}")
if not self.is_standardized:
if "global_mean" in config and "global_std" in config:
server_mean = np.array(config["global_mean"])
server_std = np.array(config["global_std"])
self.standardize(server_mean, server_std)
else:
print(f"[Client {self.client_num}] Missing standardization config.")
self.model.set_weights(parameters)
history = self.model.fit(self.x_train, self.y_train, epochs=10, batch_size=32, verbose=0)
acc = history.history["accuracy"][-1]
return self.model.get_weights(), len(self.x_train), {"accuracy": acc}
except Exception as e:
import traceback
traceback.print_exc()
raise e
def evaluate(self, parameters, config):
if not self.is_standardized:
if "global_mean" in config and "global_std" in config:
server_mean = np.array(config["global_mean"])
server_std = np.array(config["global_std"])
self.standardize(server_mean, server_std)
else:
print(f"[Client {self.client_num}] Missing standardization config. Skipping standardization.")
self.model.set_weights(parameters)
loss, acc = self.model.evaluate(self.x_test, self.y_test, verbose=0)
return loss, len(self.x_test), {"accuracy": acc}
def main():
parser = argparse.ArgumentParser()
parser.add_argument(“–client_num”, type=int, required=True)
args = parser.parse_args()
fl.client.start_numpy_client(
server_address="127.0.0.1:8080",
client=FlClient(args.client_num)
)
if name == “main”:
main()