神经网络中的层与块:概念与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块处理。
热门推荐
李子坝单轨穿楼观景平台
台儿庄战役:李宗仁指挥艺术揭秘
台儿庄大捷:李宗仁的抗战传奇
李宗仁的“焦土抗战论”:从理论到徐州会战的实践
黄道吉日购车,你选对日子了吗?
车内摆件大揭秘:好运常伴的秘密武器
双十一购车大揭秘:你的幸运星座吉日
激光雷达装机量暴增127%,L3自动驾驶时代加速到来
激光雷达:航天器精准导航的“千里眼”
美联储降息对国际油价影响几何?
激光雷达助力火星着陆新突破!🚀
炒菜时,用鸡精好还是味精好?真相竟是......
6种天然调味料,对肾很不错
运动领域的可穿戴技术
中国冰雪运动市场将更加火热 发展潜力巨大
AB罗克韦尔变频器维修指南:从安全操作到故障排查
如何添加音乐到苹果云盘
品达地堡:现代军事核战防御的秘密武器?
广岛长崎核爆74年后的今天:人类是否吸取了教训?
航天器导航新宠:导航型LiDAR
关于「过敏」的这些事儿,你真的清楚吗?
揭秘!远程医疗与智能穿戴设备如何降低医疗费用?
中国地图上的中温带干旱区:气候、地形与生态特征解析
裴秀制图六体:中国古代地图学的里程碑
昆明房租跌跌不休,租客房东都哭了
心理科普 | 缺爱型人格
英语作文写作:灵活运用句型,提升文章表现力
揭秘!爱德华七世情妇背后的惊人秘密与混乱故事
伊丽莎白二世女王:演绎一生的角色
隼鸟2号揭秘:激光雷达如何助力精准着陆?