Opacus库快速上手!使用Opacus库在Mnist数据集实现差分隐私

第一部分:代码实现

(1)基础配置

python:3.8,opacus1.1.1,torch1.12.1

pip install opacus==1.1.1

具体实现方式是参考opacus官网以及(4)的参考文献。

opacus官网为:

GitHub - pytorch/opacus:使用差分隐私训练 PyTorch 模型

(2)完整代码

# -*- coding: utf-8 -*-

# Step 1: 导入必要的库和模块
import torch  # 导入PyTorch深度学习框架
import os  # 导入操作系统模块

# 设置环境变量解决某些系统下的库冲突问题
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
# 从torchvision导入数据集和数据处理工具
from torchvision import datasets, transforms
import numpy as np  # 导入数值计算库
# 从Opacus导入差分隐私引擎
from opacus import PrivacyEngine
# 导入进度条工具
from tqdm import tqdm

# Step 2: 加载MNIST数据集
# 创建训练数据加载器
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST(
        '../mnist',  # 数据集存储路径
        train=True,  # 使用训练集
        download=True,  # 如果不存在则自动下载
        transform=transforms.Compose([  # 数据预处理管道
            transforms.ToTensor(),  # 将PIL图像转换为Tensor
            # 标准化处理(使用MNIST的均值和标准差)
            transforms.Normalize((0.1307,), (0.3081,))
        ]),
    ),
    batch_size=64,  # 每批加载64个样本
    shuffle=True,  # 打乱数据顺序
    num_workers=0,  # 使用0个子进程加载数据
    pin_memory=True  # 将数据缓存在CUDA固定内存中(如果可用)
)

# 创建测试数据加载器(参数与训练集类似)
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=0,
    pin_memory=True
)

# Step 3: 构建神经网络模型和优化器
# 使用Sequential容器构建卷积神经网络
model = torch.nn.Sequential(
    # 第一个卷积层:输入通道1,输出通道16,卷积核8x8,步长2,填充3
    torch.nn.Conv2d(1, 16, 8, 2, padding=3),
    torch.nn.ReLU(),  # ReLU激活函数
    # 最大池化层:窗口大小2x2,步长1
    torch.nn.MaxPool2d(2, 1),
    # 第二个卷积层:输入通道16,输出通道32,卷积核4x4,步长2
    torch.nn.Conv2d(16, 32, 4, 2),
    torch.nn.ReLU(),
    torch.nn.MaxPool2d(2, 1),
    torch.nn.Flatten(),  # 展平多维特征图为一维
    # 全连接层:输入特征数32*4*4,输出32
    torch.nn.Linear(32 * 4 * 4, 32),
    torch.nn.ReLU(),
    # 输出层:输入32,输出10(对应10个数字类别)
    torch.nn.Linear(32, 10)
)

# 创建随机梯度下降优化器,学习率0.05
optimizer = torch.optim.SGD(model.parameters(), lr=0.05)

# Step 4: 添加差分隐私引擎
# 初始化隐私引擎,配置差分隐私参数
privacy_engine = PrivacyEngine()
model, optimizer, train_loader = privacy_engine.make_private(
    module=model,
    optimizer=optimizer,
    data_loader=train_loader,
    noise_multiplier=1.3,  # 高斯噪声的乘数
    max_grad_norm=1.0,  # 梯度裁剪的阈值
)


# Step 5: 定义训练函数
def train(model, train_loader, optimizer, epoch, device, delta):
    model.train()  # 设置模型为训练模式
    criterion = torch.nn.CrossEntropyLoss()  # 定义交叉熵损失函数
    losses = []  # 存储每批损失的列表

    # 使用tqdm包装数据加载器以显示进度条
    for _batch_idx, (data, target) in enumerate(tqdm(train_loader)):
        # 将数据移动到指定设备(CPU/GPU)
        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 = privacy_engine.accountant.get_epsilon(delta)
    # 打印训练结果
    print(
        f"Train Epoch: {epoch} \t"
        f"Loss: {np.mean(losses):.6f} "
        f"(ε = {epsilon:.2f}, δ = {delta})"
    )


# 进行10个epoch的训练
for epoch in range(1, 11):
    train(model, train_loader, optimizer, epoch, device="cpu", delta=1e-5)

 Secure RNG 警告:

