- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
前期工作
- 语言环境: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