Hi,
I’m trying to figure out how can I calculate a combined epsilon-delta privacy budget for multiple optimizers when I provide some layer parameters to each optimizer. I tried to hook the same accountant to different optimizers, but I’m confused/not sure if it returns a combined privacy budget for the whole model.
I’m using torch 1.9.0 and opacus 1.0.1
Here is my code:
import torch
from torchvision import datasets, transforms
import numpy as np
from opacus import PrivacyEngine
from tqdm import tqdm
from opacus import GradSampleModule
from opacus.accountants import RDPAccountant
from opacus.optimizers import DPOptimizer
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
train_batch_size = 64
test_batch_size = 128
noise_multiplier = 1.0
train_loader = torch.utils.data.DataLoader(datasets.MNIST('../mnist',
train=True, download=True,
transform=transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,)),]),),
batch_size=train_batch_size, shuffle=True, num_workers=1,
pin_memory=True)
test_loader = torch.utils.data.DataLoader(datasets.MNIST('../mnist',
train=False,
transform=transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,)),]),),
batch_size=test_batch_size, shuffle=True, num_workers=1,
pin_memory=True)
model = torch.nn.Sequential(torch.nn.Conv2d(1, 16, 8, 2, padding=3),
torch.nn.ReLU(),
torch.nn.MaxPool2d(2, 1),
torch.nn.Conv2d(16, 32, 4, 2),
torch.nn.ReLU(),
torch.nn.MaxPool2d(2, 1),
torch.nn.Flatten(),
torch.nn.Linear(32 * 4 * 4, 32),
torch.nn.ReLU(),
torch.nn.Linear(32, 10))
accountant = RDPAccountant()
model = GradSampleModule(model)
model.to(device)
parameters = list(model.parameters())
params1 = parameters[:3]
params2 = parameters[3:]
optimizer1 = torch.optim.SGD(params1, lr=0.05)
optimizer2 = torch.optim.SGD(params2, lr=0.05)
optimizer1 = DPOptimizer(
optimizer=optimizer1,
noise_multiplier=noise_multiplier,
max_grad_norm=1.0,
expected_batch_size=train_batch_size
)
optimizer2 = DPOptimizer(
optimizer=optimizer2,
noise_multiplier=noise_multiplier,
max_grad_norm=1.0,
expected_batch_size=train_batch_size
)
optimizer1.attach_step_hook(
accountant.get_optimizer_hook_fn(
sample_rate=train_batch_size/len(train_loader.dataset)
)
)
optimizer2.attach_step_hook(
accountant.get_optimizer_hook_fn(
sample_rate=train_batch_size/len(train_loader.dataset)
)
)
def train(model, train_loader, optimizer1, optimizer2, epoch, device, delta):
model.train()
criterion = torch.nn.CrossEntropyLoss()
losses = []
for _batch_idx, (data, target) in enumerate(tqdm(train_loader)):
data, target = data.to(device), target.to(device)
optimizer1.zero_grad()
optimizer2.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer1.step()
optimizer2.step()
losses.append(loss.item())
epsilon, best_alpha = accountant.get_privacy_spent(delta=delta)
print(
f"Train Epoch: {epoch} \t"
f"Loss: {np.mean(losses):.6f} "
f"(ε = {epsilon:.2f}, δ = {delta}) for α = {best_alpha}"
)
def test(model, test_loader, device):
criterion = torch.nn.CrossEntropyLoss()
with torch.no_grad():
n_correct = 0
for _batch_idx, (data, target) in enumerate(tqdm(test_loader)):
data, target = data.to(device), target.to(device)
output = model(data)
loss = criterion(output, target)
# loss.backward()
# optimizer.step()
predicted = output.argmax(dim=1, keepdim=True)
n_correct += predicted.eq(target.view_as(predicted)).sum().item()
print(f'Test Acc: {100.0 * n_correct/len(test_loader.dataset)}')
for epoch in range(1, 11):
train(model, train_loader, optimizer1, optimizer2, epoch, device=device, delta=1e-5)
test(model, test_loader, device=device)
Is the privacy budget returned only for the 2nd optimizer or all of them?
Also, AFAIK (correct me if I’m wrong), the paper “Deep Learning with Differential Privacy” defines DP-SGD and accountant only for a single optimizer. How is Opacus able to calculate a single epsilon-delta for multiple optimizers, if it is able to? On which paper is the accountant implementation based?