E:\14anaconda\envs\ZjcPaper\lib\site-packages\opacus\privacy_engine.py:114: UserWarning: Secure RNG turned off. This is perfectly fine for experimentation as it allows for much faster training performance, but remember to turn it on and retrain one last time before production with ``secure_mode`` turned on. warnings.warn(

这个警告表明安全随机数生成器(RNG)处于关闭状态。在实验阶段这是可以的,因为它能让训练速度更快,但在生产环境中使用时,需要开启安全模式(secure_mode)并重训模型以确保安全性。

非完整反向传播钩子警告

这个警告指出在正向传播包含多个自动求导节点时使用非完整的反向传播钩子已经被弃用,未来版本将会移除。

训练进度信息:

100%|██████████| 938/938 [00:25<00:00, 36.12it/s] Train Epoch: 1 Loss: 1.211915 (ε = 0.36, δ = 1e-05) ... Train Epoch: 10 Loss: 0.479933 (ε = 0.45, δ = 1e-05)

这些信息显示模型在每个轮次的训练情况,随着训练轮次的增加,损失值有所下降,这通常是一个好的迹象,表明模型在不断学习数据中的模式。同时,隐私预算(ε)随着轮次的增加而逐渐增大,这是差分隐私训练中的正常现象,因为随着训练的进行,隐私泄露的风险会逐渐增加。

ε和 δ含义:

参数含义与隐私效果的关系
ε(epsilon)在差分隐私中,ε 是用来衡量隐私预算的参数,直观上表示两个相邻数据集在算法输出上的差异程度。它限制了攻击者通过观察输出结果来推断出关于特定个体数据信息的能力。一般来说,ε 越小,隐私保护效果越好。因为较小的 ε 意味着即使攻击者获取了算法的输出,也很难区分不同数据集之间的差异,从而更难推断出个体数据的信息。
δ(delta)δ 也是差分隐私中的一个参数,它表示在差分隐私定义中允许的 “失败概率”。即在某些情况下,可能会稍微超出 ε 所规定的隐私保护范围,但这种情况发生的概率被限制在 δ 以内。δ 越小,说明算法违反严格隐私保证的概率越低,通常也意味着更好的隐私效果。不过,δ 通常是一个很小的值,比如 1e - 5 等,在实际应用中需要结合 ε 一起考虑来评估隐私保护的强度。

(3)具体代码讲解

①导入必要的库和模块

# -*- coding: utf-8 -*-

# Step 1: 导入必要的库和模块
import torch  # 导入PyTorch深度学习框架
import os  # 导入操作系统模块

# 设置环境变量解决某些系统下的库冲突问题
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
# 从torchvision导入数据集和数据处理工具
from torchvision import datasets, transforms
import numpy as np  # 导入数值计算库
# 从Opacus导入差分隐私引擎
from opacus import PrivacyEngine
# 导入进度条工具
from tqdm import tqdm

②加载MNIST数据集

# Step 2: 加载MNIST数据集
# 创建训练数据加载器
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST(
        '../mnist',  # 数据集存储路径
        train=True,  # 使用训练集
        download=True,  # 如果不存在则自动下载
        transform=transforms.Compose([  # 数据预处理管道
            transforms.ToTensor(),  # 将PIL图像转换为Tensor
            # 标准化处理(使用MNIST的均值和标准差)
            transforms.Normalize((0.1307,), (0.3081,))
        ]),
    ),
    batch_size=64,  # 每批加载64个样本
    shuffle=True,  # 打乱数据顺序
    num_workers=0,  # 使用0个子进程加载数据
    pin_memory=True  # 将数据缓存在CUDA固定内存中(如果可用)
)

# 创建测试数据加载器(参数与训练集类似)
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=0,
    pin_memory=True
)

③构建神经网络模型和优化器

# Step 3: 构建神经网络模型和优化器
# 使用Sequential容器构建卷积神经网络
model = torch.nn.Sequential(
    # 第一个卷积层:输入通道1,输出通道16,卷积核8x8,步长2,填充3
    torch.nn.Conv2d(1, 16, 8, 2, padding=3),
    torch.nn.ReLU(),  # ReLU激活函数
    # 最大池化层:窗口大小2x2,步长1
    torch.nn.MaxPool2d(2, 1),
    # 第二个卷积层:输入通道16,输出通道32,卷积核4x4,步长2
    torch.nn.Conv2d(16, 32, 4, 2),
    torch.nn.ReLU(),
    torch.nn.MaxPool2d(2, 1),
    torch.nn.Flatten(),  # 展平多维特征图为一维
    # 全连接层:输入特征数32*4*4,输出32
    torch.nn.Linear(32 * 4 * 4, 32),
    torch.nn.ReLU(),
    # 输出层:输入32,输出10(对应10个数字类别)
    torch.nn.Linear(32, 10)
)

# 创建随机梯度下降优化器,学习率0.05
optimizer = torch.optim.SGD(model.parameters(), lr=0.05)

④添加差分隐私引擎

# Step 4: 添加差分隐私引擎
# 初始化隐私引擎,配置差分隐私参数
privacy_engine = PrivacyEngine()
model, optimizer, train_loader = privacy_engine.make_private(
    module=model,
    optimizer=optimizer,
    data_loader=train_loader,
    noise_multiplier=1.3,  # 高斯噪声的乘数
    max_grad_norm=1.0,  # 梯度裁剪的阈值
)

⑤定义训练函数

