初学记录:一次较为完整的使用res18微调CIFAR-10数据集

最近在想着复现自己的第一篇论文,但是医学图像的处理方面对于初次接触它的我来说还是抽象了一点,花了一个星期勉强跟着视频操作了一下,对于这种没有文档的软件学习使用感觉需要更多的成本啊(碎碎念)

于是,我就一个星期没有正经编程了,今天上课正好无聊梳理了一下自己使用pytorch进行官方数据集识别的一个小过程,写下来算是复习一下吧

参考教材:跟李沐学ai文字版教程

使用res18微调CIFAE-10数据集

1. 加载数据集

CIFAR-10数据集,pytorch官方数据集,总共60000个样本,训练样本50000个,测试样本10000个。样本规模:34×34,特点:颜色和大小差异更为明显

1.1 pytorch加载数据集的流程

  • Dataset定义数据的格式和数据的变换形式
  • Dataloader使用iter形式读入批次数据

1.2 pytorch读入数据和加载的两种方式(这里只用第一种)

  • 加载pytorch内置的数据集(MNIST、CIFAR-10之类的)
  • 读入自己的数据集,需要自定义Dataset。提供一个初学者理解的项目树叶分类
    • (在最高vote代码中完整展示了一个读入加载“自己”的数据集,然后微调res18识别一个较为复杂的数据集的全过程)
    加载训练数据集
    • train = True(训练数据)、train = False(测试数据)

    • root = 存储/读取CIFAR10的路径

    • download = True(下载)、false(不下载_保证你的路径下有的话,可以离线进行,不过有云为什么不用云要为难自己的电脑呢,平台好的当我没说)

      all_images = torchvision.datasets.CIFAR10(train = True,
              root="/content/drive/MyDrive/李沐深度学习/13. 计算机视觉/data", download=True)
      
      test_images = torchvision.datasets.CIFAR10(train = False,
                                             root="/content/drive/MyDrive/李沐深度学习/13. 计算机视觉/data", download=True)
      

2. 展示数据集

李沐的课程使用的d2l工具包,没有的话可以换一个(plt.imshow差不多的),安装不了的直接下载那个数据包放在文档上级目录加载就行了

总体展示一下

d2l.show_images([all_images[i][0] for i in range(20)],4,5,scale = 0.8)

mac贴图片太麻烦了,懒得贴了,自己看一下图片长啥样就行了,意思一下

图像的处理

# 使用RGB通道的均值和标准差进行通道的标准化,这个数值先别管是怎么来的,也可以删了,因为我暂时也不知道这是干嘛的捏
normalize = torchvision.transforms.Normalize(
  [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]
)
image_size = 224
train_augs = torchvision.transforms.Compose([
    torchvision.transforms.RandomHorizontalFlip(),
    torchvision.transforms.RandomVerticalFlip(),
    torchvision.transforms.Resize(image_size),
    # color_aug,
    # shape_aug,
    torchvision.transforms.ToTensor(),
    # 将图像的输入转换为四维张量,格式为
    # (批量大小,通道数,高度,宽度)——批量大小也就是输入个数
    normalize

])

test_augs = torchvision.transforms.Compose([
    torchvision.transforms.Resize(image_size),
    torchvision.transforms.ToTensor(),
    normalize
])

重点:为数据集使用dataset、dataloader进行加载(root自己改改)

# dataset:train的dataset
# 加载官方数据集的方式:调用torchvision.datasets.相应的数据集
# root(存放路径,没有的话download必须为true)
# train:true_训练集/false_测试集
# transform:图像处理方式
# download:路径没有是否下载

batch_size = 256
train_dataset = torchvision.datasets.CIFAR10(
            root="/content/drive/MyDrive/李沐深度学习/13. 计算机视觉/data",train=True,transform=train_augs,download=True)
train_dataloader = torch.utils.data.DataLoader(train_dataset,
        batch_size=batch_size,shuffle=True,
        num_workers=d2l.get_dataloader_workers(),drop_last=True)
test_dataset = torchvision.datasets.CIFAR10(
            root="/content/drive/MyDrive/李沐深度学习/13. 计算机视觉/data",train=False,transform=test_augs,download=True)
test_dataloader = torch.utils.data.DataLoader(test_dataset,
        batch_size=batch_size,shuffle=True,
        num_workers=d2l.get_dataloader_workers(),drop_last=True)

获取训练img和label(使用的plt.imshow)

import matplotlib.pyplot as plt
image,label = next(iter(train_dataloader))
print(image.shape,label.shape)
plt.imshow(image[0][0])

torch.Size([256, 1, 224, 224])
torch.Size([256])
<matplotlib.image.AxesImage at 0x7f19a043cc10>

详细说明一下pytorch中对于图像的四维张量表示
(cin,channels,h,w)

  • cin:输入样本数_256为一个批量大小的图片数
  • channels:通道数
  • h、w就不用说了(注意,原大小不是这个,直接放入res18需要224×224)

微调

原理:在远超训练样本的一个数据集上训练过的模型参数,即使输出样本与所需训练样本输出样本不相干,其训练参数仍被认为比随机初始化参数更为可靠。ImageNet数据集有超过1000w数据样本和1000类物品,我们实验的数据样本,哪怕是上面推荐的一个叶子分类的数据样本全部远远小于它。

使用微调进行迁移学习的步骤

  • 在源数据集(例如ImageNet数据集)上预训练神经网络模型,即源模型。
  • 创建一个新的神经网络模型,即目标模型。这将复制源模型上的所有模型设计及其参数(输出层除外)。我们假定这些模型参数包含从源数据集中学到的知识,这些知识也将适用于目标数据集。我们还假设源模型的输出层与源数据集的标签密切相关;因此不在目标模型中使用该层。
  • 向目标模型添加输出层,其输出数是目标数据集中的类别数。
  • 随机初始化该层的模型参数。在目标数据集(如椅子数据集)上训练目标模型。输出层将从头开始进行训练,而所有其他层的参数将根据源模型的参数进行微调。
pretrained_net.fc

使用记事本编程的可以直接查看使用ImageNet预训练的res18的输出层,out_features为1000,因为ImageNet中有1000类物品

我们的CIFAR-10只有10类物品,因此输出的全连接层应该是10
finetune_net = torchvision.models.resnet18(pretrained=True)
finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 10)
# 初始化输出层的参数,使用简单一点的分布输出也行,在这里影响不大
nn.init.xavier_uniform_(finetune_net.fc.weight)

定义微调函数

# 如果param_group=True,输出层中的模型参数将使用十倍的学习率
def train_fine_tuning(net, learning_rate, batch_size = 256, num_epochs=5,
                      param_group=True):
    train_iter = train_dataloader
    test_iter = test_dataloader
    devices = d2l.try_all_gpus()
    loss = nn.CrossEntropyLoss(reduction="none")
    # 这里自己理解。不行的话删了直接用else那里就很简单了
    if param_group:
        params_1x = [param for name, param in net.named_parameters()
             if name not in ["fc.weight", "fc.bias"]]
        trainer = torch.optim.SGD([{'params': params_1x},
                                   {'params': net.fc.parameters(),
                                    'lr': learning_rate * 10}],
                                lr=learning_rate, weight_decay=0.001)
    else:
        trainer = torch.optim.SGD(net.parameters(), lr=learning_rate,
                                  weight_decay=0.001)
    d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,
                   devices)

微调res18

train_fine_tuning(finetune_net, 5e-5)

res18的微调结果

训练这个花费时间不会很长,用免费算力应该是10分钟左右,比这个还慢的别折磨你的电脑了
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值