深度学习框架PyTorch——从入门到精通(5)构建神经网络

news2025/3/19 17:01:16

构建神经网络

  • 获取训练设备
  • 定义类
  • 模型层
    • nn.Flatten
    • nn.Linear
    • nn.ReLU
    • nn.Sequential
    • nn.Softmax
  • 模型参数
  • 补充说明
    • argmax

神经网络是由一些层或者模块组成的,这些层和模块会对数据进行各种操作。

在 PyTorch 里,torch.nn 这个命名空间提供了你搭建自己神经网络所需要的所有基础组件。PyTorch 里的每一个模块都是 nn.Module 类的子类。

一个神经网络本身就是一个模块,而这个模块又由其他的模块(也就是层)构成。这种一层套一层的嵌套结构,让我们能够轻松地搭建和管理复杂的神经网络架构。

在以下示例中,我们将构建一个神经网络来对时尚MNIST数据集中的图像进行分类。

import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

获取训练设备

在训练开始之前,我们需要检查我们的训练设备。

我们希望能够在CUDA、MPS、MTIA或XPU等加速器上训练我们的模型。所有如果有加速器就用加速器,没有的话只能考虑CPU。(CPU训练慢)

device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
print(f"Using {device} device")

# 输出
Using cuda device

定义类

我们通过继承 PyTorch 的nn.Module类来定义自己的神经网络。在__init__这个特殊方法中,我们会初始化网络中需要用到的各个神经层(比如全连接层、卷积层等)。每个继承自·nn.Module·的子类都必须在·forward·方法中定义如何对输入数据进行处理(即实现前向传播逻辑)。

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits
# 我们创建一个NeuralNetwork的实例,并将其移动到device和printits结构。
model = NeuralNetwork().to(device)
print(model)
# 输出
NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear_relu_stack): Sequential(
    (0): Linear(in_features=784, out_features=512, bias=True)
    (1): ReLU()
    (2): Linear(in_features=512, out_features=512, bias=True)
    (3): ReLU()
    (4): Linear(in_features=512, out_features=10, bias=True)
  )
)

要使用模型,我们将输入数据传递给它。这将执行模型的forward,以及一些后台操作。

不要直接调用model.forward()!

在输入上调用模型返回一个二维张量,dim=0对应于每个类的10个原始预测值的每个输出,dim=1对应于每个输出的单个值。我们通过将其传递给nn.Softmax模块的实例来获得预测概率。

# 生成一个随机的三维张量,并将其放置在指定的设备上  (1, 28, 28):指定生成张量的形状。
# 这里生成的是一个三维张量,第一个维度 1 通常表示批量大小(batch size),即一次处理的样本数量为 1;
# 后面两个维度 28 和 28 分别表示图像的高度和宽度。在深度学习里,这可能模拟一张单通道的 28x28 像素的图像
X = torch.rand(1, 28, 28, device=device)
# 将输入张量 X 传入已经定义好的 model 中进行前向传播,得到模型的输出 logits。	
logits = model(X)
# 将输入张量 X 传入已经定义好的 model 中进行前向传播,得到模型的输出 logits。
pred_probab = nn.Softmax(dim=1)(logits)
# 找出每个样本概率最大的类别索引,作为模型的预测结果。
# argmax 是 PyTorch 张量的一个方法,用于返回指定维度上最大值的索引。dim=1 表示在第二个维度上进行操作,即找出每个样本中概率最大的类别对应的索引
y_pred = pred_probab.argmax(1)
print(f"Predicted class: {y_pred}")
# 输出
Predicted class: tensor([7], device='cuda:0')

补充说明:argmax:请看 这里

模型层

让我们分解时尚MNIST模型中的层。为了说明它,我们将取一个包含3个大小为28x28的图像的小批量样本,看看当我们通过网络时它会发生什么。

input_image = torch.rand(3,28,28)
print(input_image.size())
# 输出
torch.Size([3, 28, 28])

