https://medium.com/pytorch/differential-privacy-series-part-1-dp-sgd-algorithm-explained-12512c3959a3
https://medium.com/pytorch/differential-privacy-series-part-1-dp-sgd-algorithm-explained-12512c3959a3

Эта статья носит прикладное значение и не объясняет все подробности дифференциальной приватности. Цель статьи - познакомить читателя с библиотекой Opacus и показать, как изменять классификатор без потерь в эффективности обучения. 

Анонимизация не всегда эффективна

Приватность - сложная вещь.

Как показала практика Netflix в соревновании Netflix Prize простой анонимизации набора данных недостаточно. 

https://paulisageek.com/imdb-250-netflix/
https://paulisageek.com/imdb-250-netflix/

Netflix анонимизировала свои данные с помощью удаления всех персональных данных, заменив их случайными данными. Этот метод оказался не эффективным и персональные данные пользователей смогли восстановить, объединив исходный набор данных с данными IMDb, в котором содержались имена пользователей.  

Strava также открыла миру, что удаление имен пользователей отнюдь не обеспечивает анонимность данных. Запустив сервис по сбору данных для отображения активности спортсменов на карте по всему миру, оказалось, что скомпрометировано расположение военной базы в Австралии. 

Секретная база в Австралии была обнаружена по тепловым картам движения персонала
https://www.dailymail.co.uk/news/article-5324121/Strava-data-reveals-secret-Australian-base-Pine-Gap.html
Секретная база в Австралии была обнаружена по тепловым картам движения персонала https://www.dailymail.co.uk/news/article-5324121/Strava-data-reveals-secret-Australian-base-Pine-Gap.html

 Таким образом, игнорирование приватности данных может серьезно обернуться. Значит появляется проблематика вида: получить тренд среди группы, и отбросить индивидуальный тренд в частности. Это и есть ключевая идея термина дифференциальная приватность. 

Неформальное объяснение дифференциальной приватности

Обещание дифференциальной приватности (точнее, ε-дифференциальная приватность) — заключается в том, чтобы предоставить измеряемый способ обеспечения баланса между приватностью и точностью модели при выкладывании в публичный доступ агрегированных данных. 
 
Допустим, у вас есть ползунок настройки: 
Уводите его влево — сохраняете полную приватность людей, чьи данные попали в датасет, но при этом добавляете в информацию большое количество шума, снижая точность совокупной статистики; 

Уводите вправо — получаете идеальную точность совокупной статистики, но раскрываете приватную информацию о людях из датасета. 

ε обозначают потерю конфиденциальности
https://cltc.berkeley.edu/2020/08/11/new-video-on-differential-privacy-what-so-what-now-what/
ε обозначают потерю конфиденциальности https://cltc.berkeley.edu/2020/08/11/new-video-on-differential-privacy-what-so-what-now-what/


Суть в том, что ползунок можно переводить в любую точку шкалы, подбирая баланс под конкретный сценарий использования. 

Как использовать библиотеку Opacus 

Opacus — это библиотека, которая позволяет обучать модели PyTorch с различным уровнем приватности. Она поддерживает обучение с минимальными изменениями кода, практически не влияет на производительность обучения и позволяет отслеживать в режиме онлайн бюджет конфиденциальности. 

Учитывая, что мы рассматриваем дифференциальную приватность как черный ящик и говорим лишь о том, что на входе и на выходе, может показаться, что изменения в коде будут весьма значительны. Это не так. 

Оказывается, это просто замена стандартного оптимизатора в вашей нейронной сети, на дифференциально приватный.  

Итак, разберем, как использовать библиотеку, на примере обучения модели классификации PyTorch набору MNIST с использованием DP-SGD

Шаг 1: Импорт PyTorch и Opacus 
Шаг 2: Загрузка данных MNIST 
Шаг 3: Создание модели классификации PyTorch и оптимизатора 
Шаг 4: Подключение механизма дифференциальной приватности к оптимизатору 
Шаг 5: Обучение модели 

 Нам потребуется: 

1. Иметь базовые знания обучения моделей в PyTorch 
2. Установить PyTorch 
3. Установить библиотеку PyTorch Opacus 

Шаг 1: Импорт PyTorch и Opacus 

 Для классификации изображений в MNIST нам потребуется использовать PyTorch, numpy, и Opacus. Также потребуется tqdm, чтобы визуализировать процесс. 

