【机器学习合集】人脸表情分类任务Pytorch实现TensorBoardX的使用 ->(个人学习记录笔记)

人脸表情分类任务

  • 注意:整个项目来自阿里云天池,下面是开发人员的联系方式,本人仅作为学习记录!!!
  • 该文章原因,学习该项目,完善注释内容,针对新版本的Pytorch进行部分代码调整
  • 本文章采用pytorch2.0.1版本,python3.10版本

源码链接

这是一个使用pytorch实现的简单的2分类任务
项目结构:
    - net.py: 网络定义脚本
    - train.py:模型训练脚本
    - inference.py:模型推理脚本
    - run_train.sh 训练可执行文件
    - run_inference.sh 推理可执行文件
    
# Copyright 2019 longpeng2008. All Rights Reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# If you find any problem,please contact us longpeng2008to2012@gmail.com 

1. 网络结构

# coding:utf8

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

# 3层卷积神经网络simpleconv3定义
# 包括3个卷积层,3个BN层,3个ReLU激活层,3个全连接层

class simpleconv3(nn.Module):
    # 初始化函数
    def __init__(self, nclass):
        # 继承父类
        super(simpleconv3, self).__init__()
        # 3通道 输入图片大小为3*48*48,输出特征图大小为12*23*23,卷积核大小为3*3,步长为2
        '''
            输出特征图大小 = [(输入大小 - 卷积核大小) / 步长] + 1
            输入大小是 48x48
            卷积核大小是 3x3
            步长是 2
            将这些值代入公式,您将得到输出特征图的大小:
            输出特征图大小 = [(48 - 3) / 2] + 1 = (45 / 2) + 1 = 22.5 + 1 = 23
        '''
        self.conv1 = nn.Conv2d(3, 12, 3, 2)
        # 批量标准化操作 12个特征通道
        self.bn1 = nn.BatchNorm2d(12)
        # 输入图片大小为12*23*23,输出特征图大小为24*11*11,卷积核大小为3*3,步长为2
        '''
            输出特征图大小 = [(输入大小 - 卷积核大小) / 步长] + 1
            输入大小是 23x23
            卷积核大小是 3x3
            步长是 2
            将这些值代入公式,您将得到输出特征图的大小:
            输出特征图大小 = [(23 - 3) / 2] + 1 = (20 / 2) + 1 = 10 + 1 = 11
        '''
        self.conv2 = nn.Conv2d(12, 24, 3, 2)
        # 批量标准化操作 24个特征通道
        self.bn2 = nn.BatchNorm2d(24)
        # 输入图片大小为24*11*11,输出特征图大小为48*5*5,卷积核大小为3*3,步长为2
        '''
            输出特征图大小 = [(输入大小 - 卷积核大小) / 步长] + 1
            输入大小是 11x11
            卷积核大小是 3x3
            步长是 2
            将这些值代入公式,您将得到输出特征图的大小:
            输出特征图大小 = [(11 - 3) / 2] + 1 = (8 / 2) + 1 = 4 + 1 = 5
        '''
        self.conv3 = nn.Conv2d(24, 48, 3, 2)
        # 批量标准化操作 48个特征通道
        self.bn3 = nn.BatchNorm2d(48)
        # 输入向量长为48*5*5=1200,输出向量长为1200 展平
        self.fc1 = nn.Linear(48 * 5 * 5, 1200)
        # 1200 -> 128
        self.fc2 = nn.Linear(1200, 128)  # 输入向量长为1200,输出向量长为128
        # 128 -> 类别数
        self.fc3 = nn.Linear(128, nclass)  # 输入向量长为128,输出向量长为nclass,等于类别数

    # 前向函数
    def forward(self, x):
        # relu函数,不需要进行实例化,直接进行调用
        # conv,fc层需要调用nn.Module进行实例化
        # 先卷积后标准化再激活
        x = F.relu(self.bn1(self.conv1(x)))
        x = F.relu(self.bn2(self.conv2(x)))
        x = F.relu(self.bn3(self.conv3(x)))
        # 更改形状 改为1维
        x = x.view(-1, 48 * 5 * 5)
        # 全连接再激活
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


