第P6周—好莱坞明星识别(2)

news2024/9/28 9:20:55

五、模型训练

# 训练循环
    def train(dataloader, model, loss_fn, optimizer):
        size = len(dataloader.dataset)  # 训练集的大小
        num_batches = len(dataloader)   # 批次数目

        train_loss, train_acc = 0, 0  # 初始化训练损失和正确率

        for X, y in dataloader:  # 获取图片及其标签
            X, y = X.to(device), y.to(device)

            # 计算预测误差
            pred = model(X)          # 网络输出
            loss = loss_fn(pred, y)  # 计算网络输出和真实值之间的差距,targets为真实值,计算二者差值即为损失

            # 反向传播
            optimizer.zero_grad()  # grad属性归零
            loss.backward()        # 反向传播
            optimizer.step()       # 每一步自动更新

            # 记录acc与loss
            train_acc += (pred.argmax(1) == y).type(torch.float).sum().item()
            train_loss += loss.item()

        train_acc  /= size
        train_loss /= num_batches

        return train_acc, train_loss

    # 测试函数
    def test(dataloader, model, loss_fn):
        size        = len(dataloader.dataset)  # 测试集的大小
        num_batches = len(dataloader)          # 批次数目,(size/batch_size,向上取整)
        test_loss, test_acc = 0, 0

        # 当不进行训练时,停止梯度更新,节省计算内存消耗
        with torch.no_grad():
            for imgs, target in dataloader:
                imgs, target = imgs.to(device), target.to(device)

                # 计算loss
                target_pred = model(imgs)
                loss        = loss_fn(target_pred, target)

                test_loss += loss.item()
                test_acc  += (target_pred.argmax(1) == target).type(torch.float).sum().item()

        test_acc  /= size
        test_loss /= num_batches

        return test_acc, test_loss

    ''' 自定义设置动态学习率 '''
    def adjust_learning_rate(optimizer, epoch, start_lr):
        # 每 2 个epoch衰减到原来的 0.92
        lr = start_lr * (0.92 ** (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)

    # 定义学习率调整函数
    lambda1 = lambda epoch: 0.92 ** (epoch // 4)
    scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1)  # 选定调整方法

    # 定义损失函数
    loss_fn = nn.CrossEntropyLoss()

    # 定义训练参数
    epochs = 40
    train_loss = []
    train_acc = []
    test_loss = []
    test_acc = []

    best_acc = 0  # 用于保存最佳模型的准确率

    for epoch in range(epochs):
        model.train()
        epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, optimizer)
        scheduler.step()  # 更新学习率(调用官方动态学习率接口时使用)

        model.eval()
        epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
    
        # 保存最佳模型到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:{:.1f}%, Train_loss:{:3f}, Test_acc:{:.1f}%, Test_loss:{:.3f}, lr:{:.2E}')
        print(template.format(epoch+1, epoch_train_acc*100, epoch_train_loss, epoch_test_acc*100, epoch_test_loss, lr))

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

    print('Done')

在非实时编译器中运行出现Python 脚本中使用多进程相关问题报错,问题通常发生在没有正确使用 if __name__ == '__main__': 块的情况下。为了解决这个问题,我将完整代码修改如下:

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

warnings.filterwarnings("ignore")