nn.Flatten

我们对nn.Flatten层进行初始化,目的是把每一张28×28的二维图像,转换成一个包含784个像素值的连续数组,同时小批量数据的维度(即维度dim=0)会保持不变。
nn.Flatten 是一个扁平化层,其功能是把多维的输入数据展平为一维。在处理图像数据时会经常用到,因为全连接层要求输入是一维向量。

flatten = nn.Flatten()
flat_image = flatten(input_image)
print(flat_image.size())
# 输出
torch.Size([3, 784])

nn.Linear

nn.Linear 是全连接层,也被叫做线性层。它使用其存储的权重和偏差对输入应用线性变换,(就是对输入数据做线性变换)
公式为 y = x A T + b y = xA^T + b y=xAT+b,这里的 x x x 是输入, A A A 是权重矩阵, b b b 是偏置项, y y y 是输出。全连接层能学习输入和输出之间的线性关系,是神经网络的基础组成部分。

layer1 = nn.Linear(in_features=28*28, out_features=20)
hidden1 = layer1(flat_image)
print(hidden1.size())
# 输出
torch.Size([3, 20])

nn.ReLU

nn.ReLU是激活函数层,使用的激活函数是修正线性单元(Rectified Linear Unit,ReLU)。ReLU 的公式是 f ( x ) = max ⁡ ( 0 , x ) f(x) = \max(0, x) f(x)=max(0,x),也就是输入小于 0 时输出为 0,输入大于等于 0 时输出等于输入。ReLU 能给神经网络引入非线性因素,让网络可以学习更复杂的模式。

非线性激活使得模型能够在的输入和输出之间创建出复杂的映射关系。在线性变换后应用以引入非线性,是为了帮助神经网络学习各种现象。

在本示例的模型中,我们在线性层之间使用nn. ReLU,但还有其他激活可以在模型中引入非线性。

print(f"Before ReLU: {hidden1}\n\n")
hidden1 = nn.ReLU()(hidden1)
print(f"After ReLU: {hidden1}")
# 输出
Before ReLU: tensor([[ 0.4158, -0.0130, -0.1144,  0.3960,  0.1476, -0.0690, -0.0269,  0.2690,
          0.1353,  0.1975,  0.4484,  0.0753,  0.4455,  0.5321, -0.1692,  0.4504,
          0.2476, -0.1787, -0.2754,  0.2462],
        [ 0.2326,  0.0623, -0.2984,  0.2878,  0.2767, -0.5434, -0.5051,  0.4339,
          0.0302,  0.1634,  0.5649, -0.0055,  0.2025,  0.4473, -0.2333,  0.6611,
          0.1883, -0.1250,  0.0820,  0.2778],
        [ 0.3325,  0.2654,  0.1091,  0.0651,  0.3425, -0.3880, -0.0152,  0.2298,
          0.3872,  0.0342,  0.8503,  0.0937,  0.1796,  0.5007, -0.1897,  0.4030,
          0.1189, -0.3237,  0.2048,  0.4343]], grad_fn=<AddmmBackward0>)


After ReLU: tensor([[0.4158, 0.0000, 0.0000, 0.3960, 0.1476, 0.0000, 0.0000, 0.2690, 0.1353,
         0.1975, 0.4484, 0.0753, 0.4455, 0.5321, 0.0000, 0.4504, 0.2476, 0.0000,
         0.0000, 0.2462],
        [0.2326, 0.0623, 0.0000, 0.2878, 0.2767, 0.0000, 0.0000, 0.4339, 0.0302,
         0.1634, 0.5649, 0.0000, 0.2025, 0.4473, 0.0000, 0.6611, 0.1883, 0.0000,
         0.0820, 0.2778],
        [0.3325, 0.2654, 0.1091, 0.0651, 0.3425, 0.0000, 0.0000, 0.2298, 0.3872,
         0.0342, 0.8503, 0.0937, 0.1796, 0.5007, 0.0000, 0.4030, 0.1189, 0.0000,
         0.2048, 0.4343]], grad_fn=<ReluBackward0>)

