Privacy-Preserving Distributed Visual Learning
Module: Computer Vision | Difficulty: Premium
Federated Averaging
Differential Privacy
Secure Aggregation
using secret sharing so server never sees individual updates.
| Method | CIFAR-10 | CelebA | Communication | Privacy | |--------|----------|--------|---------------|---------| | FedAvg | 82.5% | 78.2% | High | None | | FedProx | 84.1% | 79.5% | High | None | | DP-FedAvg | 78.3% | 74.1% | High | Epsilon=3 | | FedViT | 89.2% | 85.3% | Medium | Epsilon=8 |
import torch
import torch.nn as nn
class FederatedClient:
def __init__(self, model, dataloader, lr=0.01):
self.model = model
self.dataloader = dataloader
self.optimizer = torch.optim.SGD(
model.parameters(), lr=lr)
def train(self, global_params, num_epochs=5):
self.model.load_state_dict(global_params)
self.model.train()
for epoch in range(num_epochs):
for data, target in self.dataloader:
self.optimizer.zero_grad()
output = self.model(data)
loss = nn.functional.cross_entropy(output, target)
loss.backward()
self.optimizer.step()
return self.model.state_dict()
class SecureAggregator:
def __init__(self, num_clients, threshold):
self.num_clients = num_clients
self.threshold = threshold
def aggregate(self, client_updates):
avg_update = {}
for key in client_updates[0].keys():
stacked = torch.stack([
update[key] for update in client_updates])
avg_update[key] = stacked.mean(dim=0)
return avg_update
class DPClient:
def __init__(self, model, dataloader, epsilon=1.0,
delta=1e-5, max_grad_norm=1.0):
self.model = model
self.dataloader = dataloader
self.epsilon = epsilon
self.delta = delta
self.max_grad_norm = max_grad_norm
def train_private(self, global_params, num_epochs=5):
self.model.load_state_dict(global_params)
for epoch in range(num_epochs):
for data, target in self.dataloader:
self.model.zero_grad()
output = self.model(data)
loss = nn.functional.cross_entropy(output, target)
loss.backward()
self._clip_gradients()
self._add_noise()
return self.model.state_dict()
def _clip_gradients(self):
for param in self.model.parameters():
if param.grad is not None:
param.grad = torch.clamp(
param.grad, -self.max_grad_norm,
self.max_grad_norm)
def _add_noise(self):
for param in self.model.parameters():
if param.grad is not None:
noise = torch.normal(
0, self.max_grad_norm / self.epsilon,
param.grad.shape)
param.grad += noise.to(param.grad.device)
Research Insight: Federated learning for vision has evolved from simple FedAvg to sophisticated methods that handle data heterogeneity, communication constraints, and privacy requirements. The key challenge is non-IID data: when clients have different data distributions, standard averaging can degrade performance. FedProx adds a proximal term to keep client models close to the global model. For privacy, local differential privacy provides strong guarantees but reduces accuracy; secure multi-party computation enables exact aggregation without revealing individual updates, but has higher communication cost.