随着机器学习模型的复杂性和能力不断增加。提高大型复杂模型在小数据集性能的一种有效技术是知识蒸馏,它包括训练一个更小、更有效的模型来模仿一个更大的“教师”模型的行为。

在本文中,我们将探索知识蒸馏的概念,以及如何在PyTorch中实现它。我们将看到如何使用它将一个庞大、笨重的模型压缩成一个更小、更高效的模型,并且仍然保留原始模型的准确性和性能。

我们首先定义知识蒸馏要解决的问题。

我们训练了一个大型深度神经网络来执行复杂的任务,比如图像分类或机器翻译。这个模型可能有数千层和数百万个参数,这使得它很难部署在现实应用程序、边缘设备等中。并且这个超大的模型还需要大量的计算资源来运行,这使得它在一些资源受限的平台上无法工作。

解决这个问题的一种方法是使用知识蒸馏将大模型压缩成较小的模型。这个过程包括训练一个较小的模型来模仿给定任务中大型模型的行为。

我们将使用来自Kaggle的胸部x光数据集进行肺炎分类来进行知识蒸馏的示例。我们使用的数据集被组织成3个文件夹(train, test, val),并包含每个图像类别的子文件夹(Pneumonia/Normal)。共有5,863张x射线图像(JPEG)和2个类别(肺炎/正常)。

比较一下这两个类的图片:

数据的加载和预处理与我们是否使用知识蒸馏或特定模型无关,代码片段可能如下所示:

 transforms_train = transforms.Compose([transforms.Resize((224, 224)),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])])transforms_test = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])])train_data = ImageFolder(root=train_dir, transform=transforms_train)test_data = ImageFolder(root=test_dir, transform=transforms_test)train_loader = DataLoader(train_data, batch_size=32, shuffle=True)test_loader = DataLoader(test_data, batch_size=32, shuffle=True)

教师模型

在这个背景中教师模型我们使用Resnet-18并且在这个数据集上进行了微调。

 import torchimport torch.nn as nnimport torchvisionclass TeacherNet(nn.Module):def __init__(self):super().__init__()self.model = torchvision.models.resnet18(pretrained=True)for params in self.model.parameters():params.requires_grad_ = Falsen_filters = self.model.fc.in_featuresself.model.fc = nn.Linear(n_filters, 2)def forward(self, x):x = self.model(x)return x

微调训练的代码如下

 def train(model, train_loader, test_loader, optimizer, criterion, device):dataloaders = {'train': train_loader, 'val': test_loader}for epoch in range(30):print('Epoch {}/{}'.format(epoch, num_epochs - 1))print('-' * 10)for phase in ['train', 'val']:if phase == 'train':model.train()else:model.eval()running_loss = 0.0running_corrects = 0for inputs, labels in tqdm.tqdm(dataloaders[phase]):inputs = inputs.to(device)labels = labels.to(device)optimizer.zero_grad()with torch.set_grad_enabled(phase == 'train'):outputs = model(inputs)loss = criterion(outputs, labels)_, preds = torch.max(outputs, 1)if phase == 'train':loss.backward()optimizer.step()running_loss += loss.item() * inputs.size(0)running_corrects += torch.sum(preds == labels.data)epoch_loss = running_loss / len(dataloaders[phase].dataset)epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset)print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))

这是一个标准的微调训练步骤,训练后我们可以看到该模型在测试集上达到了91%的准确性,这也就是我们没有选择更大模型的原因,因为作为测试91的准确率已经足够作为基类模型来使用了。

我们知道模型有1170万个参数,因此不一定能够适应边缘设备或其他特定场景。

学生模型

我们的学生是一个更浅的CNN,只有几层和大约100k个参数。

 class StudentNet(nn.Module):def __init__(self):super().__init__()self.layer1 = nn.Sequential(nn.Conv2d(3, 4, kernel_size=3, padding=1),nn.BatchNorm2d(4),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2))self.fc = nn.Linear(4 * 112 * 112, 2)def forward(self, x):out = self.layer1(x)out = out.view(out.size(0), -1)out = self.fc(out)return out

看代码就非常的简单,对吧。

如果我可以简单地训练这个更小的神经网络,我为什么还要费心进行知识蒸馏呢?我们最后会附上我们通过超参数调整等手段从头训练这个网络的结果最为对比。

但是现在我们继续我们的知识蒸馏的步骤

知识蒸馏训练

训练的基本步骤是不变的,但是区别是如何计算最终的训练损失,我们将使用教师模型损失,学生模型的损失和蒸馏损失一起来计算最终的损失。

 class DistillationLoss:def __init__(self):self.student_loss = nn.CrossEntropyLoss()self.distillation_loss = nn.KLDivLoss()self.temperature = 1self.alpha = 0.25def __call__(self, student_logits, student_target_loss, teacher_logits):distillation_loss = self.distillation_loss(F.log_softmax(student_logits / self.temperature, dim=1),F.softmax(teacher_logits / self.temperature, dim=1))loss = (1 - self.alpha) * student_target_loss + self.alpha * distillation_lossreturn loss

损失函数是下面两个东西的加权和:

  • 分类损失,称为student_target_loss
  • 蒸馏损失,学生对数和教师对数之间的交叉熵损失

简单的讲,我们的教师模型需要教导学生如何“思考”的,这就是指的是它的不确定性;例如,如果教师模型的最终输出概率是[0.53,0.47],我们希望学生也得到同样类似结果,这些预测之间的差异就是蒸馏损失。