import torch  

from torchvision import datasets, transforms 

import numpy as np 

from opacus import PrivacyEngine 

from tqdm import tqdm 

Шаг 2: Загрузка данных MNIST 

 Загружаем данные MNIST с помощью DataLoader’а и разделяем их на наборы данных для обучения и тестирования. Данные перемешиваются и нормализуются с использованием среднего значения (0,1307) и стандартного отклонения (0,3081). Обучающий набор разделен на пакеты по 64 изображения в каждом, в то время как тестовый набор разделен на пакеты по 1024 изображения в каждом. 

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=64, 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=1024, shuffle=True, num_workers=1, 
pin_memory=True)
 

Шаг 3: Создание модели классификатора 

 Теперь создадим последовательную модель PyTorch, которая классифицирует изображения из набора данных MNIST. Мы создаем простую сеть, состоящую из 2 сверточных слоев, за которыми следуют 2 полносвязных слоя (стандартный классификатор) связанных с ReLu слоями. Первый слой принимает изображения определенного размера (28 х 28) в качестве входных данных. Последний слой возвращает вектор размера 1 х 10 (чтобы можно было предсказать какая цифра от 1 до 9 на изображении). В качестве оптимизатора используется SGD, скорость обучения 0,05.  

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))
 

 optimizer = torch.optim.SGD(model.parameters(), lr=0.05) 

Шаг 4. Подключение механизма дифференциальной приватности к оптимизатору 

Пока что у нас создана обычная модель классификации PyTorch. Теперь необходимо сделать её дифференциально приватной. Для этого используем PrivacyEngine из библиотеки Opacus.  

privacy_engine = PrivacyEngine(model,  

batch_size = 64,  

sample_size = 60000,  

alphas = range(2,32),  

noise_multiplier = 1.3,  

max_grad_norm = 1.0,) 

privacy_engine.attach(optimizer) 

sample_size - размер обучающей выборки 

alphas - порядок ограничения потерь приватности 

noise_multiplier - размер стандартного отклонения распределения Гауссова шума 

max_grad_norm- верхняя граница градиента потерь 

Шаг 5: Обучение модели 

Наконец, мы создаем функцию для обучения модели с использованием дифференциально частного оптимизатора SGD. Мы хотим свести к минимуму потери перекрестной энтропии. 

В рамках одного этапа обучения мы проходим весь тренировочный набор данных и просим нашу модель предсказывать метку данных. Основываясь на этом предсказании, мы получаем потерю, градиенты которой мы используем для обратного распространения loss.backward(). 

Градиент, распространяющихся в обратном направлении данных, обрезается до max_grad_norm. Это делается для обеспечения того, чтобы не превысить порог приватности и, тем самым, снизить точность модели.

После этого градиенты для пакета данных усредняются, и к добавляется случайно отобранный гауссовский шум на основе значения noise_multiplier. Это делается для обеспечения того, чтобы итоговая модель удовлетворяла гарантии дифференциальной приватности.  

def train(model, train_loader, optimizer, 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) 
optimizer.zero_grad() 
output = model(data) 
loss = criterion(output, target) 
loss.backward() 
optimizer.step() 
losses.append(loss.item()) 
 
epsilon, best_alpha =  
optimizer.privacy_engine.get_privacy_spent(delta) 
 
print( 
f"Train Epoch: {epoch} \t" 
f"Loss: {np.mean(losses):.6f} " 
f"(ε = {epsilon:.2f}, δ = {delta}) for α = {best_alpha}") 
 
for epoch in range(1, 11): 
train(model, train_loader, optimizer, epoch, device="cpu", delta=1e-5)
 

Параметры epsilon и delta помогают нам определить форму и размер распределения гауссовского шума. Вместе значения epsilon, delta и α дают нам количественную оценку дифференциальной приватности и показывают (или бюджета конфиденциальности, который мы потратили).

Вот так лакончино Opacus позволяет добавить поддержку дифференциальной приватности в модель PyTorch. При этом процесс создания модели не изменяется.

Итоговый код

Источники:

Opacus tutorials

Introducing Opacus, by Facebook AI

Дифференциальная приватность, статья от VK

DP-SGD разбор алгоритма 

Статья на towards DS

Комментарии (0)