if __name__ == '__main__':
    import torch
    x = torch.randn(1, 3, 48, 48)
    model = simpleconv3(2)
    y = model(x)
    print(model)
    '''
    simpleconv3(
          (conv1): Conv2d(3, 12, kernel_size=(3, 3), stride=(2, 2))
          (bn1): BatchNorm2d(12, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (conv2): Conv2d(12, 24, kernel_size=(3, 3), stride=(2, 2))
          (bn2): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (conv3): Conv2d(24, 48, kernel_size=(3, 3), stride=(2, 2))
          (bn3): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (fc1): Linear(in_features=1200, out_features=1200, bias=True)
          (fc2): Linear(in_features=1200, out_features=128, bias=True)
          (fc3): Linear(in_features=128, out_features=2, bias=True)
    )
    '''

2. 训练函数

部分代码内容与作者不同

  • scheduler.step()与optimizer.step()修改前后顺序
  • RandomSizedCrop改为RandomCrop
  • transforms.Scale修改为transforms.Resize
# coding:utf8
from __future__ import print_function, division
import os
import torch
import torch.nn as nn
import torch.optim as optim
# 使用tensorboardX进行可视化
from tensorboardX import SummaryWriter
from torch.optim import lr_scheduler
from torchvision import datasets, transforms

from net import simpleconv3

writer = SummaryWriter('logs')  # 创建一个SummaryWriter的示例,默认目录名字为runs

# 训练主函数
def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
    """
    训练模型
    Args:
        model: 模型
        criterion: loss函数
        optimizer: 优化器
        scheduler: 学习率调度器
        num_epochs: 训练轮次
    Returns:
    """
    # 开始训练
    for epoch in range(num_epochs):
        # 打印训练轮次
        print(f'Epoch {epoch+1}/{num_epochs}')
        for phase in ['train', 'val']:
            if phase == 'train':
                # 设置为训练模式
                model.train(True)
            else:
                # 设置为验证模式
                model.train(False)
            # 损失变量
            running_loss = 0.0
            # 精度变量
            running_accs = 0.0
            number_batch = 0
            # 从dataloaders中获得数据
            for data in dataloaders[phase]:
                inputs, labels = data
                if use_gpu:
                    inputs = inputs.cuda()
                    labels = labels.cuda()
                # 清空梯度
                optimizer.zero_grad()
                # 前向运行
                outputs = model(inputs)
                # 使用max()函数对输出值进行操作,得到预测值索引
                _, preds = torch.max(outputs.data, 1)
                # 计算损失
                loss = criterion(outputs, labels)
                if phase == 'train':
                    # 误差反向传播
                    loss.backward()
                    # 参数更新
                    optimizer.step()
                running_loss += loss.data.item()
                running_accs += torch.sum(preds == labels).item()
                number_batch += 1
            # 调整学习率
            scheduler.step()
            # 得到每一个epoch的平均损失与精度
            epoch_loss = running_loss / number_batch
            epoch_acc = running_accs / dataset_sizes[phase]

            # 收集精度和损失用于可视化
            if phase == 'train':
                writer.add_scalar('data/trainloss', epoch_loss, epoch)
                writer.add_scalar('data/trainacc', epoch_acc, epoch)
            else:
                writer.add_scalar('data/valloss', epoch_loss, epoch)
                writer.add_scalar('data/valacc', epoch_acc, epoch)

            print('{} Loss: {:.4f} Acc: {:.4f}'.format(
                phase, epoch_loss, epoch_acc))
    writer.close()
    return model


