如何深入理解Pytorch微调torchvision模型,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
一、简介
在本小节,深入探讨如何对torchvision进行微调和特征提取。所有模型都已经预先在1000类的magenet数据集上训练完成。 本节将深入介绍如何使用几个现代的CNN架构,并将直观展示如何微调任意的PyTorch模型。
本节将执行两种类型的迁移学习:
微调:从预训练模型开始,更新我们新任务的所有模型参数,实质上是重新训练整个模型。
特征提取:从预训练模型开始,仅更新从中导出预测的最终图层权重。它被称为特征提取,因为我们使用预训练的CNN作为固定 的特征提取器,并且仅改变输出层。
通常这两种迁移学习方法都会遵循一下步骤:
初始化预训练模型
重组最后一层,使其具有与新数据集类别数相同的输出数
为优化算法定义想要的训练期间更新的参数
运行训练步骤
二、导入相关包
from __future__ import print_functionfrom __future__ import divisionimport torchimport torch.nn as nnimport torch.optim as optimimport numpy as npimport torchvision from torchvision import datasets,models,transformsimport matplotlib.pyplot as pltimport timeimport osimport copyprint("Pytorch version:",torch.__version__)print("torchvision version:",torchvision.__version__)
运行结果
三、数据输入
数据集——>我在这里
链接:https://pan.baidu.com/s/1G3yRfKTQf9sIq1iCSoymWQ
提取码:1234
#%%输入data_dir="D:\Python\Pytorch\data\hymenoptera_data"# 从[resnet,alexnet,vgg,squeezenet,desenet,inception]model_name='squeezenet'# 数据集中类别数量num_classes=2# 训练的批量大小batch_size=8# 训练epoch数num_epochs=15# 用于特征提取的标志。为FALSE,微调整个模型,为TRUE只更新图层参数feature_extract=True
四、辅助函数
1、模型训练和验证
train_model函数处理给定模型的训练和验证。作为输入,它需要PyTorch模型、数据加载器字典、损失函数、优化器、用于训练和验 证epoch数,以及当模型是初始模型时的布尔标志。
is_inception标志用于容纳 Inception v3 模型,因为该体系结构使用辅助输出, 并且整体模型损失涉及辅助输出和最终输出,如此处所述。 这个函数训练指定数量的epoch,并且在每个epoch之后运行完整的验证步骤。它还跟踪最佳性能的模型(从验证准确率方面),并在训练 结束时返回性能最好的模型。在每个epoch之后,打印训练和验证正确率。
#%%模型训练和验证device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")def train_model(model,dataloaders,criterion,optimizer,num_epochs=25,is_inception=False): since=time.time() val_acc_history=[] best_model_wts=copy.deepcopy(model.state_dict()) best_acc=0.0 for epoch in range(num_epochs): print('Epoch{}/{}'.format(epoch, num_epochs-1)) print('-'*10) # 每个epoch都有一个训练和验证阶段 for phase in['train','val']: if phase=='train': model.train() else: model.eval() running_loss=0.0 running_corrects=0 # 迭代数据 for inputs,labels in dataloaders[phase]: inputs=inputs.to(device) labels=labels.to(device) # 梯度置零 optimizer.zero_grad() # 向前传播 with torch.set_grad_enabled(phase=='train'): # 获取模型输出并计算损失,开始的特殊情况在训练中他有一个辅助输出 # 在训练模式下,通过将最终输出和辅助输出相加来计算损耗,在测试中值考虑最终输出 if is_inception and phase=='train': outputs,aux_outputs=model(inputs) loss1=criterion(outputs,labels) loss2=criterion(aux_outputs,labels) loss=loss1+0.4*loss2 else: 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)) if phase=='train' and epoch_acc>best_acc: best_acc=epoch_acc best_model_wts=copy.deepcopy(model.state_dict()) if phase=='val': val_acc_history.append(epoch_acc) print() time_elapsed=time.time()-since print('training complete in {:.0f}s'.format(time_elapsed//60, time_elapsed%60)) print('best val acc:{:.4f}'.format(best_acc)) model.load_state_dict(best_model_wts) return model,val_acc_history
2、设置模型参数的'.requires_grad属性'
当我们进行特征提取时,此辅助函数将模型中参数的 .requires_grad 属性设置为False。
默认情况下,当我们加载一个预训练模型时,所有参数都是 .requires_grad = True
,如果我们从头开始训练或微调,这种设置就没问题。
但是,如果我们要运行特征提取并且只想为新初始化的层计算梯度,那么我们希望所有其他参数不需要梯度变化。
#%%设置模型参数的.require——grad属性def set_parameter_requires_grad(model,feature_extracting): if feature_extracting: for param in model.parameters(): param.require_grad=False
关于如何深入理解Pytorch微调torchvision模型问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网行业资讯频道了解更多相关知识。