当前位置: 首页 > article >正文

基于PyTorch的深度学习5——神经网络工具箱

可以学习如下内容:

• 介绍神经网络核心组件。

• 如何构建一个神经网络。

• 详细介绍如何构建一个神经网络。

• 如何使用nn模块中Module及functional。

• 如何选择优化器。

• 动态修改学习率参数。

5.1 核心组件

神经网络核心组件不多,把这些组件确定后,这个神经网络基本就确定了。这些核心组件包括:

1)层:神经网络的基本结构,将输入张量转换为输出张量。

2)模型:层构成的网络。

3)损失函数:参数学习的目标函数,通过最小化损失函数来学习各种参数。

4)优化器:如何使损失函数最小,这就涉及优化器。

多个层链接在一起构成一个模型或网络,输入数据通过这个模型转换为预测值,然后损失函数把预测值与真实值进行比较,得到损失值(损失值可以是距离、概率值等)​,该损失值用于衡量预测值与目标结果的匹配或相似程度,优化器利用损失值更新权重参数,从而使损失值越来越小。这是一个循环过程,当损失值达到一个阀值或循环次数到达指定次数,循环结束。接下来利用PyTorch的nn工具箱,构建一个神经网络实例。nn中对这些组件都有现成包或类,可以直接使用,非常方便。

——————————实现神经网络实例

构建网络层可以基于Module类,或函数(nn.functional)。

nn.Module中的大多数层(Layer)在functional中都有与之对应的函数。

nn.functional中函数与nn.Module中的Layer的主要区别是后者继承Module类,会自动提取可学习的参数。

而nn.functional更像是纯函数。

两者功能相同,且性能也没有很大区别,那么如何选择呢?像卷积层、全连接层、Dropout层等因含有可学习参数,一般使用nn.Module,而激活函数、池化层不含可学习参数,可以使用nn.functional中对应的函数。

下面通过实例来说明如何使用nn构建一个网络模型。

这节将利用神经网络完成对手写数字进行识别的实例,来说明如何借助nn工具箱来实现一个神经网络,并对神经网络有个直观了解。在这个基础上,后续我们将对nn的各模块进行详细介绍。实例环境使用PyTorch1.0+,GPU或CPU,源数据集为MNIST。

主要步骤:

1)利用PyTorch内置函数mnist下载数据。

2)利用torchvision对数据进行预处理,调用torch.utils建立一个数据迭代器。

3)可视化源数据。

4)利用nn工具箱构建神经网络模型。

5)实例化模型,并定义损失函数及优化器。

6)训练模型。

7)可视化结果。

import numpy as np
import torch

from torchvision.datasets import mnist

#导入预处理模块
import torchvision.transforms as transforms
from torch.utils.data import DataLoader

#导入nn及优化器
import torch.nn.functional as F
import torch.optim as optim
from torch import nn


接下来,定义一些超参数

train_batch_size=64
test_batch_size=128
learning_rate=0.01
num_epoches=20
lr=0.01
momentum=0.5

下载数据并对数据进行预处理

#定义预处理函数,这些预处理依次放在Compose函数中。
transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize([0.5], [0.5])])
#下载数据,并对数据进行预处理
train_dataset = mnist.MNIST('./data', train=True, transform=transform, download=True)
test_dataset = mnist.MNIST('./data', train=False, transform=transform)

#dataloader是一个可迭代对象,可以使用迭代器一样使用。
train_loader = DataLoader(train_dataset, batch_size=train_batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=test_batch_size, shuffle=False)
  • transforms.Compose:

    • Compose 是 PyTorch 中的一个工具,用于将多个预处理操作组合在一起,依次执行。
  • transforms.ToTensor():

    • 将 PIL 图像或 NumPy 数组转换为 PyTorch 张量(Tensor)。
    • 同时会将图像的像素值从 [0, 255] 转换到 [0, 1] 的范围。
  • transforms.Normalize([0.5], [0.5]):

    • 对张量进行归一化处理。
    • 归一化的公式是:output = (input - mean) / std
    • 这里的参数 [0.5] 表示均值(mean),[0.5] 表示标准差(std)。
    • 因此,归一化后数据的范围会从 [0, 1] 变为 [-1, 1]
    • DataLoader 是 PyTorch 提供的一个工具,用于将数据集分批加载,并支持多线程、打乱顺序等功能。
  • 参数解释:
    • train_dataset 和 test_dataset: 分别指定训练集和测试集。
    • batch_size: 每次加载的数据批量大小。train_batch_size 和 test_batch_size 应该在代码其他地方定义。
    • shuffle=True: 是否在每个 epoch 开始时打乱数据顺序。通常在训练集上设置为 True,以增加模型的泛化能力。
    • shuffle=False: 测试集一般不需要打乱顺序。

——————————————可视化源数据

import matplotlib.pyplot as plt

examples=enumerate(test_loader)
batch_idx,(example_data,example_targets)=next(examples)

fig=plt.figure()
for i in range(6):
    plt.subplot(2,3,i+1)
    plt.tight_layout()
    plt.imshow(example_data[i][0],cmap="gray",interpolation='none')
    plt.title("Ground Truth:{}".format(example_targets[i]))
    plt.xticks([])
    plt.yticks([])

_______________________构建模型

数据预处理结束后,开始构建模型

1)构建网络的类Net

class Net(nn.Module):
    
    """
    使用sequential构建网络,Sequential()函数的功能是将网络的层组合到一起
    """
    def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
        super(Net, self).__init__()

        self.layer1 = nn.Sequential(nn.Linear(in_dim,
n_hidden_1),nn.BatchNorm1d(n_hidden_1))
        self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2),nn.BatchNorm1d (n_hidden_2))
        self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim))

    def forward(self, x):
        x = F.relu(self.layer1(x))
        x = F.relu(self.layer2(x))
        x = self.layer3(x)
        return x