nn.Sequential

nn. Sequential是模块的有序容器。它能按顺序组装多个层,数据按照定义的相同顺序通过所有模块。
使用nn.Sequential可以更方便地构建神经网络,按顺序执行各个层的操作。
可以使用顺序容器来组装一个快速网络,如seq_modules。

seq_modules = nn.Sequential(
    flatten,
    layer1,
    nn.ReLU(),
    nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)

nn.Softmax

nn.Softmax也是激活函数层,使用的是 Softmax 函数。

神经网络的最后一个线性层会输出 “对数几率”(logits)—— 也就是取值范围在负无穷到正无穷之间的原始数值,这些数值会被送到nn.Softmax模块里

Softmax 函数会把输入的每个元素转换为 0 到 1 之间的值,这些数值代表了模型对每个类别的预测概率。dim参数指明了沿着哪个维度。

另外,这些所有数值相加的和必须为 1。所以它通常用于多分类问题的输出层,输出每个类别的概率。

模型参数

神经网络里的很多层都带有可学习的参数,也就是说,这些层有对应的权重和偏置项,在训练过程中会不断优化这些参数。

当你继承nn.Module来创建自己的模型类时,程序会自动记录模型对象里定义的所有字段,这样你就能通过模型的parameters()或者named_parameters()方法来获取所有参数。

在此示例中,我们遍历每个参数,并打印其大小和值的预览。

print(f"Model structure: {model}\n\n")

for name, param in model.named_parameters():
    print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")

# 输出
Model structure: NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear_relu_stack): Sequential(
    (0): Linear(in_features=784, out_features=512, bias=True)
    (1): ReLU()
    (2): Linear(in_features=512, out_features=512, bias=True)
    (3): ReLU()
    (4): Linear(in_features=512, out_features=10, bias=True)
  )
)


Layer: linear_relu_stack.0.weight | Size: torch.Size([512, 784]) | Values : tensor([[ 0.0273,  0.0296, -0.0084,  ..., -0.0142,  0.0093,  0.0135],
        [-0.0188, -0.0354,  0.0187,  ..., -0.0106, -0.0001,  0.0115]],
       device='cuda:0', grad_fn=<SliceBackward0>)

Layer: linear_relu_stack.0.bias | Size: torch.Size([512]) | Values : tensor([-0.0155, -0.0327], device='cuda:0', grad_fn=<SliceBackward0>)

Layer: linear_relu_stack.2.weight | Size: torch.Size([512, 512]) | Values : tensor([[ 0.0116,  0.0293, -0.0280,  ...,  0.0334, -0.0078,  0.0298],
        [ 0.0095,  0.0038,  0.0009,  ..., -0.0365, -0.0011, -0.0221]],
       device='cuda:0', grad_fn=<SliceBackward0>)

Layer: linear_relu_stack.2.bias | Size: torch.Size([512]) | Values : tensor([ 0.0148, -0.0256], device='cuda:0', grad_fn=<SliceBackward0>)

Layer: linear_relu_stack.4.weight | Size: torch.Size([10, 512]) | Values : tensor([[-0.0147, -0.0229,  0.0180,  ..., -0.0013,  0.0177,  0.0070],
        [-0.0202, -0.0417, -0.0279,  ..., -0.0441,  0.0185, -0.0268]],
       device='cuda:0', grad_fn=<SliceBackward0>)

Layer: linear_relu_stack.4.bias | Size: torch.Size([10]) | Values : tensor([ 0.0070, -0.0411], device='cuda:0', grad_fn=<SliceBackward0>)

更多详细内容可以看: torch.nn API
这是 PyTorch 官方稳定版中torch.nn的文档页面,它介绍了构建神经网络的各类基础组件,包括容器、卷积层、池化层、激活函数、损失函数等,还涵盖相关的实用工具函数,帮助开发者搭建和训练神经网络模型。

