671 字
3 分钟
深度神经网络-层和块

层和块#

深度神经网络由许多神经网络层组成,每一层都可以看作处理或提取出某一种特征。

为了整合多个层,我们可以定义一个块来包括一些紧密联系的层。

例如:nn.Linear()就会生成一个线性模型层

自定义块#

假设我们要实现一个MLP(多层感知机)的模块,这个MLP中包含一个20*20的线性层和256*256的层.

块的基本构成:

  1. 有输入
  2. 通过前向传播函数,经过多个传播层,得到输出。自定义添加隐藏层。
  3. 计算输入关于输出的梯度,可以使用反向传播算法。
  4. 存储和访问前向传播计算的参数,forward()函数
  5. 根据需要初始化模型参数__init__()函数
class MLP(nn.Block):
# 用模型参数声明层。这里,我们声明两个全连接的层
def __init__(self, **kwargs):
# 调用MLP的父类Block的构造函数来执行必要的初始化。
# 这样,在类实例化时也可以指定其他函数参数,例如模型参数params(稍后将介绍)
super().__init__(**kwargs)
self.hidden = nn.Dense(256, activation='relu') # 隐藏层
self.out = nn.Dense(10) # 输出层
# 定义模型的前向传播,即如何根据输入X返回所需的模型输出
def forward(self, X):
return self.out(self.hidden(X))

顺序快#

pytorch定义了Module类,来表示模型块。

我们可以自定义函数,来向Module中添加自定义的隐藏层。

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
"""
通过add(block),给顺序块中加入多个隐藏层
计算梯度时,逐个调用这些隐藏层,得到输出。
"""
def forward(self, X):
# OrderedDict保证了按照成员添加的顺序遍历它们
for block in self._modules.values():
X = block(X)
return X

自定义前向传播函数#

在前向传播函数forward()中,我们可以添加额外的运算操作。

class FixedHiddenMLP(nn.Module):
def __init__(self):
super().__init__()
# 不计算梯度的随机权重参数。因此其在训练期间保持不变
self.rand_weight = torch.rand((20, 20), requires_grad=False)
self.linear = nn.Linear(20, 20)
"""
nn.Linear()会自动正则化初始参数。
在forward前向传播函数中,我们可以自定义额外的运算
比如添加relu激活函数。
"""
def forward(self, X):
X = self.linear(X)
# 使用创建的常量参数以及relu和mm函数
X = F.relu(torch.mm(X, self.rand_weight) + 1)
# 复用全连接层。这相当于两个全连接层共享参数
X = self.linear(X)
# 控制流,下面这段没有实际意义。
while X.abs().sum() > 1:
X /= 2
return X.sum()
深度神经网络-层和块
https://chrisnake11.github.io/blog/posts/others/neural-network/pytorch/自定义层和块/
作者
Zheyv
发布于
2024-08-30
许可协议
CC BY-NC-SA 4.0