# Step 5: 定义训练函数
def train(model, train_loader, optimizer, epoch, device, delta):
    model.train()  # 设置模型为训练模式
    criterion = torch.nn.CrossEntropyLoss()  # 定义交叉熵损失函数
    losses = []  # 存储每批损失的列表

    # 使用tqdm包装数据加载器以显示进度条
    for _batch_idx, (data, target) in enumerate(tqdm(train_loader)):
        # 将数据移动到指定设备(CPU/GPU)
        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 = privacy_engine.accountant.get_epsilon(delta)
    # 打印训练结果
    print(
        f"Train Epoch: {epoch} \t"
        f"Loss: {np.mean(losses):.6f} "
        f"(ε = {epsilon:.2f}, δ = {delta})"
    )

⑥主函数开始训练

# step6:主函数开始训练
# 进行10个epoch的训练
for epoch in range(1, 11):
    train(model, train_loader, optimizer, epoch, device="cpu", delta=1e-5)

(4)参考文献

使用Opacus库在Mnist数据集实现差分隐私-CSDN博客

### 如何在PyTorch Lightning中集成Opacus实现差分隐私训练 为了实现在PyTorch Lightning框架下利用Opacus来进行模型的差分隐私保护训练,可以遵循如下方法: #### 安装依赖包 首先确保安装了必要的Python。可以通过pip命令来完成这些软件包的安装。 ```bash pip install pytorch-lightning opacus torchdp torchvision ``` #### 导入所需模块并初始化组件 创建一个新的脚本文件,在其中导入所需的类和其他资源,并设置好基础环境配置。 ```python import torch from torch import nn, optim from torch.utils.data import DataLoader import pytorch_lightning as pl from opacus import PrivacyEngine from torchvision import datasets, transforms ``` #### 构建数据加载器 定义用于获取MNIST手写数字识别的数据集实例化对象以及相应的转换操作;接着构建DataLoader实例以便于后续迭代读取批次样本。 ```python transform = transforms.Compose([ transforms.ToTensor(), ]) train_dataset = datasets.MNIST( root='./data', train=True, download=True, transform=transform) test_dataset = datasets.MNIST( root='./data', train=False, download=True, transform=transform) train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False) ``` #### 创建LightningModule子类 设计继承自`pl.LightningModule`的新类,重载其成员函数以适应特定任务需求——这里假设是一个简单的全连接神经网络分类器结构。 ```python class DPNet(pl.LightningModule): def __init__(self): super().__init__() self.model = nn.Sequential( nn.Linear(784, 512), nn.ReLU(), nn.Dropout(p=0.2), nn.Linear(512, 10), nn.LogSoftmax(dim=-1)) def forward(self, x): return self.model(x.view(-1, 784)) def configure_optimizers(self): optimizer = optim.SGD(self.parameters(), lr=0.01, momentum=0.9) return optimizer def training_step(self, batch, batch_idx=None): data, target = batch output = self(data) loss = F.nll_loss(output, target) pred = output.argmax(dim=1, keepdim=True) correct = pred.eq(target.view_as(pred)).sum().item() logs={"loss": loss} result={ 'log':logs, 'progress_bar':{'acc':correct / len(batch)}, } return {'loss': loss,**result} def test_step(self,batch,*args,**kwargs): data,target=batch output=self.forward(data) _,pred=output.max(1) acc=pred.eq(target).float().mean() return {"accuracy":acc.item()} ``` #### 应用Privacy Engine 通过调用`privacy_engine.make_private()`接口将上述定义好的模型转化为具有DP特性的版本,指定最大梯度范数(`max_grad_norm`)参数控制噪声强度,同时传入优化器作为输入之一。 ```python model = DPNet() optimizer = model.configure_optimizers() privacy_engine = PrivacyEngine(model=model,max_grad_norm=1.0,) private_model, private_optimizer, _ = privacy_engine.make_private_with_epsilon( module=model, optimizer=optimizer, data_loader=train_loader, epochs=10, target_delta=1e-5, target_epsilon=1., ) ``` #### 训练过程中的调整 最后一步是在实际执行fit()之前修改默认的行为逻辑,即每次反向传播之后都需要额外调用一次step()方法更新累积起来的剪裁后的梯度信息,从而达到预期效果。 ```python trainer = pl.Trainer(max_epochs=10,default_root_dir="./lightning_logs/") for epoch in range(trainer.max_epochs): for i,(inputs,labels)in enumerate(train_loader): outputs=private_model(inputs) loss=F.cross_entropy(outputs, labels) loss.backward() private_optimizer.step() private_optimizer.zero_grad() trainer.fit(private_model, train_dataloader=train_loader,test_dataloaders=test_loader) ``` 以上就是关于如何基于PyTorch Lightning平台结合Opacus工具箱开展带有差异隐私保障机制的学习流程介绍[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还不秃顶的计科生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值