- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
五月初五迎端午,今天是假期的第一天,想必大家有关于这个节日的记忆都是粽子和龙舟。而端午的由来大多数人将它视为纪念爱国诗人屈原,而屈原最为人所知的便是《离骚》中的“路漫漫其修远兮,吾将上下而求索”。而我们正在求索的路上不断前行。
今天尝试用Jupyter失败,在进行到可视化步骤的时候会出现"The kernel has died, and the automatic restart has failed",未能找到原因,随后改用Google colab完成。在第一次循环的对比中,CPU和GPU的测试准确率差距似乎较大,有没有大佬解答一下这个问题❓
实验目的:
- 要求:了解如何设置动态学习率(重点),调整代码使测试集accuracy到达84%
- 拔高:保存训练过程中的最佳模型权重,调整代码使测试集accuracy到达86%
实验环境:
- 语言环境:python 3.8
- 编译器:Google colab
- 深度学习环境:Pytorch
实验流程:
1. 设置GPU
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torchvision import transforms, datasets
import os,PIL,pathlib
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device
🪧代码输出
device(type='cuda')
2. 导入数据
前边几次实验使用这条代码最后输出classeNames都没问题,但是这次将这段代码"classeNames = [str(path).split(“\”)[1] for path in data_paths]"改成下面的才能输出下一级目录的名字
import os,PIL,random,pathlib
data_dir = '/content/drive/MyDrive/P5'
data_dir = pathlib.Path(data_dir)
data_paths = list(data_dir.glob('*'))
# Use the correct index to extract the class name or use a more robust method
classeNames = [path.name for path in data_paths]
print(classeNames)
🪧代码输出
['test', 'train']
train_transforms = transforms.Compose([
transforms.Resize([224, 224]), # 将输入图片resize成统一尺寸
# transforms.RandomHorizontalFlip(), # 随机水平翻转
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] 从数据集中随机抽样计算得到。
])
test_transform = 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] 从数据集中随机抽样计算得到。
])
train_dataset = datasets.ImageFolder("/content/drive/MyDrive/P5/train/",transform=train_transforms)
test_dataset = datasets.ImageFolder("/content/drive/MyDrive/P5/test/",transform=train_transforms)
train_dataset.class_to_idx
🪧代码输出
{
'adidas': 0, 'nike': 1}
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
🪧代码输出
Shape of X [N, C, H, W]: torch.Size([32, 3, 224, 224])
Shape of y: torch.Size([32]) torch.int64
3. 构建CNN网络
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv1=nn.Sequential(
nn.Conv2d(3, 12, kernel_size=5, padding=0), # 12*220*220
nn.BatchNorm2d(12),
nn.ReLU())
self.conv2=nn.Sequential(
nn.Conv2d(12, 12, kernel_size=5, padding=0), # 12*216*216
nn.BatchNorm2d(12),
nn.ReLU())
self.pool3=nn.Sequential(
nn.MaxPool2d(2)) # 12*108*108
self.conv4=nn.Sequential(
nn.Conv2d(12, 24, kernel_size=5, padding=0), # 24*104*104
nn.BatchNorm2d(24),
nn.ReLU())
self.conv5=nn.Sequential(
nn.Conv2d(24, 24, kernel_size=5, padding=0), # 24*100*100
nn.BatchNorm2d(24),
nn.ReLU())
self.pool6=nn.Sequential(
nn.MaxPool2d(2)) # 24*50*50
self.dropout = nn.Sequential(
nn.Dropout(0.2))
self.fc=nn.Sequential(
nn.Linear(24*50*50, len(classeNames)))
def forward(self, x):
batch_size = x.size(0)
x = self.conv1(x) # 卷积-BN-激活
x = self.conv2(x) # 卷积-BN-激活
x = self.pool3(x) # 池化
x = self.conv4(x) # 卷积-BN-激活
x = self.conv5(x) # 卷积-BN-激活
x = self.pool6(x) # 池化
x = self.dropout(x)
x = x.view(batch_size, -1) # flatten 变成全连接网络需要的输入 (batch, 24*50*50) ==> (batch, -1), -1 此处自动算出的是24*50*50
x = self.fc(x)
return x
device = "cuda" if torch.cuda.is_available() else "cpu"
print("Using {} device".format(device))
model = Model().to(device)
model
Model(
(conv1): Sequential(
(0): Conv2d(3, 12, kernel_size=(5, 5), stride=(1, 1))
(1): BatchNorm2d(12, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
)
(conv2): Sequential(
(0): Conv2d(12, 12, kernel_size=(5, 5), stride=(1, 1))
(1): BatchNorm2d(12, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU