详细介绍:PyTorch 神经网络工具箱
一、神经网络核心组件
神经网络的正常运行依赖于几个关键组件,它们各自承担着不同且重要的角色,共同构成了神经网络的基础架构。
组件 | 作用 |
---|---|
层 | 神经网络的基本结构,能够将输入张量按照特定的规则转换为输出张量,是数据在网络中流转和处理的核心环节 |
模型 | 由多个层按照一定的逻辑和顺序构成的网络结构,是实现特定任务(如分类、回归等)的完整系统 |
损失函数 | 作为参数学习的目标函数,用于衡量模型预测结果与真实值之间的差异,模型通过最小化损失函数来调整自身参数,以提高预测准确性 |
优化器 | 负责确定如何使损失函数达到最小值,即通过特定的算法(如梯度下降法及其变种)来更新模型的参数,指导模型朝着更优的方向学习 |
二、构建神经网络的主要工具
(一)nn.Module
- 核心特性
- 继承自
nn.Module
类的模块,能够自动提取网络中可学习的参数,极大地简化了参数管理的工作。 - 适用于构建卷积层(如
nn.Conv2d
)、全连接层(如nn.Linear
)、dropout 层(如nn.Dropout
)等需要进行参数学习的网络层。
- 继承自
- 使用方式:写法一般为
nn.Xxx
,例如nn.Linear
用于构建全连接层,nn.Conv2d
用于构建二维卷积层,nn.CrossEntropyLoss
用于定义交叉熵损失函数等。在使用时,需要先实例化该类并传入相应的参数,然后以函数调用的方式传入输入数据进行计算。
(二)nn.functional
- 核心特性
- 更像是一组纯函数,不具备
nn.Module
类的参数管理和自动求导等额外功能。 - 适用于激活函数(如 ReLU、Sigmoid)、池化层(如最大池化、平均池化)等不需要进行参数学习的操作。
- 更像是一组纯函数,不具备
- 使用方式:写法一般为
nn.functional.xxx
,例如nn.functional.linear
实现全连接层的计算功能,nn.functional.conv2d
实现二维卷积操作,nn.functional.cross_entropy
计算交叉熵损失等。
(三)两者区别
对比维度 | nn.Xxx | nn.functional.xxx |
---|---|---|
继承关系 | 继承于nn.Module | 无继承关系,属于纯函数 |
实例化与调用 | 需先实例化并传入参数,再以函数调用方式传入数据 | 无需实例化,直接调用函数并传入数据和相关参数(如 weight、bias) |
与 nn.Sequential 结合 | 能很好地与nn.Sequential 结合使用,便于构建顺序型网络 | 无法与nn.Sequential 结合使用 |
参数管理 | 无需自己定义和管理 weight、bias 等参数,模块内部自动处理 | 需要自己定义和管理 weight、bias 等参数,每次调用都需手动传入,不利于代码复用 |
dropout 状态转换 | 在调用model.eval() 之后,自动实现训练和测试阶段的状态转换 | 无此自动转换功能,需要手动控制 dropout 在不同阶段的状态 |
三、构建模型的方法
(一)继承 nn.Module 基类构建模型
- 步骤
- 定义一个继承自
nn.Module
的类,在类的__init__
方法中定义网络的各个层,如全连接层、批量归一化层、展平层等。 - 实现
forward
方法,在该方法中定义数据在网络中的前向传播路径,即数据经过各个层的顺序和计算方式。
- 定义一个继承自
- 代码示例
import torch
from torch import nn
import torch.nn.functional as F
class Model_Seq(nn.Module):
# 通过继承基类nn.Module来构建模型
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
super(Model_Seq, self).__init__()
self.flatten = nn.Flatten()
self.linear1 = nn.Linear(in_dim, n_hidden_1)
self.bn1 = nn.BatchNorm1d(n_hidden_1)
self.linear2 = nn.Linear(n_hidden_1, n_hidden_2)
self.bn2 = nn.BatchNorm1d(n_hidden_2)
self.out = nn.Linear(n_hidden_2, out_dim)
def forward(self, x):
x = self.flatten(x)
x = self.linear1(x)
x = self.bn1(x)
x = F.relu(x)
x = self.linear2(x)
x = self.bn2(x)
x = F.relu(x)
x = self.out(x)
x = F.softmax(x, dim=1)
return x
# 对一些超参数赋值
in_dim, n_hidden_1, n_hidden_2, out_dim = 28 * 28, 300, 100, 10
model_seq = Model_Seq(in_dim, n_hidden_1, n_hidden_2, out_dim)
print(model_seq)
- 运行结果
Model_Seq(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear1): Linear(in_features=784, out_features=300, bias=True)
(bn1): BatchNorm1d(300, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(linear2): Linear(in_features=300, out_features=100, bias=True)
(bn2): BatchNorm1d(100, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(out): Linear(in_features=100, out_features=10, bias=True)
)
(二)使用 nn.Sequential 按层顺序构建模型
nn.Sequential
是一个有序的容器,它能够按照添加层的顺序依次执行前向传播操作,方便快速构建简单的顺序型网络。主要有以下三种构建方式:
- 利用可变参数
- 直接将各个层作为可变参数传入
nn.Sequential
中,层的顺序即为前向传播的顺序。但这种方法不能给每个层指定名称。 - 代码示例
- 直接将各个层作为可变参数传入
in_dim, n_hidden_1, n_hidden_2, out_dim = 28 * 28, 300, 100, 10
Seq_arg = nn.Sequential(
nn.Flatten(),
nn.Linear(in_dim, n_hidden_1),
nn.BatchNorm1d(n_hidden_1),
nn.ReLU(),
nn.Linear(n_hidden_1, n_hidden_2),
nn.BatchNorm1d(n_hidden_2),
nn.ReLU(),
nn.Linear(n_hidden_2, out_dim),
nn.Softmax(dim=1)
)
print(Seq_arg)
- 使用 add_module 方法
- 通过调用
add_module
方法,为每个层指定一个名称,并将其添加到nn.Sequential
容器中,便于后续对特定层进行操作和查看。 - 代码示例
- 通过调用
in_dim, n_hidden_1, n_hidden_2, out_dim = 28 * 28, 300, 100, 10
Seq_module = nn.Sequential()
Seq_module.add_module("flatten", nn.Flatten())
Seq_module.add_module("linear1", nn.Linear(in_dim, n_hidden_1))
Seq_module.add_module("bn1", nn.BatchNorm1d(n_hidden_1))
Seq_module.add_module("relu1", nn.ReLU())
Seq_module.add_module("linear2", nn.Linear(n_hidden_1, n_hidden_2))
Seq_module.add_module("bn2", nn.BatchNorm1d(n_hidden_2))
Seq_module.add_module("relu2", nn.ReLU())
Seq_module.add_module("out", nn.Linear(n_hidden_2, out_dim))
Seq_module.add_module("softmax", nn.Softmax(dim=1))
print(Seq_module)
- 运行结果
Sequential(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear1): Linear(in_features=784, out_features=300, bias=True)
(bn1): BatchNorm1d(300, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu1): ReLU()
(linear2): Linear(in_features=300, out_features=100, bias=True)
(bn2): BatchNorm1d(100, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu2): ReLU()
(out): Linear(in_features=100, out_features=10, bias=True)
(softmax): Softmax(dim=1)
)
- 使用 OrderedDict 方法
- 借助
collections.OrderedDict
来构建一个有序的字典,字典中的键为层的名称,值为对应的层对象,然后将该有序字典传入nn.Sequential
中,实现带名称的层顺序构建。
- 借助
(三)继承 nn.Module 基类并应用模型容器构建模型
除了单独使用nn.Module
或nn.Sequential
构建模型外,还可以继承nn.Module
基类,并结合nn.Sequential
、nn.ModuleList
、nn.ModuleDict
等模型容器来构建更灵活、复杂的网络结构。
- 使用 nn.Sequential 模型容器
- 在继承
nn.Module
的类中,将多个相关的层组合到nn.Sequential
容器中,形成一个子模块,使网络结构更加清晰,便于管理和维护。 - 代码示例
- 在继承
class Model_lay(nn.Module):
# 使用sequential构建网络,Sequential()函数的功能是将网络的层组合到一起
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
super(Model_lay, self).__init__()
self.flatten = nn.Flatten()
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.out = nn.Sequential(nn.Linear(n_hidden_2, out_dim))
def forward(self, x):
x = self.flatten(x)
x = F.relu(self.layer1(x))
x = F.relu(self.layer2(x))
x = F.softmax(self.out(x), dim=1)
return x
in_dim, n_hidden_1, n_hidden_2, out_dim = 28 * 28, 300, 100, 10
model_lay = Model_lay(in_dim, n_hidden_1, n_hidden_2, out_dim)
print(model_lay)
- 运行结果
Model_lay(
(flatten): Flatten(start_dim=1, end_dim=-1)
(layer1): Sequential(
(0): Linear(in_features=784, out_features=300, bias=True)
(1): BatchNorm1d(300, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(layer2): Sequential(
(0): Linear(in_features=300, out_features=100, bias=True)
(1): BatchNorm1d(100, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(out): Sequential(
(0): Linear(in_features=100, out_features=10, bias=True)
)
)
- 使用 nn.ModuleList 模型容器
nn.ModuleList
是一个用于存储多个模块的列表容器,它支持像普通列表一样的索引操作。在构建网络时,可以将多个层添加到nn.ModuleList
中,然后在forward
方法中通过循环依次调用这些层。- 代码示例
class Model_lst(nn.Module):
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
super(Model_lst, self).__init__()
self.layers = nn.ModuleList([
nn.Flatten(),
nn.Linear(in_dim, n_hidden_1),
nn.BatchNorm1d(n_hidden_1),
nn.ReLU(),
nn.Linear(n_hidden_1, n_hidden_2),
nn.BatchNorm1d(n_hidden_2),
nn.ReLU(),
nn.Linear(n_hidden_2, out_dim),
nn.Softmax(dim=1)
])
def forward(self, x):
for layer in self.layers:
x = layer(x)
return x
in_dim, n_hidden_1, n_hidden_2, out_dim = 28 * 28, 300, 100, 10
model_lst = Model_lst(in_dim, n_hidden_1, n_hidden_2, out_dim)
print(model_lst)
- 运行结果
Model_lst(
(layers): ModuleList(
(0): Flatten(start_dim=1, end_dim=-1)
(1): Linear(in_features=784, out_features=300, bias=True)
(2): BatchNorm1d(300, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(3): ReLU()
(4): Linear(in_features=300, out_features=100, bias=True)
(5): BatchNorm1d(100, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(6): ReLU()
(7): Linear(in_features=100, out_features=10, bias=True)
(8): Softmax(dim=1)
)
)
- 使用 nn.ModuleDict 模型容器
nn.ModuleDict
是一个以字典形式存储模块的容器,字典的键为字符串类型的层名称,值为对应的模块。在forward
方法中,可以根据需要按照指定的层名称顺序调用相应的层,灵活性较高。- 代码示例
import torch
from torch import nn
class Model_dict(nn.Module):
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
super(Model_dict, self).__init__()
self.layers_dict = nn.ModuleDict({
"flatten": nn.Flatten(),
"linear1": nn.Linear(in_dim, n_hidden_1),
"bn1": nn.BatchNorm1d(n_hidden_1),
"relu": nn.ReLU(),
"linear2": nn.Linear(n_hidden_1, n_hidden_2),
"bn2": nn.BatchNorm1d(n_hidden_2),
"out": nn.Linear(n_hidden_2, out_dim),
"softmax": nn.Softmax(dim=1)
})
def forward(self, x):
layers = ["flatten", "linear1", "bn1", "relu", "linear2", "bn2", "relu", "out", "softmax"]
for layer in layers:
x = self.layers_dict[layer](x)
return x
in_dim, n_hidden_1, n_hidden_2, out_dim = 28 * 28, 300, 100, 10
model_dict = Model_dict(in_dim, n_hidden_1, n_hidden_2, out_dim)
print(model_dict)
- 运行结果
Model_dict(
(layers_dict): ModuleDict(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear1): Linear(in_features=784, out_features=300, bias=True)
(bn1): BatchNorm1d(300, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU()
(linear2): Linear(in_features=300, out_features=100, bias=True)
(bn2): BatchNorm1d(100, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(out): Linear(in_features=100, out_features=10, bias=True)
(softmax): Softmax(dim=1)
)
)
四、自定义网络模块
在实际应用中,为了满足特定的任务需求,常常需要自定义网络模块。以残差网络(ResNet)中的残差块为例,介绍自定义网络模块的方法。
(一)正常残差块(RestNetBasicBlock)
- 功能:该残差块将输入与经过两层卷积和批量归一化处理后的输出直接相加,然后应用 ReLU 激活函数,适用于输入和输出特征图尺寸相同的情况。
- 代码示例
import torch
import torch.nn as nn
from torch.nn import functional as F
class RestNetBasicBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride):
super(RestNetBasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
self.bn1 = nn.BatchNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=stride, padding=1)
self.bn2 = nn.BatchNorm2d(out_channels)
def forward(self, x):
output = self.conv1(x)
output = F.relu(self.bn1(output))
output = self.conv2(output)
output = self.bn2(output)
return F.relu(x + output)
(二)下采样残差块(RestNetDownBlock)
- 功能:当输入和输出特征图尺寸不同时,该残差块通过添加一个 1×1 卷积层来调整输入的通道数和分辨率,使输入与经过两层卷积和批量归一化处理后的输出能够进行相加操作。
- 代码示例
class RestNetDownBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride):
super(RestNetDownBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride[0], padding=1)
self.bn1 = nn.BatchNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=stride[1], padding=1)
self.bn2 = nn.BatchNorm2d(out_channels)
self.extra = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride[0], padding=0),
nn.BatchNorm2d(out_channels)
)
def forward(self, x):
extra_x = self.extra(x)
output = self.conv1(x)
out = F.relu(self.bn1(output))
out = self.conv2(out)
out = self.bn2(out)
return F.relu(extra_x + out)
(三)组合残差块构建 ResNet18 网络
通过组合上述两种残差块,可以构建出经典的 ResNet18 网络结构,该网络在图像分类等任务中具有出色的性能。
- 代码示例
class RestNet18(nn.Module):
def __init__(self):
super(RestNet18, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)
self.bn1 = nn.BatchNorm2d(64)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = nn.Sequential(RestNetBasicBlock(64, 64, 1),
RestNetBasicBlock(64, 64, 1))
self.layer2 = nn.Sequential(RestNetDownBlock(64, 128, [2, 1]),
RestNetBasicBlock(128, 128, 1))
self.layer3 = nn.Sequential(RestNetDownBlock(128, 256, [2, 1]),
RestNetBasicBlock(256, 256, 1))
self.layer4 = nn.Sequential(RestNetDownBlock(256, 512, [2, 1]),
RestNetBasicBlock(512, 512, 1))
self.avgpool = nn.AdaptiveAvgPool2d(output_size=(1, 1))
self.fc = nn.Linear(512, 10)
def forward(self, x):
out = self.conv1(x)
out = self.bn1(out)
out = self.maxpool(out)
out = self.layer1(out)
out = self.layer2(out)
out = self.layer3(out)
out = self.layer4(out)
out = self.avgpool(out)
out = out.reshape(x.shape[0], -1)
out = self.fc(out)
return out
五、训练模型的步骤
训练一个神经网络模型通常需要遵循以下六个主要步骤,每个步骤都至关重要,直接影响模型的训练效果和最终性能。
- 加载预处理数据集:获取用于训练和测试的数据集,并对数据进行预处理操作,如归一化、标准化、数据增强等,使数据符合模型的输入要求,同时提高模型的泛化能力。
- 定义损失函数:根据具体的任务类型(如分类任务常用交叉熵损失函数,回归任务常用均方误差损失函数)选择合适的损失函数,用于衡量模型预测值与真实值之间的差异。
- 定义优化方法:选择合适的优化器(如随机梯度下降 SGD、自适应矩估计 Adam 等),并设置相关的超参数(如学习率、动量等),优化器将根据损失函数的梯度信息更新模型的参数,以最小化损失函数。
- 循环训练模型:在训练集上进行多轮迭代训练,每一轮迭代中,将数据输入模型进行前向传播计算得到预测结果,然后根据损失函数计算损失值,再通过反向传播计算梯度,最后使用优化器更新模型参数。
- 循环测试或验证模型:在每轮训练结束后,使用测试集或验证集对模型的性能进行评估,计算模型的准确率、精度、召回率等指标,以监控模型的训练进度和泛化能力,及时发现过拟合等问题。
- 可视化结果:通过绘制损失函数曲线、准确率曲线等方式,直观地展示模型的训练过程和性能变化情况,帮助分析模型的训练效果,为后续的模型调整和优化提供依据。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/917017.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
C++ new 操作符在操作系统层执行了什么操作?
C++ new 操作符在操作系统层执行了什么操作?在C++中,new操作符的执行涉及操作系统层面的内存分配和对象构造过程,具体可分为以下几个关键步骤:
1. 调用内存分配函数(operator new)
new操作符首先通过operator ne…
[ABC422F-G] 题解
QwQ[ABC422F-G] 题解
F - Eat and Ride
考虑 DP,DP 状态要么压和要么压长度,如果压和就很直接,但是显然复杂度会爆炸,如果压长度的话,可以发现每到一个新点都要算:这条路径中在它后面的点的个数乘上它的点权,所…
天津模板建站代理wordpress增加赞赏
代码参考:《重学Java设计模式小傅哥》 目录1、静态类使用2、懒汉模式(线程不安全)3、懒汉模式(线程安全)4、饿汉模式(线程安全)5、使用类的内部类(线程安全)6、双重锁检验…
最新获取网站访客qq接口推客平台有哪些
传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。
媒体邀约的好处主要体现在提高品牌知名度、扩大受众群体以及与媒体建立良好的合作关系。
媒体邀约是一种有效的公关策略,通过吸引媒体关注来促进信息的传播。它可以帮助组织…
山东省住房和城乡建设部网站首页四川润邦建设工程设计有限公司网站
大家好,我是阿赵。 这篇文章我想写了很久,是关于Unity项目使用AssetBundle加载资源时的内存管理的。这篇文章不会分享代码,只是分享思路,思路不一定正确,欢迎讨论。 对于Unity引擎的资源内存管理,我…
公司网站模板源代码常州微网站建设文档
如果有客户端1、客户端2等N个客户端争抢一个 Zookeeper 分布式锁。大致如下:
1: 大家都是上来直接创建一个锁节点下的一个接一个的临时有序节点
2: 如果自己不是第一个节点,就对自己上一个节点加监听器
3: 只要上一…
c# Listdynamic 按字段排序
public static List<dynamic> OrderByKey (this IList<dynamic> list, string propertyName, bool isDescending = false){var propertyInfo = list[0].GetType().GetProperty(propertyName);if (isDescen…
建设一个货代网站想要多少钱做谷歌网站使用什么统计代码
官方文档:入门指南 | Selenium Selenium是一个用于Web应用测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。 所以使用这个前端测试话工具,可以自动化做很多事情,比如自动化抓取网页内容,俗称网…
大兴网站定制开发房地产招新人的坑
依赖倒转原则
在大话设计模式这本书中,作者通过电话修电脑这个例子引入了面向对象设计的基本原则之一:依赖倒转原则。
概念
依赖倒转原则是面向对象设计的基本原则之一,它用于减少类之间的耦合,提高系统的灵活性和可维护性。在…
东莞网站制作电话糗事百科 wordpress
文章目录1. 题目2. 解题1. 题目
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回符合要求的最少分割次数。
示例:
输入: "aab"
输出: 1
解释: 进行一次分割就可将 s 分割成 ["aa","b"] 这样两个回文…
济南网站建设公司 推荐行知科技自己做网站用什么app
前言
本文主要介绍Redis的三种持久化方式、AOF持久化策略等
什么是持久化
持久化是指将数据在内存中的状态保存到非易失性介质(如硬盘、固态硬盘等)上的过程。在计算机中,内存中的数据属于易失性数据,一旦断电或重启系统&#…
别再靠 “关设备” 减碳!EMS 的 “预测性控能”,让企业满产也能达标双碳
在 “双碳” 目标推进的当下,减碳已成为企业发展的必答题。然而,不少企业仍陷入 “减碳就减产” 的困境 —— 为了降低碳排放,不得不采取关停生产线、限制设备运行时长等简单粗暴的方式,结果导致订单交付延迟、产能…
双活、异地多活架构怎么设计才不翻车? - 教程
pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …
四川网站建设培训学校高端公司小程序建设
优先级
在同一级目录下,会先比较前缀bootstrap、application,其中bootstrap比application的优先级高,其次再去比较后缀.properties、.yml,其中.properties比.yml优先级高
所以它们的执行顺序如下: bootstrap.propert…
LAMP 架构说明及部署实践 - 教程
LAMP 架构说明及部署实践 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&qu…