【深度学习打卡】第六周:好莱坞明星识别

第5周:运动鞋识别
🍨 本文为🔗365天深度学习训练营中的学习记录博客
🍦 参考文章:365天深度学习训练营-第六周:好莱坞明星识别
🍖 原作者:K同学啊 | 接辅导、项目定制
🚀 文章来源:K同学的学习圈子

学习目标:
要求:
保存训练过程中的最佳模型权重
调用官方的VGG-16网络框架
拔高:
保存训练过程中的最佳模型权重
调整代码使得测试集的accuracy达到86%

学习内容:
一、前期准备
1.1 设置GPU

import torch
import torch.nn as nn
from torchvision import transforms,datasets
import os,PIL,pathlib,warnings

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

1.2 导入数据

import os,PIL,random,pathlib
data_dir = './6-data'
data_dir = pathlib.Path(data_dir)
# print(data_dir) #6-data
data_paths = list(data_dir.glob("*"))
# print(data_paths) # 返回data_dir路径下所有子文件的路径,返回的是一个列表
classNames = [str(path).split('\\')[1] for path in data_paths]  # 类别的名称
print(classNames)
train_transforms = transforms.Compose([transforms.Resize([224,224]),
                                    transforms.ToTensor(),
                                    transforms.Normalize(
                                            mean = [0.485, 0.456, 0.406],
                                            std = [0.229, 0.224, 0.225])])
total_data = datasets.ImageFolder('./6-data', transform = train_transforms)
total_data

1.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 = 1
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)

二、调用官方的VGG-16模型
VGG-16结构说明:

13个卷积层(convolutional layer),
3个全连接层(full connected layer)
5个池化层(pool layer)

在这里插入图片描述
在这里插入图片描述

from torchvision.models import vgg16
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print('Using {} device'.format(device))
# 加载预训练模型,并且对模型进行微调
model = vgg16(pretrained=True).to(device)

for param in model.parameters():
    param.requires_grad = False # 冻结模型的参数,在训练的时候之训练最后一层的参数
    
# 修改classfier模块的第6层
model.classifier._modules['6'] = nn.Linear(4096,len(classNames))
model.to(device)
model

三、训练模型
3.1 编写训练函数

def train(dataloader, model, loss_fun, optim):
    size = len(dataloader.dataset)  # 训练集的大小
    num_batches = len(dataloader) # 批次数目
    
    train_acc, train_loss = 0, 0
    for x, y in dataloader:
        x,y = x.to(device), y.to(device)
        # 计算误差
        preds = model(x)
        loss = loss_fun(preds, y) 
        
        # 反向传播
        optimizer.zero_grad() # grad属性归零
        loss.backward()  # 反向传播
        optimizer.step() # 每一步自动更新
        
        # 记录loss与acc
        train_acc += (preds.argmax(1)==y).sum().item()
        train_loss += loss.item()
    train_acc /= size
    train_loss /= num_batches
    return train_acc, train_loss

3.2 .编写测试函数

def test(dataloader, model, loss_fun):
    size = len(dataloader.dataset) # 测试集大小
    num_batches = len(dataloader)
    
    test_acc, test_loss = 0, 0
    with torch.no_grad():
        for x, y in dataloader:
            x, y = x.to(device), y.to(device)
            
            # 计算loss
            preds = model(x)
            loss = loss_fun(preds, y)
            
            test_loss += loss.item()
            test_acc += (preds.argmax(1) == y).sum().item()
    test_acc /= size
    test_loss /= num_batches
    return test_acc, test_loss

3.3 设置动态学习率¶