补充说明

argmax

在 PyTorch 中,argmax 方法的 dim 参数用于指定在哪个维度上寻找最大值的索引。dim 参数的值不同,代表的操作维度也不同,下面为你详细解释 dim=0dim=1dim=2 时的具体含义,并结合示例代码说明。

  1. dim = 0
    dim = 0 时,表示在第 0 个维度(即最外层维度)上寻找最大值的索引。对于一个多维张量,这意味着在每一列(对于二维张量)或者每一个“切片”(对于更高维张量)上进行比较,找出最大值所在的行(或相应维度)的索引。
import torch

# 创建一个二维张量
tensor_2d = torch.tensor([[1, 5, 3],
                          [4, 2, 6]])

# 在第 0 个维度上寻找最大值的索引
result_0 = tensor_2d.argmax(dim=0)
print("dim = 0 时的结果:", result_0)

在这个二维张量 tensor_2d 中,有 2 行 3 列。当 dim = 0 时,会在每一列上进行比较:

  • 对于第 1 列([1, 4]),最大值是 4,其索引为 1。
  • 对于第 2 列([5, 2]),最大值是 5,其索引为 0。
  • 对于第 3 列([3, 6]),最大值是 6,其索引为 1。
    所以最终结果是 tensor([1, 0, 1])
  1. dim = 1
    dim = 1 时,表示在第 1 个维度上寻找最大值的索引。对于二维张量,这意味着在每一行上进行比较,找出最大值所在的列的索引。
import torch

# 创建一个二维张量
tensor_2d = torch.tensor([[1, 5, 3],
                          [4, 2, 6]])

# 在第 1 个维度上寻找最大值的索引
result_1 = tensor_2d.argmax(dim=1)
print("dim = 1 时的结果:", result_1)

在这个二维张量 tensor_2d 中,当 dim = 1 时,会在每一行上进行比较:

  • 对于第 1 行([1, 5, 3]),最大值是 5,其索引为 1。
  • 对于第 2 行([4, 2, 6]),最大值是 6,其索引为 2。
    所以最终结果是 tensor([1, 2])
  1. dim = 2
    dim = 2 时,适用于三维及以上的张量,表示在第 2 个维度上寻找最大值的索引。对于三维张量,这意味着在每个“二维切片”的每一行上进行比较,找出最大值所在的列的索引。
import torch

# 创建一个三维张量
tensor_3d = torch.tensor([[[1, 5, 3],
                           [4, 2, 6]],
                          [[7, 8, 9],
                           [3, 2, 1]]])

# 在第 2 个维度上寻找最大值的索引
result_2 = tensor_3d.argmax(dim=2)
print("dim = 2 时的结果:", result_2)

在这个三维张量 tensor_3d 中,有 2 个“二维切片”,每个切片是一个 2x3 的二维张量。当 dim = 2 时,会在每个“二维切片”的每一行上进行比较:

  • 对于第 1 个“二维切片”:
    • 第 1 行([1, 5, 3]),最大值是 5,其索引为 1。
    • 第 2 行([4, 2, 6]),最大值是 6,其索引为 2。
  • 对于第 2 个“二维切片”:
    • 第 1 行([7, 8, 9]),最大值是 9,其索引为 2。
    • 第 2 行([3, 2, 1]),最大值是 3,其索引为 0。
      所以最终结果是 tensor([[1, 2], [2, 0]])

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

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

相关文章

基于PyQt5与Open3D的轻量化BIM工具开发指南(下)‌

‌基于PyQt5与Open3D的轻量化BIM工具开发指南&#xff08;下&#xff09;‌ ‌——参数化建模、数据导出与性能优化‌ 【跳转】基于PyQt5与Open3D的轻量化BIM工具开发指南&#xff08;上&#xff09;‌ ‌四、详细实现步骤&#xff08;Part 2&#xff09;‌ ‌3. 参数化建模…

