第J6周:ResNeXt-50实战解析

前期工作

  • 语言环境:Python3.9.18
  • 编译器:Jupyter Lab
  • 深度学习环境:Pytorch 1.12.1

1.设置GPU

import torch
import torch.nn as nn
import torchvision
from torchvision import transforms,datasets

import os,PIL,random,pathlib

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device

2. 导入数据

import os,PIL,random,pathlib

data_dir = "F:/365data/P4/"
data_dir = pathlib.Path(data_dir)

data_paths = list(data_dir.glob('*'))
classeNames = [str(path).split("\\")[3] for path in data_paths]
classeNames
total_datadir = 'F:/365data/P4/'

train_transforms = transforms.Compose([
    transforms.Resize([224, 224]),  # 将输入图片resize成统一尺寸
    transforms.ToTensor(),          # 将PIL Image或numpy.ndarray转换为tensor,并归一化到[0,1]之间
    transforms.Normalize(           # 标准化处理-->转换为标准正太分布(高斯分布),使模型更容易收敛
        mean=[0.485, 0.456, 0.406], 
        std=[0.229, 0.224, 0.225])  # 其中 mean=[0.485,0.456,0.406]与std=[0.229,0.224,0.225] 从数据集中随机抽样计算得到的。
])

total_data = datasets.ImageFolder(total_datadir,transform=train_transforms)
total_data

3.划分训练集测试集

train_size = int(0.8 * len(total_data))
test_size  = len(total_data) - train_size
train_dataset, test_dataset = torch.utils.data.random_split(total_data, [train_size, test_size])
train_dataset, test_dataset
batch_size = 32

train_dl = torch.utils.data.DataLoader(train_dataset,
                                           batch_size=batch_size,
                                           shuffle=True,
                                           num_workers=1)
test_dl = torch.utils.data.DataLoader(test_dataset,
                                          batch_size=batch_size,
                                          shuffle=True,
                                          num_workers=1)
for X, y in test_dl:
    print("Shape of X [N, C, H, W]: ", X.shape)
    print("Shape of y: ", y.shape, y.dtype)
    break

4.数据可视化

import matplotlib.pyplot as plt 
from PIL import Image

image_folder = 'F:/365data/P4/Monkeypox/'

image_files = [f for f in os.listdir(image_folder) if f.endswith(('.jpg','.jpeg','.png'))]

fig,axes = plt.subplots(3,8,figsize=(16,6))

for ax,img_file in zip(axes.flat,image_files):
    img_path = os.path.join(image_folder,img_file)
    img = PIL.Image.open(img_path)
    ax.imshow(img)
    ax.axis('off')

plt.tight_layout()
plt.show()

二、构建ResNet-50模型

1.构造模型

import torch.nn.functional as F

# 构造ResNeXt50模型
class ResNeXtblock(nn.Module):
    def __init__(self,in_channels,out_channels,stride=1,carinality=32):
        super(ResNeXtblock,self).__init__()
        D = out_channels*2
        C = carinality
        self.blockconv = nn.Sequential(
            nn.Conv2d(in_channels,out_channels*2,kernel_size=1,stride=stride),
            nn.BatchNorm2d(out_channels*2),
            nn.ReLU(),
            nn.Conv2d(out_channels*2,out_channels*2,kernel_size=3,stride=1,padding=1,groups=C),
            nn.BatchNorm2d(out_channels*2),
            nn.ReLU(),
            nn.Conv2d(out_channels*2,out_channels*4,kernel_size=1,stride=1),
            nn.BatchNorm2d(out_channels*4)
        )
        if stride !=1 or in_channels != out_channels*4:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels,out_channels*4,kernel_size=1,stride=stride),
                nn.BatchNorm2d(out_channels*4)
            )

    def forward(self,x):
            residual = x 
            out = self.blockconv(x)
            if hasattr(self,'shortcut'):
                residual = self.shortcut(x)
            out += residual
            out = F.relu(out)
            return out
    
class ResNeXt50(nn.Module):
    def __init__(self,block,num_classes=1000):
          super(ResNeXt50,self).__init__()

          self.conv1 = nn.Sequential(
               nn.ZeroPad2d(3),
               nn.Conv2d(3,64,kernel_size=7,stride=2),
               nn.BatchNorm2d(64),
               nn.ReLU(),
               nn.MaxPool2d((3,3),stride=2)
          )
          self.in_channels = 64

          self.layer1 = self.make_layer(ResNeXtblock,64,3,stride =1)
          self.layer2 = self.make_layer(ResNeXtblock,128,4,stride=2) # 设置步长是为了减小特征图的尺寸,即宽高缩小一倍:1、捕捉到更大范围内的上下文信息2、有效减少模型参数数量和计算量,有助于控制模型复杂性和防止过拟合。
          self.layer3 = self.make_layer(ResNeXtblock,256,6,stride=2)
          self.layer4 = self.make_layer(ResNeXtblock,512,3,stride=2)

          self.avgpool = nn.AvgPool2d((7,7))
          self.fc = nn.Linear(512*4,num_classes)

    def make_layer(self,block,channels,num_blocks,stride=1):
         strides = [stride] + [1]*(num_blocks-1)
         layers = []
         
         for stride in strides:
              layers.append(block(self.in_channels,channels,stride))
              self.in_channels = channels*4
              
         return nn.Sequential(*layers)
         
    def forward(self,x):
         out = self.conv1(x)
         out = self.layer1(out)
         out = self.layer2(out)
         out = self.layer3(out)
         out = self.layer4(out)
         out = self.avgpool(out)
         out = out.view(out.size(0),-1)
         out = self.fc(out)

         return out
import re
import torch.utils.model_zoo as model_zoo
from torchvision.models.resnet import model_urls

def resnet50(pretrained=False,**kwargs):
    model = ResNeXt50(block=ResNeXtblock,num_classes=len(classeNames),**kwargs)

    if pretrained:
        state_dict = model_zoo.load_url(model_urls['resnet50'])
        state_dict.pop('fc.weight')
        state_dict.pop('fc.bias')
        model.load_state_dict(state_dict,strict=False)
        nn.init.kaiming_normal_(model.fc.weight)
        nn.init.zeros_(model.fc.bias)
    
    return model

model = resnet50(pretrained=False).to(device)
model

2. 统计模型参数

# 统计模型参数量以及其他指标
import torchsummary as summary
summary.summary(model, (3, 224
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值