def adjust_learning_rate(optimizer, epoch, start_lr):
    # 每2个epoch衰减为原来的0.98
    lr = start_lr * (0.98 ** (epoch//2))
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr
learn_rate = 1e-4 # 初始学习率
optimizer = torch.optim.SGD(model.parameters(), lr = learn_rate)

3.4 正式训练

# 注意如何保存最佳模型
import copy 
loss_fun = nn.CrossEntropyLoss() # 创建损失函数
epochs = 40

train_loss = []
train_acc = []
test_loss = []
test_acc = []

best_acc = 0 # 设置一个最佳准确率,作为判别指标
for epoch in range(epochs):
    # 更新学习率
    adjust_learning_rate(optimizer, epoch, learn_rate) # 使用自定义学习率
    model.train()
    epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fun, optimizer)
    
    model.eval()
    epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fun)
    
    # 保存最佳模型到best_model
    if epoch_test_acc > best_acc:
        best_acc = epoch_test_acc
        best_model = copy.deepcopy(model)
    train_acc.append(epoch_train_acc)
    train_loss.append(epoch_train_loss)
    test_acc.append(epoch_test_acc)
    test_loss.append(epoch_test_loss)
    # 获取当前的学习率
    lr = optimizer.state_dict()['param_groups'][0]['lr']
    
    template = ('Epoch:{:2d}, Train_acc:{:.2f}%, Train_loss:{:.3f}, Test_acc:{:.2f}%, Test_loss:{:.3f}, Lr:{:.2E}')
    print(template.format(epoch+1, epoch_train_acc, epoch_train_loss, epoch_test_acc, epoch_test_loss, lr))

# 保存最佳模型到文件中
PATH = './best_model.pth' # 保存参数文件名
torch.save(model.state_dict(), PATH)

print('DONE!')

在这里插入图片描述

四、结果可视化
4.1 Loss 与 Accuracy图

import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore') # 忽略警告信息
def myplot(train_acc, train_loss, test_acc, test_loss):
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False 
    plt.rcParams['figure.dpi'] = 200
    
    epoch_range = range(len(train_acc))
    plt.figure(figsize=(12,3))
    plt.subplot(1,2,1)
    
    plt.plot(epoch_range, train_acc, label='Training Accuracy')
    plt.plot(epoch_range, test_acc, label = 'Test Accuracy')
    plt.legend(loc='lower right')
    plt.title('Training and Test Accuracy')
    
    plt.subplot(1,2,2)
    plt.plot(epoch_range, train_loss, label='Training Loss')
    plt.plot(epoch_range, test_loss, label='Test Loss')
    plt.legend(loc='upper right')
    plt.title('Training and Test Loss')
    
    plt.show()
myplot(train_acc, train_loss, test_acc, test_loss)

在这里插入图片描述
4.2 指定图片进行预测
torch.squeeze():对数据维数进行压缩,去掉位数为1的维数
torch.squeeze(input, dim=None,* ) torch.unqueeze(input, dim=None,* ):对数据维数进行升维,加上维数为1的维度

from PIL import Image
classes = list(total_data.class_to_idx)
def predict_one_image(image_path, model, transforms, classes):
    test_img = Image.open(image_path).convert('RGB')
    
    test_img = transforms(test_img)
    img = test_img.to(device).unsqueeze(0)
    
    model.eval()
    output = model(img)
    
    _,pred = torch.max(output, 1)
    pred_class = classes[pred]
    
    print(f'预测结果是:{pred_class}')
    # 预测训练集中的某张图片
predict_one_image(image_path='./6-data/Angelina Jolie/002_8f8da10e.jpg',model=model, transforms=train_transforms, classes=classes)

在这里插入图片描述
4.3 4模型评估¶

best_model.eval()
epoch_test_acc, epoch_test_loss = test(test_dl, best_model, loss_fun)
best_model.eval()
epoch_test_acc, epoch_test_loss = test(test_dl, best_model, loss_fun)

在这里插入图片描述

# 查看是否与记录的保存一致
epoch_test_acc,epoch_test_loss

在这里插入图片描述

五、总结
1.本周回顾了上周所学的动态学习率以及它的怎么用代码实现,几乎所有的神经网络采取的都是梯度下降法.学习率和权重更新的快慢相关,学习率过大,可能花费更少的时间收敛到最优权重。然而,学习速率过大会导致跳动过大,不够准确以致于达不到最优点。学习率过低,收敛到最优权重的时间就更长。所以在模型训练的初期,可以将学习率设置为随着迭代次数的增加,逐渐减小,保证模型在训练后期不会有太大的波动,从而最终接近最优解。
2.本周学习了如何调用官方的VGG网络架构,并且保存训练过程中最佳的模型权重。
学习率理解与分类

————————————————
版权声明:本文为CSDN博主「m0_45216728」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_45216728/article/details/134868606

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值