Pytest项目_day01(HTTP接口)

HTTP HTTP是一个协议&#xff08;服务器传输超文本到浏览器的传送协议&#xff09;&#xff0c;是基于TCP/IP通信协议来传输数据&#xff08;HTML文件&#xff0c;图片文件&#xff0c;查询结果等&#xff09;。 访问域名 例如www.baidu.com就是百度的域名&#xff0c;我们想…

在vue项目中,使用Patch请求,实现根据id修改某张发票的日结状态

目录 前言 一.问题描述 二.后端实现 1.分析 2.检查后端拦截器&#xff0c;看看是否允许接收Patch类型的请求 3.编写Dto 4.编写controller层 5.编写service层 6.mapper层 7.使用apifox&#xff0c;测试后端接口的可用性 三.前端实现 1.封装api&#xff08;本质是ax…

某快餐店用户市场数据挖掘与可视化

1、必要库的载入 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns2、加载并清洗数据 # 2.1 加载数据 df pd.read_csv(/home/mw/input/survey6263/mcdonalds.csv)# 2.2 数据清洗 # 2.2.1 检查缺失值 print(缺失值情况&#xff1a;) print(df.isn…

[C++面试] 标准容器面试点

一、入门 1、vector和list的区别 [C面试] vector 面试点总结 vector 是动态数组&#xff0c;它将元素存储在连续的内存空间中。支持随机访问&#xff0c;即可以通过下标快速访问任意位置的元素&#xff0c;时间复杂度为 O(1)&#xff0c;准确点是均摊O(1)。但在中间或开头插…

单片机学完开发板,如何继续提升自己的技能?

很多人学完开发板后都会卡在一个尴尬的阶段&#xff1a;觉得自己会的东西不少&#xff0c;但又不知道下一步该干啥。会点C语言&#xff0c;能烧录程序&#xff0c;能点亮LED&#xff0c;玩转按键&#xff0c;搞定串口等等&#xff0c;能用开发板做点小玩意儿&#xff0c;但面对…

明基PD2700U显示器无法调节图像模式

现象&#xff1a;明基PD2700U显示器无法调节图像模式&#xff0c;如下图&#xff1a; 目前未找到根本原因&#xff0c;推测可能是下面的原因&#xff1a; 1、安装了远程桌面软件&#xff1a;向日葵、虚拟显示器 2、显卡插入了接口&#xff0c;但是没接显示器 解决办法&#xf…

基于FPGA轨道交通6U机箱CPCI脉冲板板卡

板卡简介&#xff1a; 本板为脉冲板&#xff0c;脉冲板主要执行CPU下达的指令&#xff0c;通过实现各种控制算法来调节PWM&#xff0c;然后输出光纤PWM信号来驱动变频器功率模块以达到控制电机的目的。 性能规格&#xff1a; 电源&#xff1a;DC5V&#xff1b;15V FPGA&…

如何通过 Airbyte 将数据摄取到 Elasticsearch

作者&#xff1a;来自 Elastic Andre Luiz Airbyte 是一个数据集成工具&#xff0c;可自动化并可扩展地将信息从各种来源传输到不同的目的地。它使你能够从 API、数据库和其他系统提取数据&#xff0c;并将其加载到 Elasticsearch 等平台&#xff0c;以实现高级搜索和高效分析。…

如何用DeepSeek进行项目管理?AI重构项目全生命周期的实践指南

一、项目管理的核心工作范畴 现代项目管理包含六大核心模块&#xff0c;构成完整管理闭环&#xff1a; 1. 需求管理&#xff08;20%工作量&#xff09; 案例&#xff1a;某电商平台"双11"大促项目需整合23个部门的142项需求 关键动作&#xff1a;需求收集→优先级…

vue3 引入element-plus组件后,发现输入的时候没有提示,而且鼠标移到el-button显示unknown的简单解决方法

