探索隐私与 AI 之间的交叉点,并通过指南消除 AI 训练中各个数据点的影响,使用 SISA 技术应用于使用 Python 的卷积神经网络 (CNN)。
截至本文撰写之日(基于世界银行数据),世界上超过 32% 的人口(约 80 亿)年龄在 20 岁以下。这意味着大约有26亿人出生在社交媒体时代,他们的一生很可能几乎都是在网上注册的,由他们的父母、他们的核心圈子、或者最终由他们自己(取决于他们对社交媒体的依恋)媒体及其网络) 。如果我们加上二十岁到五十岁之间的人,我们就多了 33 亿人,他们在某种程度上以不同的来源和格式(图像、评论、视频等)在网上记录了自己生活的一部分。当然,考虑到五十岁以上的人,或者不是世界上每个人都可以访问或使用互联网(根据世界银行的估计,至少超过 35% 的人没有访问或使用互联网,我们可以调整数字) 2021 ) ,但我相信你明白我的意思。我们的生活中有很大一部分都记录在当今的数字世界中。
另一个高概率或确定性(我们可以再次询问 OpenAI 的 CTO 🙄)是,这些数据的大部分正在被使用或已经被用于训练当今部署的所有“最先进”模型,从法学硕士到多模式可以处理图像、视频或文本等信息的 AI 模型。在这种背景下,当涉及到数据、技术和隐私时,我们经常发现双方都在努力寻找中间立场。一方面是每个人与技术之间的社会契约,我们愿意用我们的数据的一些权利来换取技术为我们带来的好处。另一方面,问题是必须在哪里划定界限,正如该立场的大多数捍卫者所说, “数据可访问并不意味着可以自由收集和使用” 。
在本文中,我们将探讨在讨论人工智能方面的隐私时出现的一些挑战,包括机器取消学习和 SISA 训练方法(分片、隔离、切片和聚合训练)的简要概述,这是最近开发的一种机器取消学习框架帮助管理或减少人工智能训练中单个数据点的影响,并解决与“被遗忘的权利”相关的合规挑战。
历史上最早倡导隐私权的出版物之一是两位美国律师 Samuel D. Warren 和 Louis Brandeis 在 1890 年代发表的一篇文章。这篇题为《隐私权》的文章是为了提高人们对未经授权的照片和早期报纸企业的影响的认识,用他们自己的话说,这些企业已经将八卦变成了商品,损害了个人享受生活的权利,被剥夺的权利。独自留下。
个人的人身和财产受到充分保护是与普通法一样古老的原则;但有时人们发现有必要重新界定这种保护的确切性质和范围。 ……最近的发明和商业方法引起人们对下一步的关注,必须采取这一步骤来保护个人,并确保个人享有库利法官所说的“不受干扰”的权利(塞缪尔·D·沃伦,路易斯·布兰迪斯) 1890)
自《隐私权》出版以来,时代已经发生了变化,但沃伦和路易斯·布兰代斯在一件事上没有犯错:技术、政治、社会和经济变革不断挑战现有或新的权利。对此,普通法应始终保持开放态度,以满足社会的新要求,认识到对社会的保护主要来自于承认个人的权利。
从那时起,隐私常常与传统方法联系在一起,即在幕后保护我们关心和想要的东西,使其远离公众视线,并控制其访问和使用。但随着时间的推移,它的边界也确实受到了颠覆性技术的考验。摄影和视频设定了新的界限,最近数据呈指数级增长。但基于数据的技术不仅影响数据合规性,还影响数据合规性。它们也对我们的信仰和习俗产生了一些影响。社交媒体平台或超级应用程序就是这种情况,我们愿意用数据的一些权利来换取技术为我们带来的好处。这意味着上下文很重要,在某些情况下,共享我们的敏感信息更多地依赖于信任等价值观,而不是一定要考虑侵犯隐私。
“数据不仅仅是‘私有’或‘非私有’或‘敏感’或‘非敏感’。背景很重要,规范的社会价值观也很重要……”(高级人工智能助理的道德规范。Google DeepMind 2024 )
上下文和隐私之间的关系是一个有趣的思路,被称为信息隐私模型:
“上下文完整性” ( Nissenbaum,2004 ) 。它指出,在发送者和接收者之间的每一次信息交换或流动中,都有社会规则对其进行管理。了解这些规则对于确保信息交换得到适当监管至关重要。
例如,一个明显的例子是有关我孩子在学校表现的信息。如果老师与其他家长或校外的陌生人分享我孩子的表现记录,我可能会认为这是侵犯隐私。然而,如果同一位老师与其他教我的孩子分享经验并提高孩子在学校表现的老师分享相同的信息,我可能不会那么担心,并且会依赖老师的信任、价值观和良好判断。因此,在情境完整性方法下,隐私不被判定为“独处权”的僵化状态。相反,重要的是信息的流动受到适当的监管,考虑到背景和其中的管理规范来确定限制。隐私作为一项基本权利不应改变,但可以重新考虑。
僵化的隐私观念是否应该保持不变?或者我们应该首先了解管理信息流动的社会规则?
随着人工智能继续塑造未来,这种重新思考挑战我们考虑调整现有权利或可能引入新的数字权利。
无论您将隐私视为一个严格的概念还是考虑上下文完整性方法,我认为我们大多数人都会同意,我们都应该在征得我们同意的情况下公平地处理我们的数据,并在必要时能够纠正或删除它。
虽然 GDPR 促进了数据和隐私的共存,但在监管框架内平衡隐私和人工智能却提出了不同的挑战。尽管我们可以删除或修改数据集中的敏感数据,但在人工智能模型中这样做要复杂得多。他们不会每天接受重新培训,在大多数情况下,需要几个月的时间才能确保其可靠性。为了解决在不显着牺牲模型性能的情况下选择性删除人工智能模型中特定训练数据点(及其影响)的任务,机器取消学习等技术已经出现并正在研究中,以找到隐私问题的解决方案,遵守任何可能的强制法规,并保护用户的合法删除或更正权。
与可以追溯到一百多年前的隐私政策研究相比,机器遗忘是一个相对较新的领域,最初的研究仅出现在大约 10 年前(Y. Cao 和 J. Yang,2015)。
那么我们为什么要对机器取消学习感兴趣呢?无论您是一位突破界限的 AI 研究人员,还是致力于开发 AI 解决方案以使 AI 对最终用户友好,以下都是在 ML 流程中采用机器取消学习技术的一些充分理由:
· 被遗忘的权利(RTBF):法学硕士和最先进的基础模型以复杂、快速发展的方式处理数据。正如 GDPR 所见,用户请求删除权并将其纳入适用于人工智能的法规只是时间问题。这将要求任何使用人工智能的公司调整流程以满足法规要求,并遵循用户请求从预先训练的模型中删除个人数据。
· 非零影响:当今存在诸如差分隐私之类的框架,通过引入噪声来隐藏任何单个数据点的贡献,从而确保敏感数据集的某些隐私。然而,虽然差异隐私有助于减轻单个数据点的影响,但这种努力仍然是“非零”的。这意味着目标数据点仍有可能对模型产生某种影响。在需要完全删除数据点的场景中,可能需要不同的差分隐私方法。
· 性能优化:众所周知,基础模型是使用大量数据进行训练的,需要大量的时间和计算资源。从头开始重新训练完整的模型以删除单个数据点可能是消除模型中该数据点的任何影响的最有效方法,但这不是最有效的方法(模型需要经常重新训练😨) 。机器取消学习景观通过将时间和计算资源视为逆转或否定特定数据点对模型参数的影响的过程中的约束来解决这个问题。
· 网络安全:模型无法免受对手的攻击,对手会注入数据来操纵模型的行为,以提供有关用户的敏感信息。机器取消学习可以帮助删除有害数据点并保护用于训练模型的敏感信息。
在机器取消学习领域,我们发现了两种思路:精确机器取消学习和近似机器取消学习。精确机器取消学习侧重于通过完全删除特定数据点来消除它们的影响(就好像该数据从未被引入到模型中一样) ,近似机器取消学习旨在有效地减少训练模型中特定数据点的影响(使得该模型的行为近似于从未引入数据点时的情况) 。两种方法都提供了多种技术来解决用户的擦除权,并考虑模型性能恶化、计算资源、时间消耗、存储资源、特定学习模型或数据结构等约束。
为了更好地了解该领域正在进行的工作,我建议阅读两本有趣的读物:机器遗忘:解决方案和挑战 (2024)和学习遗忘:洞察机器遗忘 (2023) 。这两篇论文很好地回顾了过去几年机器学习领域科学家和研究人员的非凡工作。
SISA 框架是 Exact Machine Unlearning 思路的一部分,旨在删除数据而不需要对模型进行全面的重新训练。该框架的前提是,尽管从头开始重新训练,但排除需要忘记的数据点,是符合“被遗忘权”原则的最直接方法(提供证据和保证,证明不需要的数据已被删除)删除) ,它还认识到,当涉及使用大型数据集训练的复杂基础模型时,这可能被视为一种幼稚的策略,这需要大量的资源来进行训练。因此,为了解决遗忘过程的问题,任何技术都应该满足以下要求:
- 易于理解(可理解性):该技术应该易于理解和实施。
- 准确性:虽然可能会损失一些准确性,但差距应该很小。
- 时间/计算效率:与从头开始排除数据点并使用与训练过程中已有的计算资源类似的计算资源相比,它应该需要更少的时间。
- 易于验证(可证明的保证):该技术应清楚地证明所请求的数据点已被遗忘,而不影响模型参数,并且证明可以轻松解释(甚至对非专家而言)。
- 模型无关:它应该适用于不同性质和复杂性的模型。
如何保证特定训练数据点的完全去除?我们如何验证这种遗忘过程是否成功?
SISA 框架(分片、隔离、切片和聚合)于 2019 年在论文“ Machine Unlearning ” (Bourtoule 等人)中首次引入,旨在为从 ML 模型中取消学习数据的问题提供替代解决方案,确保消除保证很容易理解。这篇论文的介绍性页面很容易阅读,但如果您不熟悉机器学习领域,它可能会变得复杂。因此,我将尝试总结我在该技术中发现的一些有趣的特征,但如果您有时间,我强烈建议您尝试一下这篇论文,它值得一读! (还可以在作者在 IEEE 安全与隐私研讨会上制作的视频中观看该论文研究结果的有趣演示)
SISA 训练方法涉及多次复制模型,每个副本都在数据集的不同子集(称为分片)上进行训练。每个模型被称为“构成模型”。在每个分片内,数据被进一步划分为“片”,并应用增量学习并相应存档参数。每个组成模型在训练阶段主要与其分配的分片一起工作,而每个分片中的分片则用于管理数据并支持增量学习。训练后,来自每个分片的子模型被聚合以形成最终模型。在推理过程中,来自各个组成模型的预测被组合起来以产生总体预测。图 02 说明了 SISA 培训方法的工作原理。
当需要忘记数据时,仅重新训练其分片包含要忘记的点的组成模型(数据点是从特定分片中的特定切片中忘记的) 。
应用 SISA:忘记并重新训练用于图像识别的 CNN 模型
为了了解如何应用 SISA,我将使用 Python 编写一个用例示例。最近,我使用 PyTorch、计算机视觉技术和卷积神经网络 (CNN) 构建了一个基本设置来跟踪曲棍球运动员和球队并收集一些基本的表现统计数据(您可以在此处访问完整的文章) 。
尽管秘鲁直排曲棍球协会 (APHL) 同意在该项目中使用 40 秒的视频,但让我们想象一下我们的 SISA 用例的场景:一名球员抱怨他的图像被使用,并行使他的删除权,已要求从 CNN 预训练模型中删除他的图像,该模型将球员分类为每支球队。这需要我们从训练数据集中删除图像并重新训练整个模型。然而,通过应用 SISA 技术,我们只需要处理包含这些图像的分片和切片,从而避免了从头开始重新训练模型和优化时间的需要。
最初的CNN模型结构如下:
#************卷积神经网络-三类检测****************************
# 裁判
# 白队 (white_away)
# 黄队 (yellow_home)
导入操作系统
进口火炬
将 torch.nn 导入为 nn
导入 torch.optim 作为 optim
导入 torch.nn.function 作为 F
导入 torchvision.transforms 作为变换
导入 torchvision.datasets 作为数据集
从 torch.utils.data 导入 DataLoader
从 sklearn.metrics 导入准确度_分数、精度_分数、召回_分数、f1_分数
将 matplotlib.pyplot 导入为 plt
#********************************数据转换******************** **************************
# 训练和验证数据集
data_dir = 'D:/PYTHON/teams_sample_dataset'
变换 = 变换.Compose([
变换.调整大小((150, 150)),
变换.ToTensor(),
变换.Normalize(平均值=[0.5,0.5,0.5],std=[0.5,0.5,0.5])
])
# 加载数据集
train_dataset = datasets.ImageFolder(os.path.join(data_dir, 'train'), transform=transform)
val_dataset = datasets.ImageFolder(os.path.join(data_dir,'val'),transform=transform)
train_loader = DataLoader(train_dataset,batch_size=32,shuffle=True)
val_loader = DataLoader(val_dataset,batch_size=32,shuffle=False)
#********************************CNN模型架构**************** **********************
CNNModel 类(nn.Module):
def __init__(自身):
super(CNNModel, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
self.fc1 = nn.Linear(128 * 18 * 18, 512)
self.dropout = nn.Dropout(0.5)
self.fc2 = nn.Linear(512, 3) #三个类
def 前向(自身,x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = self.pool(F.relu(self.conv3(x)))
x = x.view(-1, 128 * 18 * 18)
x = F.relu(self.fc1(x))
x = self.dropout(x)
x = self.fc2(x)
返回x
#********************************CNN 培训**************** ******************************
# 模型损失函数优化器
模型 = CNNModel()
标准 = nn.CrossEntropyLoss()
优化器 = optim.Adam(model.parameters(), lr=0.001)
#*********************************训练*************** **************************************
纪元数 = 10
train_losses, val_losses = [], []
对于范围内的纪元(num_epochs):
模型.train()
运行损失 = 0.0
对于输入,train_loader 中的标签:
优化器.zero_grad()
输出 = 模型(输入)
标签 = labels.type(torch.LongTensor)
损失=标准(输出,标签)
loss.backward()
优化器.step()
running_loss += loss.item()
train_losses.append(running_loss / len(train_loader))
模型.eval()
val_loss = 0.0
所有标签 = []
all_preds = []
使用 torch.no_grad():
对于输入,val_loader 中的标签:
输出 = 模型(输入)
标签 = labels.type(torch.LongTensor)
损失=标准(输出,标签)
val_loss += loss.item()
_, preds = torch.max(输出, 1)
all_labels.extend(labels.tolist())
all_preds.extend(preds.tolist())
#********************************指标与性能**************** **********************
val_losses.append(val_loss / len(val_loader))
val_accuracy = precision_score(all_labels, all_preds)
val_ precision = precision_score(all_labels,all_preds,平均值='宏',zero_division = 1)
val_recall=recall_score(all_labels, all_preds,average='macro',zero_division=1)
val_f1 = f1_score(all_labels, all_preds, 平均值='宏', Zero_division=1)
print(f"纪元 [{纪元 + 1}/{num_epochs}], "
f“损失:{train_losses[-1]:.4f},”
f“Val损失:{val_losses[-1]:.4f},”
f“验证值:{val_accuracy:.2%},”
f“值精度:{val_ precision:.4f},”
f“Val召回:{val_recall:.4f},”
f"Val F1 分数:{val_f1:.4f}")
#********************************显示指标和性能**************** ******************
plt.plot(train_losses, label='火车损失')
plt.plot(val_losses, label='验证损失')
plt.图例()
plt.show()
# 保存 GH_CV_track_teams 代码的模型
torch.save(model.state_dict(), 'D:/PYTHON/hockey_team_classifier.pth')
正如你所看到的,它是一个使用 ReLU 作为激活函数的三层(conv1、conv2、conv3)神经网络结构,使用大约 90 张图像的数据集进行训练,分为三类:裁判、Team_Away(白球衣球员)、和 Team_Home(黄衫球员),超过 10 个 epoch 的完整周期。
考虑到这种初始方法,从训练过程中删除图像的请求将涉及从训练和验证数据集中删除图像并重新训练模型。虽然对于像我们这样的小数据集来说这可能很容易,但对于较大的数据集,例如当前大型语言模型(LLM)中使用的数据集,这将代表大量的资源使用。此外,重复执行此过程也可能是一个限制。
现在,让我们想象一下,在构建模型时,我们意识到用户删除或纠正的权利,并考虑应用 SISA 技术。这种方法将为未来可能需要从训练数据集中永久删除图像的任何场景以及 CNN 在学习过程中可能捕获的任何特征准备模型。第一步是调整上面提出的初始模型,以包括 SISA 技术的四个步骤:分片、隔离、切片和聚合。
步骤01:碎片和切片
在前面代码开头指定的转换步骤之后,我们将通过将数据集划分为分片来开始应用 SISA。在代码中,您将看到分片是多种多样的,然后分成相等大小的部分,以确保每个分片包含有代表性的样本数量,并且在我们想要预测的不同类之间保持平衡(在我们的例子中,我们正在预测三堂课) 。
#*****************************分割数据集**************** **********
def shard_dataset(数据集, num_shards):
索引 = 列表(范围(len(数据集)))
np.random.shuffle(索引)
碎片=[]
shard_size = len(数据集) // num_shards
对于范围内的 i(num_shards):
shard_indices = 索引[i * shard_size : (i + 1) * shard_size]
shards.append(子集(数据集, shard_indices))
返回碎片
#********************************重叠切片******************** **********
def create_overlapping_slices(分片, slice_size, 重叠):
索引 = 列表(分片.索引)
切片=[]
步骤 = slice_size - 重叠
对于范围内的开始(0,len(索引) - slice_size + 1,step):
slice_indices = 索引[开始:开始 + slice_size]
slices.append(子集(shard.dataset, slice_indices))
返回切片
您会注意到,对于切片过程,我没有按照 SISA 技术的建议为每个分片分配独占切片。相反,我们使用重叠的切片。这意味着每个切片不仅仅由来自一个分片的数据点组成;一个切片中的一些数据点也会出现在下一个切片中。
那么为什么我要重叠切片呢?正如您可能已经猜到的,我们的数据集很小(大约 90 个图像) ,因此使用每个分片的独占切片并不能保证每个切片具有足够平衡的数据集来维持模型的预测能力。重叠切片使模型能够更好地利用可用数据并提高泛化能力。对于较大的数据集,非重叠切片可能更有效,因为它们需要更少的计算资源。最后,创建分片和切片需要考虑数据集的大小、计算资源以及维护模型预测能力的需要。
最后,定义完函数后,我们继续设置分片和切片过程的超参数:
#****************************应用分片和切片********************
分片数 = 4
slice_size = len(full_train_dataset) // num_shards // 2
重叠 = slice_size // 2
分片 = shard_dataset(full_train_dataset, num_shards)
#************************每个分片的重叠切片********************
所有切片 = []
对于分片中的分片:
切片= create_overlapping_slices(分片,切片大小,重叠)
all_slices.extend(切片)
数据集分为 4 个分片,但我应该提到的是,最初我使用了 10 个分片。这导致每个分片仅包含少量样本图像,无法正确代表完整数据集的类别分布,从而导致模型的性能指标(准确度、精度和 F1 分数)显着下降。由于我们处理的是小型数据集,因此将分片数量减少到四个是一个明智的决定。最后,切片过程将每个分片分成两个重叠 50% 的切片,这意味着每个切片中的一半图像与下一个切片重叠。
步骤02:隔离特定数据点
在此步骤中,我们继续隔离最终用户可能想要从模型学习过程中纠正或删除的特定数据点。首先,我们定义一个函数,从每个切片中删除指定的数据点。接下来,我们根据图像的文件名来识别图像的索引。然后,这些索引用于通过删除它们所在的数据点来更新每个切片。
#*************************+*隔离数据点******************** **********
defisolate_data_for_unlearning(切片,data_points_to_remove):
new_indices = [如果 i 不在 data_points_to_remove 中,则 i 表示 slice.indices 中的 i]
返回子集(切片.数据集,new_indices)
#*****识别我们想要纠正/删除的图像的索引*********
def get_indices_to_remove(数据集, image_names_to_remove):
indexs_to_remove = [] #列表为空
image_to_index = {img_path: idx for idx, (img_path, _) in enumerate(dataset.imgs)}
对于 image_names_to_remove 中的 image_name:
如果 image_name 在 image_to_index 中:
indexs_to_remove.append(image_to_index[image_name])
返回要删除的索引
#*************************指定和删除图像******************** ******
要删除的图像 = []
indexs_to_remove = get_indices_to_remove(full_train_dataset, images_to_remove)
Updated_slices = [isolate_data_for_unlearning(切片,indices_to_remove)用于all_slices中的切片]
目前,列表为空 (images_to_remove = [] ),因此此阶段不会删除任何图像,但当请求到达时,设置即可使用(我们将在本文后面看到一个示例) 。
实现 SISA 技术的模型的完整版本应如下所示:
导入操作系统
将 numpy 导入为 np
进口火炬
将 torch.nn 导入为 nn
导入 torch.optim 作为 optim
导入 torch.nn.function 作为 F
导入 torchvision.transforms 作为变换
导入 torchvision.datasets 作为数据集
从 torch.utils.data 导入 DataLoader,子集
从 sklearn.metrics 导入准确度_分数、精度_分数、召回_分数、f1_分数
将 matplotlib.pyplot 导入为 plt
#********************************数据转换******************** **************************
# 训练和验证数据集
data_dir = 'D:/PYTHON/teams_sample_dataset'
变换 = 变换.Compose([
变换.调整大小((150, 150)),
变换.ToTensor(),
变换.Normalize(平均值=[0.5,0.5,0.5],std=[0.5,0.5,0.5])
])
# 加载数据
full_train_dataset = datasets.ImageFolder(os.path.join(data_dir, 'train'), transform=transform)
val_dataset = datasets.ImageFolder(os.path.join(data_dir,'val'),transform=transform)
#*****************************分割数据集**************** **********
def shard_dataset(数据集, num_shards):
索引 = 列表(范围(len(数据集)))
np.random.shuffle(索引)
碎片=[]
shard_size = len(数据集) // num_shards
对于范围内的 i(num_shards):
shard_indices = 索引[i * shard_size : (i + 1) * shard_size]
shards.append(子集(数据集, shard_indices))
返回碎片
#********************************重叠切片******************** **********
def create_overlapping_slices(分片, slice_size, 重叠):
索引 = 列表(分片.索引)
切片=[]
步骤 = slice_size - 重叠
对于范围内的开始(0,len(索引) - slice_size + 1,step):
slice_indices = 索引[开始:开始 + slice_size]
slices.append(子集(shard.dataset, slice_indices))
返回切片
#****************************应用分片和切片********************
分片数 = 4
slice_size = len(full_train_dataset) // num_shards // 2
重叠 = slice_size // 2
分片 = shard_dataset(full_train_dataset, num_shards)
#************************每个分片的重叠切片********************
所有切片 = []
对于分片中的分片:
切片= create_overlapping_slices(分片,切片大小,重叠)
all_slices.extend(切片)
#*************************+*隔离数据点******************** **********
defisolate_data_for_unlearning(切片,data_points_to_remove):
new_indices = [如果 i 不在 data_points_to_remove 中,则 i 表示 slice.indices 中的 i]
返回子集(切片.数据集,new_indices)
#*****识别我们想要纠正/删除的图像的索引*********
def get_indices_to_remove(数据集, image_names_to_remove):
要删除的索引 = []
image_to_index = {img_path: idx for idx, (img_path, _) in enumerate(dataset.imgs)}
对于 image_names_to_remove 中的 image_name:
如果 image_name 在 image_to_index 中:
indexs_to_remove.append(image_to_index[image_name])
返回要删除的索引
#*************************指定和删除图像******************** ******
要删除的图像 = []
indexs_to_remove = get_indices_to_remove(full_train_dataset, images_to_remove)
Updated_slices = [isolate_data_for_unlearning(切片,indices_to_remove)用于all_slices中的切片]
#********************************CNN模型架构**************** **********************
CNNModel 类(nn.Module):
def __init__(自身):
super(CNNModel, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
self.fc1 = nn.Linear(128 * 18 * 18, 512)
self.dropout = nn.Dropout(0.5)
self.fc2 = nn.Linear(512, 3) # 输出三个类
def 前向(自身,x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = self.pool(F.relu(self.conv3(x)))
x = x.view(-1, 128 * 18 * 18)
x = F.relu(self.fc1(x))
x = self.dropout(x)
x = self.fc2(x)
返回x
#********************************CNN 培训**************** ******************************
# 模型损失函数优化器
模型 = CNNModel()
标准 = nn.CrossEntropyLoss()
优化器 = optim.Adam(model.parameters(), lr=0.001)
#*********************************训练*************** **************************************
纪元数 = 10
train_losses, val_losses = [], []
对于范围内的纪元(num_epochs):
模型.train()
运行损失 = 0.0
对于 update_slices 中的切片:
train_loader = DataLoader(切片,batch_size = 32,shuffle = True)
对于输入,train_loader 中的标签:
优化器.zero_grad()
输出 = 模型(输入)
标签 = labels.type(torch.LongTensor)
损失=标准(输出,标签)
loss.backward()
优化器.step()
running_loss += loss.item()
train_losses.append(running_loss / (len(updated_slices)))
模型.eval()
val_loss = 0.0
所有标签 = []
all_preds = []
使用 torch.no_grad():
val_loader = DataLoader(val_dataset,batch_size=32,shuffle=False)
对于输入,val_loader 中的标签:
输出 = 模型(输入)
标签 = labels.type(torch.LongTensor)
损失=标准(输出,标签)
val_loss += loss.item()
_, preds = torch.max(输出, 1)
all_labels.extend(labels.tolist())
all_preds.extend(preds.tolist())
#********************************指标与性能**************** **********************
val_losses.append(val_loss / len(val_loader))
val_accuracy = precision_score(all_labels, all_preds)
val_ precision = precision_score(all_labels,all_preds,平均值='宏',zero_division = 1)
val_recall=recall_score(all_labels, all_preds,average='macro',zero_division=1)
val_f1 = f1_score(all_labels, all_preds, 平均值='宏观', Zero_division=1)
print(f"纪元 [{纪元 + 1}/{num_epochs}], "
f“损失:{train_losses[-1]:.4f},”
f“Val损失:{val_losses[-1]:.4f},”
f“验证值:{val_accuracy:.2%},”
f“值精度:{val_ precision:.4f},”
f“Val召回:{val_recall:.4f},”
f"Val F1 分数:{val_f1:.4f}")
#********************************显示指标和性能**************** ******************
plt.plot(train_losses, label='火车损失')
plt.plot(val_losses, label='验证损失')
plt.图例()
plt.show()
# 保存模型
torch.save(model.state_dict(), 'hockey_team_classifier_SISA.pth')
现在,让我们进入擦除场景。想象一下,模型部署已经过去了几个月,一名曲棍球运动员请求从 CNN 模型的训练数据中删除他们的图像。对于此示例,我们假设玩家由训练和验证数据集中的三个图像表示: A way_image03.JPG、Away_image04.JPG 和 Away_image05.JPG 。要从训练过程中删除这些图像,只需在代码的“指定和删除图像”部分中指定它们(如上所示)。只有包含这些图像的切片才需要重新训练。
#*************************指定和删除图像******************** ******
images_to_remove = ["Away_image03.JPG", "Away_image04.JPG", "Away_image05.JPG"]
indexs_to_remove = get_indices_to_remove(full_train_dataset, images_to_remove)
Updated_slices = [isolate_data_for_unlearning(切片,indices_to_remove)用于all_slices中的切片]
最后,我想分享一些根据我的模型调整 SISA 框架的重要收获:
- 弱学习器和性能权衡:由于每个组成模型都是在小子集(分片和切片)上进行训练的,因此人们可能会认为它们的准确性会低于在整个数据集上训练的单个模型的准确性,从而降低模型的泛化能力。令人惊讶的是,在我们的例子中,模型的性能显着提高,这可能是由于使用小的重叠数据集,导致一定程度的过度拟合。在涉及大型数据集的用例中,考虑潜在的性能权衡非常重要。
- 适当的碎片:我对大量碎片的初步尝试导致碎片很少,导致对模型的性能产生负面影响。不要低估碎片和切片过程的重要性。适当的碎片有助于模型避免过度拟合并在验证集上更好地概括。
我希望您发现该项目应用了SISA技术,以进行机器学习有趣。您可以在此GitHub存储库中访问完整的代码。
我和我的姐姐都有这个例行程序,我们在其中交换了社交媒体平台的每日图像,这使我们想起了我们发布的五,十或十五年前的图像。我们经常为分享的东西或当时所做的评论笑(显然,因为我们大多数人第一次出现时都没有完全了解社交媒体) 。随着时间的流逝,我学会了更明智地利用我的社交媒体存在,欣赏社交媒体生态系统之外的周围环境以及我们生活中某些方面应得到的隐私。但事实是,我的姐姐和我都不是十年或十五年前的同一个人,尽管过去是我们现在是谁的重要组成部分,但它并没有定义我们(并非一切都必须写成”在数字世界中的石头” 。我们所有人都有权选择该数据是否可能留在数字世界中,而不是使用定义我们的选择/偏好或其他数据的数据。
的确,在接受与将使用它类似的用户的数据培训时,AI的性能更好(高级AI助手的伦理学,Google DeepMind 2024) 。但是, “隐私需要透明度” 。因此,如何以及何时将机器学习与预训练的敏感数据实现“被遗忘的权利”对于朝着我们所有人都想要的值得信赖的AI迈进至关重要。
感谢您的阅读!与往常一样,欢迎您的建议并保持对话。
版权声明
本文为本站原创内容,转载需注明文章来源(https://www.eiefun.com),另:文中部分素材可能会引用自其他平台,如有侵权或其它,请联系 admin@eiefun.com,我们会第一时间配合删除