def main():
    # 您的现有代码放在这里
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    print(device)

    import os, PIL, random, pathlib

    data_dir = 'D:/P6/48-data/'
    data_dir = pathlib.Path(data_dir)

    data_path = list(data_dir.glob('*'))
    print(data_path)
    classname = [str(path).split("\\")[3] for path in data_path]
    print(classname)

    train_transforms = transforms.Compose([
        transforms.Resize([224, 224]),
        transforms.ToTensor(),
        transforms.Normalize(
            mean=[0.39354826, 0.41713402, 0.48036146],
            std=[0.25076334, 0.25809455, 0.28359835]
        )
    ])

    total_data = datasets.ImageFolder("D:/P6/48-data/", transform=train_transforms)
    print(total_data)

    print(total_data.class_to_idx)

    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])
    print(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)

    from torchvision.models import vgg16

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    print("Using {} device\n".format(device))

    ''' 调用官方的VGG-16模型 '''
    # 加载预训练模型,并且对模型进行微调
    model = vgg16(pretrained=True).to(device)  # 加载预训练的vgg16模型
    for param in model.parameters():
        param.requires_grad = False  # 冻结模型的参数,这样子在训练的时候只训练最后一层的参数
    # 修改classifier模块的第6层(即:(6): Linear(in_features=4096, out_features=2, bias=True))
    # 注意查看我们下方打印出来的模型
    model.classifier._modules['6'] = nn.Linear(4096, 17)  # 修改vgg16模型中最后一层全连接层,输出目标类别个数
    model.to(device)

    print(model)

    # 训练循环
    def train(dataloader, model, loss_fn, optimizer):
        size = len(dataloader.dataset)  # 训练集的大小
        num_batches = len(dataloader)   # 批次数目

        train_loss, train_acc = 0, 0  # 初始化训练损失和正确率

        for X, y in dataloader:  # 获取图片及其标签
            X, y = X.to(device), y.to(device)

            # 计算预测误差
            pred = model(X)          # 网络输出
            loss = loss_fn(pred, y)  # 计算网络输出和真实值之间的差距,targets为真实值,计算二者差值即为损失

            # 反向传播
            optimizer.zero_grad()  # grad属性归零
            loss.backward()        # 反向传播
            optimizer.step()       # 每一步自动更新

            # 记录acc与loss
            train_acc += (pred.argmax(1) == y).type(torch.float).sum().item()
            train_loss += loss.item()

        train_acc  /= size
        train_loss /= num_batches

        return train_acc, train_loss

    # 测试函数
    def test(dataloader, model, loss_fn):
        size        = len(dataloader.dataset)  # 测试集的大小
        num_batches = len(dataloader)          # 批次数目,(size/batch_size,向上取整)
        test_loss, test_acc = 0, 0

        # 当不进行训练时,停止梯度更新,节省计算内存消耗
        with torch.no_grad():
            for imgs, target in dataloader:
                imgs, target = imgs.to(device), target.to(device)

                # 计算loss
                target_pred = model(imgs)
                loss        = loss_fn(target_pred, target)

                test_loss += loss.item()
                test_acc  += (target_pred.argmax(1) == target).type(torch.float).sum().item()

        test_acc  /= size
        test_loss /= num_batches

        return test_acc, test_loss

    ''' 自定义设置动态学习率 '''
    def adjust_learning_rate(optimizer, epoch, start_lr):
        # 每 2 个epoch衰减到原来的 0.92
        lr = start_lr * (0.92 ** (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)

    # 定义学习率调整函数
    lambda1 = lambda epoch: 0.92 ** (epoch // 4)
    scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1)  # 选定调整方法

    # 定义损失函数
    loss_fn = nn.CrossEntropyLoss()

    # 定义训练参数
    epochs = 40
    train_loss = []
    train_acc = []
    test_loss = []
    test_acc = []

    best_acc = 0  # 用于保存最佳模型的准确率

    for epoch in range(epochs):
        model.train()
        epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, optimizer)
        scheduler.step()  # 更新学习率(调用官方动态学习率接口时使用)

        model.eval()
        epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
    
        # 保存最佳模型到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:{:.1f}%, Train_loss:{:3f}, Test_acc:{:.1f}%, Test_loss:{:.3f}, lr:{:.2E}')
        print(template.format(epoch+1, epoch_train_acc*100, epoch_train_loss, epoch_test_acc*100, epoch_test_loss, lr))

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

    print('Done')
if __name__ == '__main__':
    main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1035082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

定制化精准推送与用户分组策略:数智营销的硬技能

对于移动应用开发者和运营者而言,推送是保持良好客户互动,实现用户裂变增长的重要方式,在实际推送服务设计中,往往会根据不同的需求和应用场景,针对性的选取特定对象发送特定内容的推送。具体而言,主流的智…

【C刷题】day3

一、选择题 1、已知函数的原型是: int fun(char b[10], int *a); ,设定义: char c[10];int d; ,正确的调用语句是( ) A: fun(c,&d); B: fun(c,d); C: fun(&c,&d); D: fun(&c,d); 【答案…

大模型应用发展的方向|代理 Agent 的兴起及其未来(下)

“ 借助LLM作为代理大脑的优势,探讨了单一代理、多代理系统和人机协作等应用场景,探讨了代理的社会行为、心理活动以及在模拟社会环境中观察新兴社会现象和人类洞见的可能性。” 01 — 造福人类:代理实践 LLM型智能代理是一种新兴的方向&…

【51单片机实验笔记】LED篇(二)多色LED的基本控制

目录 前言硬件介绍双色LED三色LED七彩自动闪烁LED 接线图面包板介绍直插电阻介绍色环解析 双色LED实际接线图三色LED实际接线图七彩自动闪烁LED实际接线图 软件实现双色LED交替闪烁三色LED灯交替闪烁 总结 前言 本节内容我们学习了解一些多色LED的显示原理及驱动方式。 本节涉…

Pytorch---空间特征金字塔SPP模块的实现

文章目录 一、SPP模块二、使用pytorch实现 一、SPP模块 SPP模块是指定空间特征金字塔模块,是由何凯明在2014年的论文中所提出的。 论文地址如下: 论文地址 该模块的主要作用是:在分类网络中,通过分类器之后,与全连接…

stack与queue的简单封装

前言: stack与queue即栈和队列,先进后出/先进先出的特性我们早已了然于心, 在学习数据结构时,我们利用c语言实现栈与队列,从结构体写起,利用数组或指针表示他们的数据成员,之后再一个个实现他们…

Linux 故障定位手段之保存某个时间段内的top结果

