Advanced

DP-SGD: Differentially Private Training

DP-SGD (Differentially Private Stochastic Gradient Descent) modifies the standard SGD training algorithm to provide formal differential privacy guarantees. It is the most widely used method for training neural networks with privacy.

How DP-SGD Works

DP-SGD modifies standard SGD with two key changes at each training step:

  1. Per-Example Gradient Clipping

    Compute gradients for each example individually, then clip each gradient to a maximum norm C. This bounds the sensitivity - no single example can have an outsized influence on the update.

  2. Noise Addition

    Add calibrated Gaussian noise to the clipped, aggregated gradient before applying the update. The noise scale depends on the clipping norm C, the batch size, and the target privacy budget.

  3. Privacy Accounting

    After each step, track the cumulative privacy loss using a privacy accountant (Rényi DP or PLD-based). Training stops when the privacy budget is exhausted.

Python - DP-SGD Pseudocode
def dp_sgd_step(model, batch, clip_norm, noise_multiplier, lr):
    """One step of DP-SGD training."""

    # 1. Compute per-example gradients
    per_example_grads = []
    for example in batch:
        grad = compute_gradient(model, example)
        per_example_grads.append(grad)

    # 2. Clip each gradient to bound sensitivity
    clipped_grads = []
    for grad in per_example_grads:
        norm = torch.norm(grad)
        clip_factor = min(1.0, clip_norm / norm)
        clipped_grads.append(grad * clip_factor)

    # 3. Aggregate and add noise
    avg_grad = sum(clipped_grads) / len(batch)
    noise_std = clip_norm * noise_multiplier / len(batch)
    noisy_grad = avg_grad + torch.normal(0, noise_std)

    # 4. Update model parameters
    model.parameters -= lr * noisy_grad

Training with Opacus (PyTorch)

Python - Opacus DP-SGD Training
import torch
from opacus import PrivacyEngine

# Standard model, optimizer, dataloader
model = MyModel()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
dataloader = DataLoader(dataset, batch_size=256)

# Attach PrivacyEngine for DP-SGD
privacy_engine = PrivacyEngine()
model, optimizer, dataloader = privacy_engine.make_private_with_epsilon(
    module=model,
    optimizer=optimizer,
    data_loader=dataloader,
    epochs=10,
    target_epsilon=3.0,
    target_delta=1e-5,
    max_grad_norm=1.0,    # Clipping norm C
)

# Train normally - Opacus handles clipping + noise
for epoch in range(10):
    for batch in dataloader:
        optimizer.zero_grad()
        loss = criterion(model(batch[0]), batch[1])
        loss.backward()
        optimizer.step()

    # Check privacy budget spent so far
    epsilon = privacy_engine.get_epsilon(delta=1e-5)
    print(f"Epoch {epoch}: ε = {epsilon:.2f}")

Key Hyperparameters

ParameterEffectGuidance
Clipping norm (C)Bounds per-example gradient influenceToo small = underfitting; too large = more noise needed. Start with median gradient norm.
Noise multiplier (σ)Controls privacy-utility trade-offHigher = more private but noisier gradients. Auto-calibrated by Opacus if target ε is set.
Batch sizeLarger batches improve signal-to-noise ratioUse the largest batch size you can afford. DP-SGD benefits more from large batches than standard SGD.
EpochsMore epochs = more privacy budget spentFewer epochs with larger batches is generally better under DP.
Learning rateStandard training parameterMay need to be higher than usual to compensate for noisy gradients.
Practical tip: DP-SGD training is slower than standard training due to per-example gradient computation. Use Opacus's virtual batches or JAX-based implementations for better performance. Pre-training on public data and fine-tuning with DP-SGD on private data is a proven strategy for maintaining accuracy.

Ready to Go Deeper?

Live instructor-led courses from our partners. Affiliate disclosure.