为了控制损失,还有有两个主要参数:

  • 蒸馏损失的权重:0意味着我们只考虑蒸馏损失,反之亦然。
  • 温度:衡量教师预测的不确定性。

在上面的要点中,alpha和temperature的值都是根据我们尝试过一些组合得到的最佳结果的值。

结果对比

这是这个实验的表格摘要。

我们可以清楚地看到使用更小(99.14%),更浅的CNN所获得的巨大好处:与无蒸馏训练相比,准确率提升了10点,并且比Resnet-18快11倍!也就是说,我们的小模型真的从大模型中学到了有用的东西。

https://avoid.overfit.cn/post/482f5c111e7344179e2aba57865427ea

作者:Alessandro Lamberti

使用PyTorch进行知识蒸馏的代码示例相关推荐

  1. 【Pytorch】使用Pytorch进行知识蒸馏

    使用Pytorch进行知识蒸馏 一.知识蒸馏原理 1. 使用 `softmax` 进行蒸馏: 2. 知识迁移:老师知识 -> 学生知识 二.知识蒸馏实现 1. 导入各种包 2. 设置随机种子 3 ...

  2. java窗口三栏布局_移动端的flex三栏布局的相关知识介绍(代码示例)

    本篇文章给大家带来的内容是关于移动端的flex三栏布局的相关知识介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 默认情况下先显示移动端,通过 @media 属性适配屏 ...

  3. 7个使用PyTorch的技巧,含在线代码示例!网友:我连第一个都不知道?!

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 丰色 发自 凹非寺 量子位 报道 | 公众号 QbitAI 大家在使 ...

  4. 知识蒸馏——pytorch实现

    轻量化网络 知识蒸馏可以理解为轻量化网络的一个tricks,轻量化网络是深度学习的一个大的发展趋势,尤其是在移动端,终端边缘计算这种对算力和运算时间有要求的场景中. 轻量化网络可以有以下四种方式实现: ...

  5. 知识蒸馏之自蒸馏【附代码】

    知识蒸馏的核心思想就是将大模型的知识传给小模型. 这里的知识通常就是模型所学的数据分布.大模型特点一般是具有非常高的精度,但可能在速度上不行,或者是不易部署,小模型通常是易部署,速度快但精度不如大模型 ...

  6. 详解知识蒸馏原理和代码

    目录 知识蒸馏 原理 概念 技巧 举例说明 KL 散度及损失 KD训练代码 导入包 网络架构 teacher网络 student网络 teacher网络训练 定义基本函数 训练主函数 student网 ...

  7. 杂谈 | 当前知识蒸馏与迁移学习有哪些可用的开源工具?

    所有参与投票的 CSDN 用户都参加抽奖活动 群内公布奖项,还有更多福利赠送 作者&编辑 | 言有三 来源 | 有三AI(ID:yanyousan_ai) [导读]知识蒸馏与迁移学习不仅仅属于 ...

  8. 微软亚研院提出用于语义分割的结构化知识蒸馏 | CVPR 2019

    作者 | CV君 来源 | 我爱计算机视觉 今天跟大家分享一篇关于语义分割的论文,刚刚上传到arXiv的CVPR 2019接收论文<Structured Knowledge Distillati ...

  9. 【杂谈】当前知识蒸馏与迁移学习有哪些可用的开源工具?

    知识蒸馏与迁移学习不仅仅属于模型优化的重要技术之一,也是提升模型跨领域泛化能力的重要技术,那么当前有哪些可用的知识蒸馏和迁移学习开源工具呢? 作者&编辑 | 言有三 1 PaddleSlim ...

最新文章

  1. Fragment 使用 replace 的方式实现切换 以及切换的时候Fragment 生命周期
  2. goroutine 那些事
  3. java安装库源文件_JOGL安装
  4. VTK修炼之道80:VTK开发基础_智能指针与引用计数
  5. mysql create很多table,SQL CREATE TABLE 语句
  6. oracle日志文件大小规则,在线重做Oracle日志文件大小
  7. 天津和塘沽两天一夜自由行(第一天)
  8. 诗与远方:无题(五十七)
  9. 完全分布式Hadoop2.3安装与配置
  10. 谷歌再推AI开源平台AI·ON,你有机会参与Bengio的项目了
  11. [转]引用 VC 对话框设置位图背景并透明控件
  12. java p39课后答案_面向对象程序设计(JAVA)答案
  13. js 表格动态增加行通用函数
  14. matlab编程椅子放平问题,数学模型程序代码Matlab-姜启源-第一章-建立数学模型.docx...
  15. 动易 转 html5,动易dedecms数据转成dedecms的php程序
  16. 大数据日志分析Hadoop项目实战
  17. java判断小数位数_java-使用BigDecimal确定小数位数
  18. vue控制台报错Extraneous non-props attributes (class) were passed to component but could not be automatica
  19. 关于微信录音的坑-Linux服务器上进行音频格式的转换
  20. 我在北大青鸟的工作经历

热门文章

  1. oracle bom递归查询,求多阶BOM查询代码
  2. 申请优豆云免费虚拟主机使用感受分享心得
  3. 北风网课程开放下载第一季
  4. 线上相亲交友源码APP开发,是互联网婚恋市场的新途径
  5. Tekton task入门上
  6. 基础实验——485传感器修改地址
  7. uc神马推广一年多少钱,uc信息流推广一个月要多少钱
  8. NLP之文本分类:「Tf-Idf、Word2Vec和BERT」三种模型比较
  9. JSON格式字符串解析,转换为JSONObject
  10. Iptables与Firewalld防火墙(最详细说明)