if __name__ == '__main__':

    # 图像统一缩放大小
    image_size = 60
    # 图像裁剪大小,即训练输入大小
    crop_size = 48
    # 分类类别数
    nclass = 2
    # 创建模型
    model = simpleconv3(nclass)
    # 数据目录
    data_dir = './data'

    # 模型缓存接口
    if not os.path.exists('models'):
        os.mkdir('models')

    # 检查GPU是否可用,如果是使用GPU,否使用CPU
    use_gpu = torch.cuda.is_available()
    if use_gpu:
        model = model.cuda()
    print(model)

    # 创建数据预处理函数,训练预处理包括随机裁剪缩放、随机翻转、归一化,验证预处理包括中心裁剪,归一化
    data_transforms = {
        'train': transforms.Compose([
            transforms.RandomCrop(48),  # 随机大小、长宽比裁剪图片size=48 RandomSizedCrop改为RandomCrop
            transforms.RandomHorizontalFlip(),  # 随机水平翻转 默认概率p=0.5
            transforms.ToTensor(),  # 将原始的PILImage格式或者numpy.array格式的数据格式化为可被pytorch快速处理的张量类型
            transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])  # 数据标准化 要将图像三个通道的数据 整理到 [-1,1] 之间 ,可以加快模型的收敛
        ]),
        'val': transforms.Compose([
            transforms.Resize(64),  # Scale用于调整图像的大小,现在采用transforms.Resize()代替
            transforms.CenterCrop(48),  # 从图像中心裁剪图片尺寸size=48
            transforms.ToTensor(),
            transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
        ]),
    }

    # 使用torchvision的dataset ImageFolder接口读取数据
    image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'val']}

    # 创建数据指针,设置batch大小,shuffle,多进程数量
    dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x],
                                                  batch_size=16,  # 每个小批次包含16个样本
                                                  shuffle=True,   # 是否随机打乱数据
                                                  num_workers=4)  # 加载数据的子进程数
                   for x in ['train', 'val']}
    # 获得数据集大小
    dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}

    # 优化目标使用交叉熵,优化方法使用带动量项的SGD,学习率迭代策略为step,每隔100个epoch,变为原来的0.1倍
    criterion = nn.CrossEntropyLoss()
    # 优化器 传入权重阈值,学习率0.1 动量(momentum)是一个控制梯度下降方向的超参数。
    # 它有助于加速训练,特别是在存在平坦区域或局部极小值时。动量的值通常在0到1之间。较大的动量值会使参数更新更平滑。在这里,动量设置为0.9。
    optimizer_ft = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)

    '''
    
    lr_scheduler.StepLR 是PyTorch中的学习率调度器(learning rate scheduler),用于在训练神经网络时动态调整学习率。
    lr_scheduler.StepLR 允许您在训练的不同阶段逐步减小学习率,以帮助优化过程。
    optimizer_ft:这是您用于优化模型参数的优化器,通常是 optim.SGD 或其他PyTorch优化器的实例。
                学习率调度器将监控这个优化器的状态,并根据其规则更新学习率。
    step_size=100:这是学习率更新的周期,也称为学习率下降步数。在每个 step_size 个训练周期之后,学习率将减小。
            gamma=0.1:这是学习率减小的因子。在每个 step_size 个训练周期之后,学习率将乘以 gamma。这意味着学习率将以 gamma 的倍数逐步减小。
    '''
    exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=100, gamma=0.1)

    model = train_model(model=model,
                        criterion=criterion,
                        optimizer=optimizer_ft,
                        scheduler=exp_lr_scheduler,
                        num_epochs=10)

    torch.save(model.state_dict(), 'models/model.pt')

3. 预测

执行以下内容,或者自行安排数据集

## 使用方法 python3 inference.py 模型路径 图片路径
python3 inference.py models/model.pt data/train/0/1neutral.jpg
python3 inference.py models/model.pt data/train/1/1smile.jpg
# coding:utf8

import sys
import numpy as np
import torch
from PIL import Image
from torchvision import transforms

# 全局变量
# sys.argv[1] 权重文件
# sys.argv[2] 图像文件夹

