04pytorch入门肺部感染识别案例

肺部感染识别案例

案例的主要流程:

第一步:加载预训练模型ResNet,该模型已在ImageNet上训练过

第二部:冻结预训练模型中底层卷积层的参数(权重)

第三步:用可训练参数的多层替换分类层

第四步:在训练集上训练分类层

第五步:微调超参数,根据需要解冻更多层。

在这里插入图片描述

显示数据集中的图片代码:

# 1 加载库
import torch
import torch.nn as nn
from torchvision import datasets, transforms
import os
from torch.utils.data import DataLoader
from torchvision.utils import make_grid
import matplotlib.pyplot as plt
import numpy as np


# 2 定义一个方法:显示图片
def image_show(inp, title=None):
    plt.figure(figsize=(14, 3))
    inp = inp.numpy().transpose((1,2,0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    inp = std * inp + mean
    inp = np.clip(inp, 0, 1)
    plt.imshow(inp)
    if title is not None:
        plt.title(title)
    plt.pause(0.001)
    plt.show()


def main():
    # 3 定义超参数
    BATCH_SIZE = 8 # 每批处理的数据数量
    DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    # 4 图片转换
    data_transforms = {
        'train':
            transforms.Compose([
                transforms.Resize(300),
                transforms.RandomResizedCrop(300),
                transforms.RandomHorizontalFlip(),
                transforms.CenterCrop(256),
                transforms.ToTensor(),
                transforms.Normalize([0.485, 0.456, 0.406],
                                     [0.229, 0.224, 0.225])
            ]),

        'val':
            transforms.Compose([
                transforms.Resize(300),
                transforms.CenterCrop(256),
                transforms.ToTensor(),
                transforms.Normalize([0.485, 0.456, 0.406],
                                     [0.229, 0.224, 0.225])
            ])
    }

    # 5 操作数据集
    # 5.1 数据集路径
    data_path = "./chest_xray/" # "F:\桌面\04 轻松学PyTorch 肺部感染识别案例\chest_xray"
    # 5.2 加载数据集train 和 val
    image_datasets = { x : datasets.ImageFolder(os.path.join(data_path, x),
                                                data_transforms[x]) for x in ['train', 'val']}
    # 5.3 为数据集创建一个迭代器,读取数据
    datalaoders = {x : DataLoader(image_datasets[x], shuffle=True,
                                  batch_size=BATCH_SIZE) for x in ['train', 'val']}

    # 5.3 训练集和验证集的大小(图片的数量)
    data_sizes = {x : len(image_datasets[x]) for x in ['train', 'val']}

    # 5.4 获取标签的类别名称:  NORMAL 正常 --- PNEUMONIA 感染
    target_names = image_datasets['train'].classes

    # 6 显示一个batch_size的图片(8张图片)
    # 6.1 读取8张图片
    datas, targets = next(iter(datalaoders['train']))
    # 6.2 将若干张图片拼成一幅图像
    out = make_grid(datas, nrow=4, padding=10)
    # 6.3 显示图片
    image_show(out, title=[target_names[x] for x in targets])


if __name__ == '__main__':
    main()

迁移学习,模型微调

迁移学习:就是把以及训练好的模型参数迁移到新的模型来帮助新的模型训练

网络–>大数据集–>模型–>模型微调–>新数据集–>新模型

迁移学习

# 8 更改池化层
class AdaptiveConcatPool2d(nn.Module):
    def __init__(self, size=None):
        super().__init__()
        size = size or (1, 1) # 池化层的卷积核大小,默认值为(1,1)
        self.pool_one = nn.AdaptiveAvgPool2d(size) # 池化层1
        self.pool_two = nn.AdaptiveAvgPool2d(size) # 池化层2

    def forward(self, x):
        return torch.cat([self.pool_one(x), self.pool_two(x), 1]) # 连接两个池化层

# 7 迁移学习:拿到一个成熟的模型,进行模型微调
def get_model():
    model_pre = models.resnet50(pretrained=True) # 获取预训练模型
    # 冻结预训练模型中所有的参数
    for param in model_pre.parameters():
        param.requires_grad = False
    # 微调模型:替换ResNet最后的两层网络,返回一个新的模型
    model_pre.avgpool = AdaptiveConcatPool2d() # 池化层替换
    model_pre.fc = nn.Sequential(
        nn.Flatten(), # 所有维度拉平
        nn.BatchNorm1d(4096), # 256 x 6 x 6   ——> 4096
        nn.Dropout(0.5),  # 丢掉一些神经元
        nn.Linear(4096, 512),  # 线性层的处理
        nn.ReLU(), # 激活层
        nn.BatchNorm1d(512), # 正则化处理
        nn.Linear(512,2),
        nn.LogSoftmax(dim=1), # 损失函数
    )

    return model_pre

定义训练函数

# 9 定义训练函数
def train(model,device,train_loader,criterion,optimizer,epoch,writer):
    model.train()
    total_loss = 0.0 # 总损失值初始化为0
    # 循环读取训练数据集,更新模型参数
    for batch_id ,(data,target) in enumerate(train_loader):
        data,target = data.to(device),target.to(device)
        optimizer.zero_grad() # 梯度初始化为0
        output = model(data) #训练后的输出
        loss = criterion(output,target) # 计算损失
        loss.backward() # 反向传播
        optimizer.step() # 更新参数
        total_loss+=loss #累计训练损失

    writer.add_scaler("Train Loss",total_loss/len(train_loader),epoch)
    writer.flush() # 刷新
    return total_loss/len(train_loader) # 返回平均损失值

定义测试函数

# 10 定义测试函数
def test(model, device, test_loader, criterion,  epoch, writer):
    model.eval()
    # 损失和正确
    total_loss = 0.0  # 总损失值初始化为0
    correct =0.0
    # 循环读取训练数据集,更新模型参数
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            # 预测输出
            output = model(data)
            total_loss +=criterion(output, target).item()  # 计算损失
            # 获取预测结果中每行数据概率最大的下标
            _,preds = torch.max(output,dim=1)
            #累计预测正确的个数
            correct += torch.sum(preds==target)
        #平均损失
        total_loss/=len(test_loader)
        #正确率
        accuracy = correct/len(test_loader)
        # 写入日志
        writer.add_scaler("Test Loss", total_loss , epoch)
        writer.add_scaler("Accuracy", accuracy, epoch)
        writer.flush()  # 刷新
        # 输出信息
        print("Test Loss : {:.4f},Accuracy : {:.4f} ".format(total_loss,accuracy))
        return total_loss ,accuracy # 返回损失值和正确率

racy, epoch)
writer.flush() # 刷新
# 输出信息
print("Test Loss : {:.4f},Accuracy : {:.4f} ".format(total_loss,accuracy))
return total_loss ,accuracy # 返回损失值和正确率


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值