神经网络中的层与块:概念与PyTorch实现
创作时间:
作者:
@小白创作中心
神经网络中的层与块:概念与PyTorch实现
引用
CSDN
1.
https://m.blog.csdn.net/qq_62827972/article/details/140369938
本文总结了神经网络中的层与块的概念及其在PyTorch中的实现方式,适合深度学习初学者阅读。
在介绍神经网络时,我们通常会从单一输出的线性模型开始,然后过渡到具有多个输出的网络。随着研究的深入,我们发现需要一个介于单个层和整个模型之间的组件,这就是神经网络块(block)的概念。
块可以描述单个层、由多个层组成的组件,甚至是整个模型本身。使用块进行抽象的一个重要优点是,可以将一些块组合成更大的组件,这一过程通常是递归的。通过定义代码来按需生成任意复杂度的块,我们可以用简洁的代码实现复杂的神经网络。
自定义块
为了更好地理解“块”的概念,我们可以自己实现一个简单的多层感知器(MLP):
import torch
import torch.nn as nn
import torch.nn.functional as F
class MLP(nn.Module):
# 用模型参数声明层。这里,我们声明两个全连接的层
def __init__(self):
# 调用MLP的父类Module的构造函数来执行必要的初始化。
# 这样,在类实例化时也可以指定其他函数参数,例如模型参数params(稍后将介绍)
super().__init__()
self.hidden = nn.Linear(20, 256) # 隐藏层
self.out = nn.Linear(256, 10) # 输出层
# 定义模型的前向传播,即如何根据输入X返回所需的模型输出
def forward(self, X):
# 注意,这里我们使用ReLU的函数版本,其在nn.functional模块中定义。
return self.out(F.relu(self.hidden(X)))
# 实例化这个类
net = MLP()
X = torch.randn(2, 20) # 随机生成输入数据
output = net(X) # 等效于net.forward(X)
print(output)
输出结果如下:
tensor([[ 0.2535, -0.1106, 0.1944, -0.1779, -0.1540, 0.0939, 0.2560, 0.1141,
0.0368, -0.1281],
[ 0.0286, 0.0554, 0.1914, 0.0065, -0.0017, 0.2003, 0.0707, 0.0512,
-0.0016, -0.0085]], grad_fn=<AddmmBackward0>)
这个例子展示了如何定义一个简单的MLP模型。值得注意的是,当我们调用net(X)
时,实际上是在调用net.forward(X)
。
顺序块
接下来,我们来看看如何实现一个顺序块。顺序块类似于PyTorch中的nn.Sequential
,但提供了更多的灵活性:
class MySequential(nn.Module):
def __init__(self, *args):
super().__init__()
for idx, module in enumerate(args):
# 这里,module是Module子类的一个实例。我们把它保存在'Module'类的成员
# 变量_modules中。_module的类型是OrderedDict
self._modules[str(idx)] = module
def forward(self, X):
# OrderedDict保证了按照成员添加的顺序遍历它们
for block in self._modules.values():
X = block(X)
return X
# 使用顺序块
net = MySequential(nn.Linear(20, 256), nn.ReLU(), nn.Linear(256, 10))
X = torch.randn(2, 20) # 随机生成输入数据
output = net(X)
print(output)
输出结果如下:
tensor([[ 0.0011, 0.1545, -0.0147, -0.0517, -0.1129, 0.1292, 0.3381, 0.0989,
-0.0893, -0.0295],
[-0.0605, 0.1350, -0.0213, -0.1577, -0.0175, 0.0041, 0.2423, -0.0636,
-0.0778, 0.0949]], grad_fn=<AddmmBackward0>)
这段代码定义了一个名为 MySequential
的类,它继承自 PyTorch 的 nn.Module
类。这个类实现了一个自定义的序列模型,类似于 PyTorch 的 nn.Sequential
,但是提供了一种自定义的方式来添加模块。下面是代码的逐行解释:
class MySequential(nn.Module)
:定义了一个名为MySequential
的类,它继承自nn.Module
。__init__(self, *args)
:构造函数接受任意数量的位置参数*args
。这些参数应该是nn.Module
的子类实例。super().__init__()
:调用父类nn.Module
的构造函数来执行必要的初始化。for idx, module in enumerate(args):
:遍历所有传入的参数。enumerate
函数返回每个参数的索引(idx
)和参数本身(module
)。self._modules[str(idx)] = module
:将每个模块实例添加到_modules
字典中。索引被转换为字符串,因为_modules
字典的键需要是字符串类型。这里使用字符串索引而不是数字索引是为了保持模块添加的顺序,类似于OrderedDict
。def forward(self, X)
:定义了模型的前向传播方法。for block in self._modules.values():
:遍历_modules
字典中的所有值(即所有模块实例)。X = block(X)
:对输入X
应用当前模块block
,并更新X
为模块的输出。return X
:返回经过所有模块处理后的最终输出。
这个自定义的 MySequential
类允许你以顺序的方式堆叠多个神经网络模块。每个模块将按照它们添加到 MySequential
实例中的顺序依次应用于输入数据 X
。这与 PyTorch 的内置 nn.Sequential
类的功能类似,但提供了更多的灵活性,例如通过索引访问特定的模块或修改模块的顺序。
小结
- 一个块可以由许多层组成;一个块可以由许多块组成。
- 块可以包含代码。
- 块负责大量的内部处理,包括参数初始化和反向传播。
- 层和块的顺序连接由Sequential块处理。
热门推荐
驶向港口经济新蓝海——山东日照港产城融合激活城市发展新动能
新型半导体光放大器设计:如何实现高增益和高饱和输出功率
内镜检查前 准备工作要做好
2024年嘉兴市秀洲区公办初中招生学区划片范围一览表
2400 万难掩民愤,新能源自燃烧小区谁该赔?
如何评价吕布?作为一方诸侯他为何不能在乱世立足?一文说清楚
近十年中国各省人均收入变化GIS分析 | 你涨了多少工资呢?
跳绳减脂全攻略:从基础姿势到高效训练计划详解
中央红军长征,从8.6万人锐减到7千人,红军兵力究竟损耗在何处?
生物医学工程在职研究生哪个大学好
太行山上的造林队:15年植树1170万株 10万荒山披绿装
2025植物科学与技术专业就业前景及方向:好找工作吗?
延迟退休对养老金金融的影响与对策建议
重启人生—DBS手术治疗帕金森病
山东中医药大学赴新加坡、美国高校交流访问
投资海南 | 这里的榴莲,为啥可以“睡到自然醒”?
国外论文文献如何查找
针灸助力自然受孕,为不孕患者解难题
补牙后的注意事项有哪些
崴了脚后久治不愈,影响髋、膝关节!正确康复训练方法在此
砭石的作用(砭石的来历及作用)
揭秘防晒误区,教你科学防晒新姿势
夫妻共同财产中的银行存款分割
查尔斯国王勇敢与胰腺癌抗争,医生预测他只能活两年
降息对经济发展的影响及其未来趋势分析
中国最好二本民办大学排名
哪款SUV最适合跑川藏线?看这篇就够了,总有一款适合你!
DeepSeek:预测2025低空经济人才招聘趋势
先天性肾上腺皮质增生症
宝宝肠绞痛的五大特征,新手爸妈必读!