testsize = 48  # 测试图大小
from net import simpleconv3

# 定义模型
net = simpleconv3(2)
# 设置推理模式,使得dropout和batchnorm等网络层在train和val模式间切换
net.eval()
# 停止autograd模块的工作,以起到加速和节省显存
torch.no_grad()

# 载入模型权重
modelpath = sys.argv[1]
net.load_state_dict(torch.load(modelpath, map_location=lambda storage, loc: storage))

# 定义预处理函数
data_transforms = transforms.Compose([
    transforms.Resize(48),
    transforms.ToTensor(),
    transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])

# 读取3通道图片,并扩充为4通道tensor
imagepath = sys.argv[2]
image = Image.open(imagepath)
imgblob = data_transforms(image).unsqueeze(0)

# 获得预测结果predict,得到预测的标签值label
predict = net(imgblob)
index = np.argmax(predict.detach().numpy())
# print(predict)
# print(index)

if index == 0:
    print('the predict of ' + sys.argv[2] + ' is ' + str('none'))
else:
    print('the predict of ' + sys.argv[2] + ' is ' + str('smile'))

4. TensorBoardX的使用

TensorBoardX 是一个用于在 PyTorch 中可视化训练过程和结果的工具。它是 TensorBoard 的 Python 版本,用于创建交互式、实时的训练和评估图表。以下是一些使用 TensorBoardX 的一般步骤:

  1. 安装 TensorBoardX:首先,您需要安装 TensorBoardX 库。您可以使用以下命令安装它:

    pip install tensorboardX
    
  2. 导入库:在您的 PyTorch 代码中,导入 TensorBoardX 库:

    from tensorboardX import SummaryWriter
    
  3. 创建 SummaryWriter:创建一个 SummaryWriter 对象,以将日志数据写入 TensorBoard 日志目录。

    writer = SummaryWriter()
    
  4. 记录数据:在训练循环中,使用 writer.add_* 方法来记录各种数据,例如标量、图像、直方图等。以下是一些示例:

    • 记录标量数据:

      writer.add_scalar('loss', loss, global_step)
      
    • 记录图像数据:

      writer.add_image('image', image, global_step)
      
    • 记录直方图数据:

      writer.add_histogram('weights', model.conv1.weight, global_step)
      
    • 记录文本数据:

      writer.add_text('description', 'This is a description.', global_step)
      
  5. 启动 TensorBoard 服务器:在命令行中,使用以下命令启动 TensorBoard 服务器:

    tensorboard --logdir=/path/to/log/directory
    

    其中 /path/to/log/directory 是存储 TensorBoardX 日志的目录。

  6. 查看可视化结果:在浏览器中打开 TensorBoard 的 Web 界面,通常位于 http://localhost:6006,您可以在该界面上查看可视化结果。

请注意,您可以根据需要记录不同类型的数据,并根据训练过程的不同阶段定期记录数据。TensorBoardX 提供了丰富的可视化工具,以帮助您监视和分析模型的训练过程。

确保在训练循环中适时记录数据,并使用 TensorBoardX 查看结果,以更好地理解和改进您的深度学习模型。


这是 TensorBoard 启动时的一般信息,表明TensorBoard运行在本地主机(localhost)。如果您想使 TensorBoard 可以在网络上访问,可以采取以下几种方法:

  1. 使用代理:您可以使用代理服务器来将 TensorBoard 的端口暴露到网络上。这通常需要在代理服务器上进行一些配置,以便外部用户可以访问 TensorBoard。代理服务器可以是诸如 Nginx 或 Apache 之类的 Web 服务器。

  2. 使用 --bind_all 参数:在启动 TensorBoard 时,您可以使用 --bind_all 参数,以将 TensorBoard 绑定到所有网络接口。这样,TensorBoard 将可以在本地网络上的任何 IP 地址上访问,而不仅仅是本地主机。例如:

    tensorboard --logdir=/path/to/log/directory --bind_all
    
  3. 使用 --host 参数:您还可以使用 --host 参数来指定 TensorBoard 的主机名(hostname),以使其在指定的主机上可用。例如:

    tensorboard --logdir=/path/to/log/directory --host=0.0.0.0
    

    这将允许 TensorBoard 在所有网络接口上运行,从而在网络上的任何 IP 地址上访问。

