%config InlineBackend.figure_formats = ['svg']
# Page-only setting: show every worker's log lines
# (Ray deduplicates identical lines across workers by default).
import os
os.environ["RAY_DEDUP_LOGS"] = "0"
"""
Utility functions and classes for Jupyter Notebooks lessons.
"""
from collections import OrderedDict
import logging
from logging import INFO
import warnings
from flwr.common import ndarrays_to_parameters, Context
from flwr.server import ServerAppComponents
from flwr.client import Client, ClientApp, NumPyClient
from flwr.common.logger import (
ConsoleHandler,
console_handler,
FLOWER_LOGGER,
LOG_COLORS,
)
from logging import LogRecord
from flwr.server import ServerApp, ServerConfig
from flwr.simulation import run_simulation
from flwr_datasets import FederatedDataset
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import Compose, Normalize, ToTensor
# Customize logging for the course.
class InfoFilter(logging.Filter):
def filter(self, record):
return record.levelno == INFO
FLOWER_LOGGER.removeHandler(console_handler)
warnings.filterwarnings("ignore")
# To filter logging coming from the Simulation Engine
# so it is more readable in notebooks
from logging import ERROR
backend_setup = {"init_args": {"logging_level": ERROR, "log_to_driver": True}}
class ConsoleHandlerV2(ConsoleHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def format(self, record: LogRecord) -> str:
"""Format function that adds colors to log level."""
if self.json:
log_fmt = "{lvl='%(levelname)s', time='%(asctime)s', msg='%(message)s'}"
else:
log_fmt = (
f"{LOG_COLORS[record.levelname] if self.colored else ''}"
f"%(levelname)s {'%(asctime)s' if self.timestamps else ''}"
f"{LOG_COLORS['RESET'] if self.colored else ''}"
f": %(message)s"
)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
console_handlerv2 = ConsoleHandlerV2(
timestamps=False,
json=False,
colored=True,
)
console_handlerv2.setLevel(INFO)
console_handlerv2.addFilter(InfoFilter())
FLOWER_LOGGER.addHandler(console_handlerv2)
# Route Flower logs to stdout so they render on this page.
import sys
console_handlerv2.setStream(sys.stdout)
DEVICE = torch.device("cpu")
transforms = Compose([ToTensor(), Normalize((0.5,), (0.5,))])
def normalize(batch):
batch["image"] = [transforms(img) for img in batch["image"]]
return batch
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.fc = nn.Linear(784, 128)
self.relu = nn.ReLU()
self.out = nn.Linear(128, 10)
def forward(self, x):
x = torch.flatten(x, 1)
x = self.fc(x)
x = self.relu(x)
x = self.out(x)
return x
def train_model(net, trainloader, epochs: int = 1):
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters())
net.train()
for _ in range(epochs):
for batch in trainloader:
images = batch["image"].to(DEVICE)
labels = batch["label"].to(DEVICE)
optimizer.zero_grad()
loss = criterion(net(images), labels)
loss.backward()
optimizer.step()
def evaluate_model(net, testloader):
net.to(DEVICE)
criterion = torch.nn.CrossEntropyLoss()
correct, loss = 0, 0.0
with torch.no_grad():
for batch in testloader:
images = batch["image"].to(DEVICE)
labels = batch["label"].to(DEVICE)
outputs = net(images.to(DEVICE))
labels = labels.to(DEVICE)
# criterion returns the MEAN loss over the batch, so multiply by
# the batch size to accumulate a total and divide by the dataset
# size at the end. Summing the batch means would give a number that
# grows with the number of batches instead of a per-example loss.
loss += criterion(outputs, labels).item() * labels.size(0)
correct += (
(torch.max(outputs.data, 1)[1] == labels).sum().item()
)
accuracy = correct / len(testloader.dataset)
loss = loss / len(testloader.dataset)
return float(loss), float(accuracy)
def set_weights(net, parameters):
params_dict = zip(net.state_dict().keys(), parameters)
state_dict = OrderedDict(
{k: torch.tensor(v) for k, v in params_dict}
)
net.load_state_dict(state_dict, strict=True)
def get_weights(net):
ndarrays = [
val.cpu().numpy() for _, val in net.state_dict().items()
]
return ndarraysData Privacy in Federated Learning
This page is about data privacy and privacy enhancing technologies, PETs for short. It builds some intuition for how to think about PETs in the context of federated learning, and then dives into differential privacy as the worked example, including how it is applied in a Flower system.
Privacy Lens on Federated Learning
Looking at federated learning through the lens of privacy, federated learning itself serves as a data minimization solution. It prevents direct access to data, since raw data never leaves its owner. However, the model updates exchanged between clients and server can still potentially leak private information. Federated learning by itself does not guarantee data privacy.
Privacy Attacks
Depending on the attack model and on the adversary’s role in the federation, various privacy attacks can be constructed. The adversary can be a client, the server, or a third party. Three examples show what an attacker might attempt.
- A membership inference attack aims to infer whether specific data samples participated in training.
- An attribute inference attack aims to infer unseen attributes of the training data.
- A reconstruction attack aims to recover specific training data samples.
A fourth threat is worth separating out, because it inverts the direction of the problem. The three above are attacks on privacy, where an adversary tries to learn something. A poisoning attack is an attack on integrity, where a malicious client submits deliberately crafted updates to degrade the global model or plant a backdoor. Federated learning is unusually exposed to it, since the server cannot inspect client data and therefore cannot easily distinguish a client with unusual data from a client that is lying. Data heterogeneity makes the defense harder still.
Reconstruction is not hypothetical. Researchers have shown in a paper how, in one particular setting, a malicious server was able to reconstruct training data samples of a specific client in federated learning. The reconstructed images were not exactly identical to the originals, but their quality was surprisingly close to the original data. Updates leak.
Privacy Enhancing Technologies
Because federated learning alone does not close these gaps, federated systems layer privacy enhancing technologies on top of it. Two of them come up most often. Differential privacy bounds and obscures the contribution of any single data point, and it is the technology the rest of this page develops. Secure aggregation takes a different route. Clients mask their updates before sending them, the masks cancel out when the updates are summed, and the server ends up with the aggregate without ever being able to read an individual update.
The two address different weaknesses, which is why they are often deployed together. Secure aggregation hides individual updates from the server, while differential privacy limits what the aggregate itself can reveal.
Secure aggregation is worth naming properly, because the idea underneath it is older and more general than federated learning. It is an application of secure multiparty computation, usually shortened to SMPC, which is a branch of cryptography concerned with one question. Can several parties jointly compute a function over their private inputs while none of them learns anything about anyone else’s input beyond what the answer itself reveals?
For federated learning the function is a sum, and Bonawitz et al. (2017) worked out how to compute it at scale. The core intuition is pairwise masking. Each pair of clients agrees on a shared random value, one of the pair adds it to its update and the other subtracts it, so the masks cancel exactly once everything is summed. Any individual masked update looks like noise, and only the total is recoverable.
Treat that as the intuition rather than the protocol. Plain pairwise masks cancel only if both members of every pair actually upload, and on mobile devices clients drop out mid-round constantly. The real construction therefore adds a self-mask on top of the pairwise ones and distributes secret shares of both, so that surviving clients can help the server cancel the masks belonging to a dropped participant without ever revealing that participant’s update. A good deal of the engineering goes into that recovery path rather than into the masking.
Two qualifications matter for what the guarantee is worth. It holds against a server that does not collude with clients beyond an assumed threshold, and it protects individuals only when the aggregate covers enough of them. A round that ends up aggregating a single client reveals that client’s update no matter how well the masks worked, which is one reason a minimum cohort size is part of a serious deployment.
Even so, the change in the trust model is real. Without secure aggregation you are trusting the server not to inspect individual updates. With it, and within the assumptions above, the server is cryptographically unable to, which is a much better thing to be able to tell a regulator or a participating hospital.
Review Questions
1. Federated learning already keeps raw data at its owner. What is left to attack?
The model updates. Parameters exchanged between client and server are shaped by the local training data, and attacks on them can infer whether a sample was in the training set (membership inference), infer unseen attributes of the data (attribute inference), or even reconstruct training samples themselves (reconstruction). Federated learning is data minimization, not a privacy guarantee.
1. Who can the adversary be in a federated learning system?
A client, the server, or a third party. The demonstrated reconstruction attack is an example where the server itself was malicious and recovered near-original training images of a specific client from its updates.
1. Differential privacy and secure aggregation are both PETs. What does each one protect?
Secure aggregation protects the individual update. Clients mask their updates so that only the sum can be recovered, so a curious server cannot read what any single client sent, provided the protocol’s assumptions hold. Those assumptions matter. The server must not collude with more clients than the threshold allows, and the aggregate has to cover enough participants, since a round that ends up summing one client’s update reveals it however well the masking worked. Differential privacy protects against what the result itself reveals, by clipping and adding noise so that the presence or absence of any single data point does not measurably change the model. They cover different weaknesses, so they are often used together.
Differential Privacy
Differential privacy, DP for short, is a prominent solution for enhancing the privacy of individuals during data analysis. It obscures individual data by adding calibrated noise to query results, which ensures that the presence or absence of any single data point does not significantly impact the outcome of the analysis. The analysis stays accurate overall without compromising sensitive information about any individual.
Say you have two datasets \(D\) and \(D'\) that differ in only one data point, Alice’s. Differential privacy guarantees that any analysis \(M\), such as calculating the average income, will produce nearly identical results on both datasets. The output \(O\) computed on \(D\) and the output \(O'\) computed on \(D'\) would be similar.
The force of the guarantee is in what the picture does not show. Nothing about the two outputs tells you which dataset produced them, so nobody looking at the result can work out whether Alice was in the data at all.
Applied to machine learning, the guarantee reads as follows. Train a model \(M_1\) on dataset \(D\), then add or remove a single data point, such as Alice’s data, and train a second model \(M_2\). Differential privacy guarantees that \(M_1\) and \(M_2\) will be indistinguishable to a certain degree, and that degree is quantified by the level of privacy protection you aim to achieve.
Compare this picture with the previous one and one thing has changed. The analysis in the middle is no longer a query returning a number, it is the training run itself, and what comes out on the right is a model rather than a statistic. That is what makes the guarantee useful here. A trained model is handed around, evaluated, and sometimes published, so the question of what it reveals about any single training example is a question about an artifact that leaves the building. The degree to which \(M_1\) and \(M_2\) stay indistinguishable is the level of privacy protection you chose, and the two operations below are how that level is bought.
Two operations make this work in practice.
- Clipping bounds the sensitivity and mitigates the impact of outliers. Sensitivity here means the maximum amount the output can change when a single data point is added to or removed from the dataset.
- Noising adds calibrated noise to make the output statistically indistinguishable.
Central and Local Differential Privacy
In the context of federated learning, DP can be applied at various stages of the process, during model training, during aggregation of model updates, and during communication between clients and the server. Depending on where it is applied, it provides different levels of privacy. Two variants matter here.
In central differential privacy, the central server is responsible for adding noise to the globally aggregated parameters. The overall approach is to clip the model updates sent by the clients and then add some amount of noise to the aggregated model. Note that trust in the server is required, since the server sees the un-noised updates.
In local differential privacy, each client is responsible for performing DP itself. Each client clips and adds noise locally, before sending its updated model to the server. This avoids the need for a fully trusted aggregator.
Review Questions
1. State the differential privacy guarantee for two models trained on datasets differing in one person’s data.
If \(M_1\) is trained on \(D\) and \(M_2\) on \(D'\), where the two datasets differ only in that one data point, the resulting models are indistinguishable up to a chosen degree. The degree of indistinguishability quantifies the level of privacy protection, and it means no analysis of the model can confidently reveal whether that person’s data was used.
1. What roles do clipping and noising each play in differential privacy?
Clipping bounds the sensitivity, the maximum amount the output can change when a single data point is added or removed, and thereby limits the influence of outliers. Noising then adds calibrated noise sized to that bounded sensitivity, making outputs statistically indistinguishable. Clipping without noise proves nothing, and noise without clipping cannot be calibrated.
1. Central DP versus local DP. Who adds the noise, and what does the choice imply about trust?
In central DP the server adds noise to the aggregated model after clipping the client updates, which requires trusting the server, because it handles un-noised updates. In local DP each client clips and noises its own update before sending it, so no fully trusted aggregator is needed.
Lab: Differential Privacy in Flower
A central DP setup with client side adaptive clipping combines a server side strategy with a client side modifier.
Everything this lab needs, next to your notebook.
- utils4.py (4 KB), the helper file with the model, training loop, weight exchange functions, and logging setup
- requirements.txt (1 KB), the package versions the course shipped
The MNIST dataset for this lab is fetched automatically by Flower Datasets from Hugging Face on first use, so there is nothing to download by hand.
The course pinned Flower 1.10 and an older Hugging Face datasets release. This page runs on Flower 1.33 with current releases. Three things changed (updated 2026-08-31).
- The dataset id is namespaced. The Hub now requires
ylecun/mnistrather than the baremnistthe course used. - The example counts returned to Flower were corrected. The course returns
len(self.trainloader)andlen(self.testloader), which are batch counts. Flower weights each client’s contribution by this number when it averages, so it has to be the number of examples, and the page returnslen(loader.dataset). - The evaluation loss is now a per-example mean. The course sums the per-batch mean losses without dividing, which produces a number that grows with the batch count rather than a comparable loss. This changes the reported distributed loss.
The differential-privacy setup, the adaptive clipping mod, the noise multiplier, the model and the five-round run are the course’s own.
The helper file is nearly identical to the one from the tuning lab, with the same SimpleModel, epoch-aware train_model, evaluate_model, normalize, and the set_weights and get_weights pair.
Client Side with a Mod
Two imports carry the DP machinery, the client side clipping mod and the server side DP wrapper strategy.
from flwr.client.mod import adaptiveclipping_mod
from flwr.server.strategy import (
DifferentialPrivacyClientSideAdaptiveClipping,
FedAvg,
)The data loading uses Flower Datasets exactly as in the tuning lab, this time partitioning MNIST into ten partitions.
def load_data(partition_id):
fds = FederatedDataset(dataset="ylecun/mnist", partitioners={"train": 10})
partition = fds.load_partition(partition_id)
traintest = partition.train_test_split(test_size=0.2, seed=42)
traintest = traintest.with_transform(normalize)
trainset, testset = traintest["train"], traintest["test"]
trainloader = DataLoader(trainset, batch_size=64, shuffle=True)
testloader = DataLoader(testset, batch_size=64)
return trainloader, testloaderThe FlowerClient and client_fn are the standard ones, with fit training for the helper’s default of one local epoch.
class FlowerClient(NumPyClient):
def __init__(self, net, trainloader, testloader):
self.net = net
self.trainloader = trainloader
self.testloader = testloader
def fit(self, parameters, config):
set_weights(self.net, parameters)
train_model(self.net, self.trainloader)
# Flower weights each client's update by this number when it averages,
# so it must be the number of EXAMPLES the client trained on. len() on a
# DataLoader returns the number of batches, which would weight a client
# by how its data happens to be batched rather than how much it has.
return get_weights(self.net), len(self.trainloader.dataset), {}
def evaluate(self, parameters, config):
set_weights(self.net, parameters)
loss, accuracy = evaluate_model(self.net, self.testloader)
# Same rule here, the count is examples rather than batches.
return loss, len(self.testloader.dataset), {"accuracy": accuracy}
def client_fn(context: Context) -> Client:
net = SimpleModel()
partition_id = int(context.node_config["partition-id"])
trainloader, testloader = load_data(partition_id=partition_id)
return FlowerClient(net, trainloader, testloader).to_client()The new piece is how the ClientApp is created. Flower supports mods, short for modifiers, which perform operations before and after a task is processed by the ClientApp. There are built-in mods, and custom ones can be defined. Here the built-in adaptiveclipping_mod performs adaptive clipping of the model updates before they are sent back to the server.
It is worth asking why the clipping belongs here, on the client, when the noise is added later on the server. Clipping is what bounds the sensitivity, and an update can only be bounded where it is produced. Be precise about what is bounded, though. adaptiveclipping_mod clips the whole model update a client returns, so it bounds how much one client can move the aggregate. That is client-level (or update-level) privacy. It is not the same as the record-level DP-SGD you may have read about, which clips per-example gradients to bound what a single training row can do. Note also that because the mod runs on the client, the server is trusting client code to apply it. Flower also offers a server-side clipping variant for settings where that trust is not warranted. The noise is a separate job. It is added once to the aggregate rather than once per client, which is exactly what makes this setup central differential privacy, and it is why the accuracy survives better here than it would if every client noised its own update.
client = ClientApp(
client_fn,
mods=[adaptiveclipping_mod], # modifiers
)Server Side with a Wrapper Strategy
On the server side, the federated averaging strategy is created as usual, named fedavg_without_dp, but instead of passing it directly to the ServerApp, it is wrapped in a strategy called DifferentialPrivacyClientSideAdaptiveClipping. The wrapper is a strategy itself. It takes the inner strategy plus two DP specific arguments, the noise multiplier and the number of sampled clients. During each round it receives the model updates, forwards them to the inner strategy for aggregation, and then adds noise to the aggregated model.
Wrapping is the reason this stays simple in code. The same wrapper composes over federated averaging, FedAdam, or any other strategy, and no DP specific version of each one has to exist. The guarantee, however, is not automatic. The noise is calibrated as the clipping norm divided by the number of sampled clients, which is the right sensitivity for a uniform mean. An inner strategy that weights clients unequally, takes a median, or applies a nonlinear server optimizer has a different sensitivity, and the noise would need recalibrating to keep the same guarantee. It also puts the noise exactly where it belongs in the sequence, after aggregation and before the global model goes back out.
net = SimpleModel()
params = ndarrays_to_parameters(get_weights(net))
def server_fn(context: Context):
fedavg_without_dp = FedAvg(
fraction_fit=0.6,
fraction_evaluate=1.0,
initial_parameters=params,
)
fedavg_with_dp = DifferentialPrivacyClientSideAdaptiveClipping(
fedavg_without_dp, # <- wrap the FedAvg strategy
noise_multiplier=0.3,
num_sampled_clients=6,
)
# Five rounds keeps this demonstration quick. A real run would need many
# more rounds to reach useful accuracy under the noise, and each extra round
# spends more of the privacy budget, so the noise would be recalibrated
# against a privacy accountant rather than left as it is here.
config = ServerConfig(num_rounds=5)
return ServerAppComponents(
strategy=fedavg_with_dp,
config=config,
)server = ServerApp(server_fn=server_fn)Running It
The simulation runs with ten clients, and the strategy selects six of them each round, which is what a fraction_fit of 0.6 produces. This is the client selection idea from the previous page in use, and under DP it carries extra weight. The amount of noise needed depends on how many clients contributed to the aggregate, which is why the wrapper was given num_sampled_clients=6 to match. Those two numbers describe the same six clients, so if one is changed the other has to change with it, or the noise no longer matches what it is supposed to be hiding.
run_simulation(server_app=server,
client_app=client,
num_supernodes=10,
backend_config=backend_setup
)INFO : Starting Flower ServerApp, config: num_rounds=5, no round_timeout INFO : INFO : [INIT] INFO : Using initial global parameters provided by strategy INFO : Starting evaluation of initial global parameters INFO : Evaluation returned no results (`None`) INFO : INFO : [ROUND 1] INFO : configure_fit: strategy sampled 6 clients (out of 10)
(ClientAppActor pid=41490) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41492) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41489) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41487) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41494) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41493) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41494) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41494) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_fit: received 6 results and 0 failures INFO : aggregate_fit: central DP noise with 0.0053 stdev added INFO : configure_evaluate: strategy sampled 10 clients (out of 10)
(ClientAppActor pid=41489) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.1000. (ClientAppActor pid=41490) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.1000. (ClientAppActor pid=41494) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.1000. (ClientAppActor pid=41493) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.1000. (ClientAppActor pid=41487) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.1000. (ClientAppActor pid=41492) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.1000. (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41494) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41494) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41488) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41495) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41491) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (ClientAppActor pid=41488) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41488) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41488) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41488) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41495) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41495) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41495) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41495) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_evaluate: received 10 results and 0 failures INFO : INFO : [ROUND 2] INFO : configure_fit: strategy sampled 6 clients (out of 10)
(ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41488) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41488) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41495) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41495) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_fit: received 6 results and 0 failures INFO : aggregate_fit: central DP noise with 0.0047 stdev added INFO : configure_evaluate: strategy sampled 10 clients (out of 10)
(ClientAppActor pid=41488) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0915. (ClientAppActor pid=41491) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0915. (ClientAppActor pid=41492) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0915. (ClientAppActor pid=41489) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0915. (ClientAppActor pid=41490) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0915. (ClientAppActor pid=41495) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0915. (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41488) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41488) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41494) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41494) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41495) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41495) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_evaluate: received 10 results and 0 failures INFO : INFO : [ROUND 3] INFO : configure_fit: strategy sampled 6 clients (out of 10)
(ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41494) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41494) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_fit: received 6 results and 0 failures INFO : aggregate_fit: central DP noise with 0.0042 stdev added INFO : configure_evaluate: strategy sampled 10 clients (out of 10)
(ClientAppActor pid=41489) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0819. (ClientAppActor pid=41490) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0819. (ClientAppActor pid=41494) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0819. (ClientAppActor pid=41493) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0819. (ClientAppActor pid=41491) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0819. (ClientAppActor pid=41492) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0819. (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41488) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41488) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41494) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41494) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41495) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41495) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_evaluate: received 10 results and 0 failures INFO : INFO : [ROUND 4] INFO : configure_fit: strategy sampled 6 clients (out of 10)
(ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_fit: received 6 results and 0 failures INFO : aggregate_fit: central DP noise with 0.0039 stdev added INFO : configure_evaluate: strategy sampled 10 clients (out of 10)
(ClientAppActor pid=41489) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0735. (ClientAppActor pid=41490) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0735. (ClientAppActor pid=41493) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0735. (ClientAppActor pid=41491) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0735. (ClientAppActor pid=41487) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0735. (ClientAppActor pid=41492) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0735. (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41488) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41488) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41494) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41494) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41495) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41495) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_evaluate: received 10 results and 0 failures INFO : INFO : [ROUND 5] INFO : configure_fit: strategy sampled 6 clients (out of 10)
(ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41488) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41488) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41494) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41494) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41495) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41495) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_fit: received 6 results and 0 failures INFO : aggregate_fit: central DP noise with 0.0035 stdev added INFO : configure_evaluate: strategy sampled 10 clients (out of 10)
(ClientAppActor pid=41489) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0669. (ClientAppActor pid=41488) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0669. (ClientAppActor pid=41494) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0669. (ClientAppActor pid=41495) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0669. (ClientAppActor pid=41491) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0669. (ClientAppActor pid=41487) INFO : adaptiveclipping_mod: parameters are clipped by value: 0.0669. (ClientAppActor pid=41488) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41488) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41490) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41490) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41494) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41494) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41495) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41495) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41491) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41491) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41487) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41487) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41492) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41492) obj.co_lnotab, # for < python 3.10 [not counted in args] (ClientAppActor pid=41489) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41489) obj.co_lnotab, # for < python 3.10 [not counted in args]
INFO : aggregate_evaluate: received 10 results and 0 failures INFO : INFO : [SUMMARY] INFO : Run finished 5 round(s) in 22.27s INFO : History (loss, distributed): INFO : round 1: 2.2583573249181113 INFO : round 2: 2.2019069175720216 INFO : round 3: 2.145465254465739 INFO : round 4: 2.1043224751154583 INFO : round 5: 2.065950899283091 INFO :
(ClientAppActor pid=41493) /Users/hossein/Documents/website/.venv/lib/python3.13/site-packages/datasets/utils/_dill.py:385: DeprecationWarning: co_lnotab is deprecated, use co_lines instead. (ClientAppActor pid=41493) obj.co_lnotab, # for < python 3.10 [not counted in args]
After local training, the client side mod clips the parameters, and the logs show lines from adaptiveclipping_mod reporting that the parameters were clipped. The inner strategy aggregates the clipped updates, and the DP wrapper adds central noise, visible in aggregate_fit logs as noise with a certain standard deviation.
One practical note. Because of the clipping and the noise, DP often leads to slower convergence. This demonstration therefore uses a small noise multiplier, which means less privacy, and runs only five rounds to keep the runtime short. A real run would need many more rounds to reach useful accuracy under the noise. Be careful about the direction of that trade, though. Extra rounds do not make a privacy guarantee hold. Each round releases another noised aggregate, so the privacy loss composes and the cumulative budget grows. More rounds buy utility and cost privacy, and keeping a target budget while running longer means turning the noise up, tracked with a privacy accountant. This lab specifies no epsilon, delta, or accountant at all, so it demonstrates the mechanism rather than any particular guarantee. Privacy enhancements come with costs, such as reduced utility and computational overhead, and the noise multiplier and round count are the knobs that trade them off.
Review Questions
1. In the Flower central DP setup, where does clipping happen and where does noising happen?
Clipping happens on the client, performed by the adaptiveclipping_mod before the update is sent. Noising happens on the server, where the DifferentialPrivacyClientSideAdaptiveClipping wrapper adds noise to the model after the inner strategy has aggregated the clipped updates.
1. The DP wrapper strategy contains another strategy. What does each of the two layers do?
The inner strategy, plain federated averaging here, does the actual aggregation of client updates. The wrapper receives the updates first, forwards them to the inner strategy for aggregation, and then applies the DP step, adding calibrated noise to the aggregated model. Wrapping keeps DP composable with any inner aggregation strategy.
1. Why did the DP experiment use a small noise multiplier, and why would a real deployment run many more rounds than this lab’s five?
Clipping and noise slow convergence, so a DP run needs more rounds to reach useful accuracy. The small noise multiplier weakens privacy but keeps the training feasible for a demonstration. The catch is that rounds are not free on the privacy side. Every round publishes another noised aggregate, so the privacy loss accumulates, and running longer at a fixed budget means adding more noise per round. In a real deployment the noise level and round count are chosen together against the desired privacy and utility targets using a privacy accountant.
References
- Bonawitz, K., Ivanov, V., Kreuter, B., Marcedone, A., McMahan, H. B., Patel, S., et al. (2017). Practical secure aggregation for privacy-preserving machine learning. In Proceedings of the 2017 ACM SIGSAC Conference on Computer and Communications Security (pp. 1175-1191). ACM. https://doi.org/10.1145/3133956.3133982