2)创造实例

#检测是否有可用的GPU,有则使用,否则使用CPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#实例化网络
model = Net(28 * 28, 300, 100, 10)
model.to(device)

# 定义损失函数criterion和优化器optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)

以下内容为大语言模型生成:

这段代码实现了一个使用nn.Sequential构建的三层全连接神经网络,包含批归一化和ReLU激活函数。以下是对代码的分析及优化建议:


代码结构分析

  1. 网络定义

    • Layer1 :线性层(in_dimn_hidden_1) + 批归一化。
    • Layer2 :线性层(n_hidden_1n_hidden_2) + 批归一化。
    • Layer3 :线性层(n_hidden_2out_dim),无批归一化和激活函数。
  2. 前向传播

    • 前两层使用ReLU激活,最后一层输出原始 logits(适用于分类任务结合CrossEntropyLoss或回归任务)。

————————训练模型

这里使用for循环进行迭代。其中包括对训练数据的训练模型,然后用测试数据的验证模型。

1.训练模型

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from tqdm import tqdm

# 假设已定义模型、数据集、损失函数和优化器
# model = Net(...)
# train_dataset = ...
# test_dataset = ...

# 数据预处理(展平)
class FlattenTransform:
    def __call__(self, img):
        return img.view(-1)

transform = transforms.Compose([
    transforms.ToTensor(),
    FlattenTransform()
])

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64)

# 初始化
losses = []
acces = []
eval_losses = []
eval_acces = []

for epoch in range(num_epoches):
    # 动态调整学习率
    if epoch > 0 and epoch % 5 == 0:
        for param_group in optimizer.param_groups:
            new_lr = max(param_group['lr'] * 0.1, 1e-6)
            param_group['lr'] = new_lr
            print(f"Learning rate updated to {new_lr}")

    # 训练阶段
    model.train()
    train_loss = 0
    train_correct = 0
    train_total = 0
    for img, label in tqdm(train_loader, desc=f"Epoch {epoch+1} Training"):
        img, label = img.to(device), label.to(device)
        
        # 前向传播
        output = model(img)
        loss = criterion(output, label)
        
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        # 记录指标
        train_loss += loss.item()
        _, pred = output.max(1)
        train_correct += (pred == label).sum().item()
        train_total += label.size(0)
    
    # 计算平均指标
    avg_train_loss = train_loss / len(train_loader)
    avg_train_acc = train_correct / train_total
    losses.append(avg_train_loss)
    acces.append(avg_train_acc)

    # 测试阶段
    model.eval()
    eval_loss, eval_acc = calculate_metrics(test_loader, model, criterion, device)
    eval_losses.append(eval_loss)
    eval_acces.append(eval_acc)
    
    # 打印日志
    print(f'Epoch {epoch+1}/{num_epoches}: '
          f'Train Loss: {avg_train_loss:.4f}, Train Acc: {avg_train_acc:.4f}, '
          f'Test Loss: {eval_loss:.4f}, Test Acc: {eval_acc:.4f}')

以下内容由大语言模型生成

为什么需要 model.eval()

在神经网络中,某些层(如 BatchNormDropout)在训练(training)和推理(evaluation)阶段的行为不同:

  1. BatchNorm 层

    • 训练阶段 :使用当前 batch 的均值和方差进行标准化,并更新运行统计量(running mean/variance)。
    • 推理阶段 :使用训练阶段累积的运行统计量,而非当前 batch 的统计量。
    • 若不调用 model.eval(),推理时会继续更新统计量,导致结果不稳定。
  2. Dropout 层

    • 训练阶段 :随机丢弃部分神经元,防止过拟合。
    • 推理阶段 :关闭 Dropout,使用所有神经元的输出(权重按概率缩放)。
    • 若不调用 model.eval(),推理时会继续随机丢弃神经元,导致结果随机。

功能详解

调用 model.eval() 后:

  1. 关闭训练相关行为
    • BatchNorm 层停止计算均值/方差,使用累积的统计量。
    • Dropout 层停止随机丢弃神经元。
  2. 不影响梯度计算
    • model.eval() 仅改变层的行为,不涉及梯度计算。如果需要禁用梯度,需配合 torch.no_grad()

http://www.kler.cn/a/578760.html

相关文章:

  • 百货店的诞生与现代商业革命:结合开源AI智能客服、AI智能名片与S2B2C商城小程序的新视角
  • 通过HTML有序列表(ol/li)实现自动递增编号的完整解决方案
  • SpringBatch之ResultSet.next()
  • 基于Canvas和和原生JS实现俄罗斯方块小游戏
  • 【贪心算法】简介
  • el-input-number添加自定义内容class-unit
  • 【算法题】小鱼的航程
  • AWS中使用CloudFront分发位于S3中的静态网站
  • SV学习笔记——数组、队列
  • spring boot+vue项目(免费)
  • es-初体验easy-es时报错:找不到mapper
  • Vue 过滤器 filter(s) 的使用
  • win32汇编环境,对话框中使用树形视图示例四
  • Objective-C 中 @synthesize VS @dynamic
  • webtinyserver讲解
  • pytorch retain_grad vs requires_grad
  • 电路研究9.3.1——合宙Air780EP中的AT开发指南:TCP 使用 SSL 示例
  • 关于VScode终端无法识别外部命令
  • mysql安装(演示为mac安装流程)
  • 使用 Python 批量提取 PDF 书签:一款实用工具的实现