请根据您的需求和网络设置选择适当的方法。如果只需要在本地访问 TensorBoard,无需进行任何更改。如果需要在网络上访问,可以使用上述选项之一。不过,请注意,为了安全起见,最好将 TensorBoard 限制在受信任的网络上,或者使用身份验证和授权来保护访问。


效果展示
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

R与Python结合,在安装tensorflow时遇到了报错--尚未解决

在服务器上安装tensorflow时,遇到了一个报错信息: 在网上找到一个类似的错误(TensorFlow_error),见下图,但是博主没有给出解决办法。

解决javascript报错:SyntaxError: Invalid Unicode escape sequence

在处理cookie时报这个错: 网上搜了一圈都说是反斜杠问题,要把\替换成/ 但是试了网上的replace替换: replace(/\\/g, /) 结果没有用!!! 然后我干脆直接做了一个最简单字符串赋值,再打印出来。…

macOS鼠标管理操作增强BetterMouse简体中文

BetterMouse是一款专为Mac用户设计的鼠标增强工具,旨在帮助用户更好地掌握和管理鼠标操作。它提供了全局鼠标手势、高度可定制的鼠标设置选项以及一些有用的鼠标增强功能,如鼠标放大镜、鼠标轨迹和应用程序切换功能。这些功能可以大大提高用户的工作效率…

单例模式及其使用场景

单例模式(Singleton):指在一个系统中某个类只存在一个实例,类中自行实例化,实例向该系统提供统一的访问接口。 单例模式有两种表现形式,饿汉式:类加载时,就进行实例化;懒…

23款奔驰E300L升级几何多光束大灯 车辆自检等功能

