583. NeurIPS 2023 - Machine Unlearning | neurips-2023-machine-unlearning
首先,感谢Kaggle举办如此有趣的竞赛,也感谢每一位Kaggler。对我来说,这是一段真正难忘的经历,不仅因为活跃的讨论区提供了有趣且有用的思路和方法,更因为这次机器学习遗忘的主题本身意义非凡。我很荣幸能在此介绍我的解决方案。
我的方案基于两阶段训练方法:在遗忘数据集上进行1个epoch的遗忘阶段,然后在遗忘数据集和保留数据集上进行8个epoch的对抗性微调阶段。具体细节如下:
(1)为了让模型在logits空间初步遗忘,我们优化了输出logits与均匀伪标签之间的KL散度。
(2)对抗性微调阶段:
遗忘轮次:
在面对无监督学习任务(如特征嵌入聚类)时,实例级SCL(自监督对比学习)可能是一种有益的方法。自监督对比学习旨在拉近正样本与其增强样本之间的距离,同时推远正样本与所有样本之间的距离。根据我的假设,我们需要让遗忘样本在特征空间中尽可能均匀分布,这可以视为推远任何遗忘样本与所有保留样本之间的距离。因此,我提出了两种对比损失函数:
对于遗忘样本x,使用其增强版本x'作为正对,使用保留批次中的所有样本作为负对。最终损失公式如下:

每个保留样本与任何遗忘样本作为正样本的概率相同,意味着它们在对比损失公式中具有相同的权重。最终损失公式如下:

我最终采用了第二个损失函数作为提交版本(因为初步测试发现第一个损失函数表现不如第二个,受时间限制放弃了该思路)。温度系数t设为1.15。
遗忘训练轮次代码如下:
for sample_forget, sample_retain in zip(forget_loader, retain_ld4fgt):
t = 1.15 ##温度系数
inputs_forget,inputs_retain = sample_forget["image"],sample_retain['image']
inputs_forget, inputs_retain = inputs_forget.to(DEVICE), inputs_retain.to(DEVICE)
optimizer_forget.zero_grad()
outputs_forget,outputs_retain = net(inputs_forget),net(inputs_retain).detach()
loss = (-1 * nn.LogSoftmax(dim=-1)(outputs_forget @ outputs_retain.T/t)).mean() ##加权对比损失
##损失函数
loss.backward()
optimizer_forget.step()
由于forget_loader和retain_loader(此处指retain_ld4fgt,一个用于对比学习的新数据加载器)的步数不同,在不同检查点会出现意外的随机打乱,这可以视为一种集成方法。
保留轮次:
为了提升在保留数据集上的性能,微调是不可避免的。这里我简单地使用交叉熵损失重新训练模型。
在比赛期间,我的思路经历了多个阶段,每个阶段对比赛和任务都有不同的理解。事实上,论坛中许多优秀的代码和讨论给了我很大帮助。例如,@Maria Gorinova的评估笔记本是帮助你快速理解评估指标的出色工作。我也见证了论坛上许多截然不同的想法。我相信每个想法都有其自身的原因,但比赛场景是有限且理想化的。虽然高分方法在实际场景中可能存在局限性,但其背后的创新方法具有普遍适用性。我一直期待看到任何创造性的解决方案。