FedAvg with PyTorch state_dicts
Intuition
After a round of local training, each client has slightly different weights. FedAvg combines them into the next global model by averaging each parameter, giving clients with more data more say — exactly the weighted average of FL-02, now applied tensor by tensor to a state dict.
Precise explanation
total = sum(counts)
averaged = {k: sum(state[k] * (n / total) for state, n in zip(states, counts)) for k in states[0]}
model.load_state_dict(averaged)
- All clients must share one architecture, so their state dicts have the same keys and shapes.
- Floating-point tensors are averaged. Integer buffers — for example BatchNorm's
num_batches_tracked— cannot be averaged meaningfully; copy them from the first client. - A round: send the global model to every client (FL-05), collect
(state_dict, n), average, load into the global model. Repeat for several rounds. - With non-IID clients (FL-04) local models drift apart; more rounds with fewer local epochs, or FedProx (FL-14), help.
Worked example
Two clients with 30 and 10 examples and weights w = 1.0 and 2.0 give 0.75·1.0 + 0.25·2.0 = 1.25.
Common mistakes
- Averaging without weights when client sizes differ.
- Averaging
num_batches_trackedand getting a float or a type error. - Reusing the same seed for every client, so all shuffles are identical.
Why this matters
This is the algorithm behind federated keyboards and hospital collaborations; frameworks such as Flower implement the same loop across real devices. The project idea after this step simulates departments.
References
- Saving and Loading Models (PyTorch tutorial) — PyTorch (
S108) - PyTorch Quickstart tutorial — PyTorch (
S039)