在Linux中对故障原因进行定位时,除了查看对应的软体运行日志、OS运行日之外,还可以查看 top 的资源消耗结果。 参考语句: 以CPU为基准列进行排序记录TOP结果 nohup top -d 1 -b -o %CPU | tee -a /tmp/cpu.txt & 语句含义:每…

etc目录下的profile.d文件目录设置环境变量和全局脚本

一、设置环境变量 etc目录下的profile.d文件目录 /etc/profile.d 1、编写 vi test.sh文件内容 # jdk变量 export ZHK_HOME/root export PATH$PATH:$ZHK_HOME/test # 可以取出来ZHK_HOME变量给ZZZ_HOME赋值 export ZZZ_HOME${ZHK_HOME}/test2、刷新 执行source /etc/profile …

34.CSS魔线图标的悬停效果

效果 源码 index.html <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Icon Fill Hover Effects</title> <link rel="stylesheet" h…

【深度学习实验】前馈神经网络(final):final

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 构建数据集&#xff08;IrisDataset&#xff09; 2. 构建模型&#xff08;FeedForward&#xff09; a. __init__(初始化) b. forward(前向传播) 3.整合训练、评估…

Mojo:新型AI语言中的7个令人惊叹的Python升级,用简单的英语解释人工智能

Mojo&#xff1a;新型AI语言中的7个令人惊叹的Python升级 编程之美 用简单的英语解释人工智能 编程之美 由Coding Beauty设计的图像&#xff0c;使用Mojo标志和Python标志。 它比C更快&#xff0c;与Python一样简单&#xff0c;但速度提高了35000倍。 进入Mojo&#xff1a;一种…

冒泡排序与选择排序(最low的两兄弟)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言&#xff1a; 在我们的生活中&#xff0c;无处不在用到排序&#xff0c;比如说成绩的排名&#xff0c;淘宝&#xff0c;京东等等商品在各个方面的排序&#xff0c;这样看来一个好的算 法很重要&#xff0c;接下来我们要先…

深度学习自学笔记四:浅层神经网络(一)

一、神经网络概述 神经网络是一种模仿人脑神经系统结构和功能的计算模型。它由大量相互连接的人工神经元组成&#xff0c;并通过这些神经元之间的信息传递来进行计算和学习。 神经网络的基本组成单元是神经元&#xff0c;也称为节点或单元。每个神经元接收来自其他神经元的输…

第一百五十二回 自定义组件综合实例:游戏摇杆三

文章目录 内容回顾优化性能示例代码我们在上一章回中介绍了 如何实现游戏摇杆相关的内容,本章回中将继续介绍这方面的知识.闲话休提,让我们一起Talk Flutter吧。 内容回顾 我们在前面章回中介绍了游戏摇杆的概念以及实现方法,并且通过示例代码演示了实现游戏摇杆的整个过程…

取消github向邮箱推送邮件及修改密码

取消或者说禁止github向邮箱推送邮件&#xff0c;因为量太大了&#xff0c;没多久就上万封邮件&#xff0c;于是取消订阅或者推送。 1、登录github 2、点击右上角头像&#xff0c;然后点击Settings 3、点击Notifications&#xff08;通知&#xff09; 4、取消各种推送&#x…

SpringBoot开发实战(微课视频版)

ISBN: 978-7-302-52819-7 编著&#xff1a;吴胜 页数&#xff1a;311页 阅读时间&#xff1a;2023-06-24 推荐指数&#xff1a;★★★★☆ 本文介绍SpringBoot 2.0.5 、JDK 1.8&#xff0c;虽然现在已经不维护了&#xff0c;但是大体的流程还是对口的&#xff0c; 而且书里面讲…

新手学习:ArcGIS对shp文件裁剪

新手学习&#xff1a;ArcGIS对SHP文件裁剪 新手学习 记录每个步骤&#xff0c;因为有很多控件可能刚开始还不熟悉&#xff0c;根本不知道在哪里&#xff0c;所以写的比较详细。 1.添加要裁剪的shp文件 2.查看shp文件的地理坐标系 双击shp文件&#xff0c;就可以查看shp文件的…

LeetCode【174. 地下城游戏】

一片丹心图报国&#xff0c;两行清泪为忠家。——于谦 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里&#xff0c;他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康…

【Linux】系统编程基于环形队列生产者消费者模型(C++)

目录 【1】引入POSIX信号量 【1.1】初始化信号量 【1.2】销毁信号量 【1.3】等待信号量 【1.4】发布信号量 【2】基于环形队列的生产消费模型 【2.1】生产消费模型打印数字模型 【2.2】生产消费模型计算公式模型 【2.3】生产消费模型计算公式加保存任务模型 【1】引入…

###Data Structure###考研重点

顺序表 顺序表 &#xff08;此代码i是序号而非角标&#xff09; 结构体&#xff1a; 插入&#xff1a;从最后一个元素逐个往后移一位 删除&#xff1a;从删除位置的下一个把每个提前一位 顺序&#xff08;循环&#xff09;队列 结构体 判断队满 &#xff08;总结&#xff…