Datawhale AI夏令营第三期 - 脑PET图像分析和疾病预测挑战赛——Baseline修改及优化

(一)Datawhale AI夏令营第三期 - 脑PET图像分析和疾病预测挑战赛——环境搭建及 PyTorch Baseline跑通

上期完成Baseline跑通后,这期主要是对Baseline的优化,整队图像分类问题,主要有以下几类优化方法。

Baseline优化的常见方法

1.图像增强

由于本次任务提供的训练集较少,正负样本各25个,共计50个训练样本,因此需对图像进行增强。以下是进行图像增强的方法

首先安装并引入数据增强库albumentations

import albumentations as A
pip install albumentations

在读取数据时设置图像增强 

train_loader = torch.utils.data.DataLoader(
    XunFeiDataset(train_path[:-10],
            A.Compose([
            A.RandomRotate90(),#随机旋转90度
            A.RandomCrop(120, 120),#随机裁剪
            A.HorizontalFlip(p=0.5),#随机水平翻转
            A.RandomBrightnessContrast(p=0.5),#随机亮度对比度
        ])
    ), batch_size=2, shuffle=True, num_workers=0, pin_memory=False
)

上面代码主要对图像做了以下增强,由于数据集的图片为灰度的医学图像,不够直观,所有下面采用网图进行举例,增强效果案例左边为原图,右边为增强后图片

A.RandomRotate90(),#随机旋转90度(括号内可添加参数p(0-1)表示旋转概率)

在这里插入图片描述

 A.RandomCrop(120, 120),#随机裁剪

将图像随机截取120*120大小部分

在这里插入图片描述

A.HorizontalFlip(p=0.5),#随机水平翻转,翻转概率为50%

在这里插入图片描述

 A.RandomBrightnessContrast(p=0.5),#随机亮度对比度概率为50%

在这里插入图片描述

除此之外,还有RGBShift(RGB平移),RandomGamma 随机Gamma 等方法,大家可以参考

albumentations官方文档

Albumentations数据增强方法

针对灰度图像RGB平移这一类方法不会起作用,一般增加对比度和亮度效果比较明显

2.调整验证方式为交叉验证

交叉验证(Cross-Validation,简称CV)是一种在机器学习中用于评估模型性能和选择参数的技术。它的目标是充分利用有限的数据,减少因数据分布不均匀或随机性带来的评估误差。交叉验证将数据分成多个子集(折叠),然后多次训练和测试模型,以获取更准确的性能评估。

 

本次直接使用sk-learn的交叉验证库

首先引入对应库 

from sklearn.model_selection import train_test_split, StratifiedKFold, KFold

随后设置K者基本参数

#n_splits=10设置为10折验证
#random_state=233设置随机状态为233(这里随便设置一个整数就行了)
#shuffle=True开启数据随机打乱
skf = KFold(n_splits=10, random_state=233, shuffle=True)

在数据载入时使用交叉验证方式(对于新版的numpy有一个小坑,需要使用np.array(train_path)将数组转换为np arry才能运行,不然会报错)

for fold_idx, (train_idx, val_idx) in enumerate(skf.split(train_path, train_path)):
    #测试集读取
    train_loader = torch.utils.data.DataLoader(
        XunFeiDataset(np.array(train_path)[train_idx],#此处需将train_path这个数组前置转换为np arry
                A.Compose([
                A.RandomRotate90(),
                A.RandomCrop(120, 120),
                A.HorizontalFlip(p=0.5),
                A.RandomBrightnessContrast(p=0.5),
                # A.RandomGamma(),
            ])
        ), batch_size=1, shuffle=True, num_workers=0, pin_memory=False
    )
    #验证集读取
    val_loader = torch.utils.data.DataLoader(
    XunFeiDataset(np.array(train_path)[val_idx],#针对原始的数据读取方法主要就是修改了这里
            A.Compose([
            A.RandomCrop(120, 120),
            A.RandomRotate90(),
            A.HorizontalFlip(p=0.5),
            A.RandomBrightnessContrast(p=0.5),
            # A.RandomGamma(),
        ])
    ), batch_size=1, shuffle=False, num_workers=0, pin_memory=False
)

设置模型训练参数并进行模型训练

    model = XunFeiNet()#设置训练模型
    model = model.to('cuda')#选择使用cuda训练
    criterion = nn.CrossEntropyLoss().cuda()#设置损失函数
    optimizer = torch.optim.AdamW(model.parameters(), 0.001)#设置优化器及学习率
    for _  in range(10):#进行十次训练
        train_loss = train(train_loader, model, criterion, optimizer)
        val_acc  = validate(val_loader, model, criterion)
        train_acc = validate(train_loader, model, criterion)

        print(train_loss, train_acc, val_acc)输出训练损失,训练集准确率,验证集准确率
        torch.save(model.state_dict(), './resnet18_fold{0}.pt'.format(fold_idx))#将该折模型参数保存起来

预测时使用多模型进行预测

pred = None

for model_path in ['resnet18_fold0.pt', 'resnet18_fold1.pt', 'resnet18_fold2.pt',
                  'resnet18_fold3.pt', 'resnet18_fold4.pt', 'resnet18_fold5.pt',
                  'resnet18_fold6.pt', 'resnet18_fold7.pt', 'resnet18_fold8.pt',
                  'resnet18_fold9.pt']:
         
    model = XunFeiNet()#设置预测模型
    model = model.to('cuda')#设置为cuda计算
    model.load_state_dict(torch.load(model_path))#读取模型参数
    #进行模型预测
    for _ in range(10):
        if pred is None:
            pred = predict(test_loader, model, criterion)
        else:
            pred += predict(test_loader, model, criterion)

3.更换模型

原Baseline使用的是Resnet18模型,也可进行模型更换;来提高模型效果,更换模型后主要需要修改两个地方,第一个是模型的第一层,一个是模型的最后层输出层,下面已将Resnet18更换为Vgg19进行举例:

原始Baseline Resnet18代码如下:

class XunFeiNet(nn.Module):
    def __init__(self):
        super(XunFeiNet, self).__init__()
                
        model = models.resnet18(True)
        model.conv1 = torch.nn.Conv2d(50, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
        model.avgpool = nn.AdaptiveAvgPool2d(1)
        model.fc = nn.Linear(512, 2)
        self.resnet = model
        
    def forward(self, img):        
        out = self.resnet(img)
        return out

首先我们需要查看vgg19网络模型结构,如下图

 

针对以上网络模型主要修改如下 

1.默认的Vgg19是针对RGB图像的因此默认输入适配3通道图像,本次Baseline使用50通道图像,因此需修改第一层

2.默认vgg19模型最后输出为1000个分类,本次Baseline为2分类问题,因此需要修改最后的全连接层输出为2

修改后代码如下:

class XunFeiNet(nn.Module):
    def __init__(self):
        super(XunFeiNet, self).__init__()
        model = models.vgg19(True)#修改模型为vgg19并启用预训练模型
        model.features[0]=nn.Conv2d(50, 16, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)#将第一层输入修改为本次数据的50通道
        model.classifier[6]=nn.Linear(4096,2,bias=True)#将最后一程输出修改为2
        self.resnet = model

    def forward(self, img):
        out = self.resnet(img)
        return out

经过以上调整,成功将分数提升到了0.74214,后续将继续对模型进行优化

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值