1、element-plus官方地址 一个 Vue 3 UI 框架 | Element Plus 2、安装 安装 | Element Plus 3、安装插件unplugin-vue-components、unplugin-auto-import并配制 快速开始 | Element Plus 4、输入关键词没有提示及ElButton:unknown的处理 1&#xff09;装个扩展插件&#xf…

【Linux】浅谈环境变量和进程地址空间

一、环境变量 基本概念 环境变量&#xff08;Environment Variables&#xff09;是操作系统提供的一种机制&#xff0c;用于存储和传递配置信息、系统参数、用户偏好设置等。 环境变量的作用 配置程序行为&#xff1a; 程序可以通过环境变量获取配置信息&#xff0c;例如日…

如何使用 DeepEval 优化 Elasticsearch 中的 RAG 检索

作者&#xff1a;来自 Elastic Kritin Vongthongsri 学习如何使用 DeepEval 优化 RAG 流水线中的 Elasticsearch 检索器。 LLMs 容易产生幻觉、缺乏特定领域的专业知识&#xff0c;并受限于上下文窗口。检索增强生成&#xff08;Retrieval-Augmented Generation - RAG&#xff…

行为模式---状态模式

概念 状态模式是一种行为模式&#xff0c;用于在内部状态改变的时候改变其行为。它的核心思想就是允许一个对象在其内部状态改变的时候改变它的行为。状态模式通过将对象的状态封装成独立的类&#xff0c;并将其行为委托给当前的状态对象&#xff0c;从而使得对象行为随着状态…

嵌入式裸机设计--MCU常用裸机架构有哪些?

为什么是裸机设计 792125321入群学习更高效&#xff01; 在MCU&#xff08;微控制器单元&#xff09;裸机开发中&#xff0c;我们常见的架构设计主要围绕如何高效管理资源和任务调度。认识这些开发方式&#xff0c;对我们开发一个小型项目来说及有好处&#xff01; 下面介绍…

【LInux进程六】命令行参数和环境变量

【LInux进程六】命令行参数和环境变量 1.main函数的两个参数2.利用main函数实现一个简单的计算器3.环境变量之一&#xff1a;PATH4.修改PATH5.在命令行解释器bash中查看所有环境变量6.用自己写的程序查看环境变量7.main函数的第三个参数8.本地的环境变量和环境变量9.环境变量具…

激光slam学习笔记10---ubuntu2004部署运行fastlivo2踩坑记录

背景&#xff1a;mars实验室又发福利啦&#xff01;跑跑效果&#xff0c;验了那句&#xff0c;mars出品&#xff0c;必属精品&#xff01;本人pc环境ubuntu20.04&#xff0c;基本流程按照readme走就行&#xff0c;sophus和vikit安装有些注意地方。本文做了一些部署踩坑记录&…

织梦DedeCMS优化文章模版里的“顶一下”与“踩一下”样式

测试的版本5.7.1UTF-8 一、插入<head>Js代码 将下面代码插入到文章模版里的<head>标签里 <script language"javascript" type"text/javascript" src"{dede:global.cfg_cmsurl/}/include/dedeajax2.js"></script> <…

IDEA+Docker插件一键部署SpringBoot项目到远程服务器

文章目录 1. 服务端1.1 安装Docker1.2 Docker放开远程连接1.3 重启Docker1.4 开放端口1.4.1 云端1.4.2 服务器内部防火墙指令 2.IntelliJ IDEA2.1 安装IDEA2.2 安装Docker插件2.3 SSH Configurations2.4 Docker选择对应的SSH2.5 Dockerfile2.5.1 Dockerfile2.5.2 Dockerfile Ed…

C++基础 [五] - String的模拟实现

目录 前言 string类的模拟实现 成员函数的实现 构造函数 拷贝构造函数 赋值运算符重载 析构函数 元素访问的实现 operator[ ] Iterator - 迭代器 容量大小的实现 size capacity reserve ​编辑resize 内容修改的实现 push_back append operator(char ch) …