奔驰几何多光束大灯核心特点就是通过内部的84颗可独立控制的LED光源,行车远光灯会甄别对向驶来的车辆或者行人,并且动态的跟随目标,之后阴影话该区域,避免晃到车辆和行人。 奔驰升级几何多光束 LED 大灯(MULTIBEAM LED…

nu1l-死亡ping命令攻略

book-nu1l docker 虚拟化技术 把传统的虚拟机堪称容器 依赖镜像启动容器,镜像可以理解为模板克隆的虚拟机,删除容器,对镜像没有影响 镜像在云端 本地要使用某个镜像,根据地址,直接从云端拉取 基本命令 # 查看系统…

【unity3D】Rect Transform组件

💗 未来的游戏开发程序媛,现在的努力学习菜鸡 💦本专栏是我关于游戏开发的学习笔记 🈶本篇是unity的Rect Transform组件 Rect Transform组件 基础知识详细介绍补充 基础知识 Rect Transform是Unity中的一个UI组件,用于…

适用于物联网的UI设计工具都有哪些?

随着科学技术的飞速发展,“万物相连的互联网”时代逐渐成为现实。如今,物联网已经不是什么新词了。事实上,早在各种屏幕设备诞生之前,人们就与物理世界交织在一起,产生了无数的互动。如何将人们多年积累的互动经验与物…

BurpSuite安装

下载 BurpSuite 下载 Java17 下载后确定版本 java -version获取启动器 密钥生成器 破解 将下载的 BurpSuite、启动器、密钥生成器,放入同一个目录 打开 CMD 进入该目录 启动密钥生成器 java -jar burp-keygen-scz.jar开启新的CMD,进入该目录 启动…

理解什么是接口测试?怎样做接口测试?

一 什么是接口? 接口测试主要用于外部系统与系统之间以及内部各个子系统之间的交互点,定义特定的交互点,然后通过这些交互点来,通过一些特殊的规则也就是协议,来进行数据之间的交互。接口测试主要用于外部系统与系统之…

微信小程序学习(02)

页面导航 - 声明式导航 1. 导航到 tabBar 页面 tabBar 页面指的是被配置为 tabBar 的页面。 在使用<navigator> 组件跳转到指定的 tabBar 页面时&#xff0c;需要指定 url 属性和 open-type 属性&#xff0c;其中&#xff1a; ⚫ url 表示要跳转的页面的地址&#xff0…

TX Text Control.NET For WPF 32.0 Crack

TX Text Control 支持VISUAL STUDIO 2022、.NET 5 和 .NET 6 支持 .NET WPF 应用程序的文档处理 将文档编辑、创建和 PDF 生成添加到您的 WPF 应用程序中。 视窗用户界面 功能齐全的文档编辑器 TX Text Control 是一款完全可编程的丰富编辑控件&#xff0c;它在专为 Visual Stu…

TensorFlow2从磁盘读取图片数据集的示例(tf.keras.utils.image_dataset_from_directory)

import os import warnings warnings.filterwarnings("ignore") import tensorflow as tf from tensorflow.keras.optimizers import Adam from tensorflow.keras.applications.resnet import ResNet50#数据所在文件夹 base_dir ./data/cats_and_dogs train_dir os…

ES 数据迁移最佳实践

ES 数据迁移最佳实践与讲解 数据迁移是 Elasticsearch 运维管理和业务需求中常见的操作之一。以下是不同数据迁移方法的最佳实践和讲解&#xff1a; 一、数据迁移需求梳理 二、数据迁移方法梳理 三、各方案对比 方案 优点 缺点&#xff08;限制&#xff09; 适用场景 是否有…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十三:通用表格组件封装实现

一、本章内容 本章实现通用表格组件,根据实体配置自动实现表格列识别、数据搜索、表格排序、添加、编辑、删除等操作功能。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 3.1 B站视频地址:

Linux中的开发工具(yum,vim,gcc/g++,gdb,Makefile,git)

文章目录 1. Linux软件包管理器——yumyum 语法yum 常用命令安装 yum 仓库源 2. Linux编辑器——vimvim 的五种常用模式模式切换vim 基本操作命令模式命令集&#xff08;1&#xff09;光标命令&#xff08;2&#xff09;复制粘贴命令&#xff08;3&#xff09;撤销与重做&#…

app分发的一些流程2

应用分发的流程通常包括以下步骤&#xff1a; 开发应用程序&#xff1a;首先&#xff0c;您需要开发您的应用程序。这包括编写代码、设计用户界面、测试应用程序等等。确保您的应用程序符合各个应用商店的规范和要求&#xff0c;以确保顺利通过审核。 准备应用材料&#xff1…

Json数据上传—>对象转换—>存入MongoDB(SpringData提供的规范)

上传json 代码实现 RestController RequestMapping("/api/hosp") public class ApiController{Autowiredprivate HospitalService hospitalService;PostMapping("saveHospital")public Result saveHosp(HttpServletRequest request){Map<String,String…

基于html5+javascript技术开发的房贷利率计算器

房贷计算器是一款专为购房者设计的实用工具应用&#xff0c;其主要功能是帮助用户详细计算房贷的还款金额、利息以及还款计划等。通过这款软件&#xff0c;用户可以更加便捷地了解到自己的还款情况和计划&#xff0c;从而更好地规划自己的财务。下面将对房贷计算器进行详细的介…

k8s-----25、资源调度-ResourceQuota资源配额、资源限制limitrange、服务质量QoS

1、ResourceQuota资源配额 1.0 作用 命名空间资源配额。防止公司内部人员对资源的不合理利用。 1.1、为什么需要资源配额 1、作为k8s集群的管理员&#xff0c;知道集群的规模&#xff0c;会合理规划资源&#xff0c;但是使用侧不知道&#xff0c;会导致很多不合理的使用场景…