深度学习(5):torch.nn.Module
文章目录
- 一、是什么
- 二、`nn.Module` 的核心功能
- 三、`nn.Module` 的基本用法
- 1. 定义自定义模型
- 2. 初始化模型
- 3. 模型的使用
- 四、`nn.Module` 的关键特性
- 1. 自动注册子模块和参数
- 2. `forward` 方法
- 3. 不需要定义反向传播
- 五、常用的内置模块
- 六、示例:创建一个简单的神经网络
- 1. 问题描述
- 2. 模型定义
- 3. 训练过程
- 七、深入理解 `nn.Module` 的一些重要概念
- 1. 参数访问
- 2. 模块访问
- 3. 保存和加载模型
- 4. 自定义层和模块
- 八、`nn.Module` 的实践技巧
- 1. 使用 `Sequential` 快速构建模型
- 2. 模型的嵌套
- 九、总结
- 十、参考示例:完整的训练脚本
一、是什么
torch.nn.Module
是 PyTorch 中所有神经网络模块的基类,是构建神经网络模型的核心组件。
二、nn.Module
的核心功能
-
参数管理:自动管理模型的可训练参数(
parameters
),方便参数的访问和更新。 -
子模块管理:支持将模型分解为多个子模块,便于组织复杂的网络结构。
-
前向计算(forward):定义模型的前向传播逻辑。
三、nn.Module
的基本用法
1. 定义自定义模型
要创建自定义的神经网络模型,需要继承 nn.Module
,并实现以下内容:
- 构造函数
__init__
:在这里定义网络的层和子模块。 - 前向方法
forward
:定义数据如何经过网络进行前向传播。
import torch
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
# 定义网络层
self.layer1 = nn.Linear(10, 20)
self.relu = nn.ReLU()
self.layer2 = nn.Linear(20, 1)
def forward(self, x):
# 定义前向传播过程
out = self.layer1(x)
out = self.relu(out)
out = self.layer2(out)
return out
2. 初始化模型
model = MyModel()
3. 模型的使用
-
前向传播:
output = model(input_data)
-
获取模型参数:
for name, param in model.named_parameters(): print(name, param.size())
四、nn.Module
的关键特性
1. 自动注册子模块和参数
在 __init__
方法中,当你将 nn.Module
的实例(如 nn.Linear
、nn.Conv2d
等)赋值给模型的属性时,nn.Module
会自动将这些子模块注册到模型中。这意味着:
- 参数管理:模型的所有参数都会被自动收集,存储在
model.parameters()
中。 - 子模块管理:可以通过
model.children()
或model.modules()
访问子模块。
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.fc = nn.Linear(10, 5)
self.conv = nn.Conv2d(3, 16, kernel_size=3)
model = MyModule()
print(list(model.parameters())) # 自动包含了 fc 和 conv 的参数
2. forward
方法
forward
方法定义了模型的前向传播逻辑。在调用模型实例时,会自动调用 forward
方法。
output = model(input_data) # 等价于 output = model.forward(input_data)
3. 不需要定义反向传播
在大多数情况下,不需要手动实现反向传播函数。PyTorch 的自动求导机制(autograd)会根据前向传播中的操作,自动计算梯度。
五、常用的内置模块
PyTorch 提供了大量的内置模块,继承自 nn.Module
,可以直接使用:
- 线性层:
nn.Linear
- 卷积层:
nn.Conv1d
、nn.Conv2d
、nn.Conv3d
- 循环神经网络:
nn.RNN
、nn.LSTM
、nn.GRU
- 归一化层:
nn.BatchNorm1d
、nn.BatchNorm2d
- 激活函数:
nn.ReLU
、nn.Sigmoid
、nn.Softmax
- 损失函数:
nn.MSELoss
、nn.CrossEntropyLoss
六、示例:创建一个简单的神经网络
1. 问题描述
创建一个多层感知机(MLP),用于对 MNIST 手写数字进行分类。
2. 模型定义
class MNISTClassifier(nn.Module):
def __init__(self):
super(MNISTClassifier, self).__init__()
self.flatten = nn.Flatten() # 将输入展开为一维
self.fc1 = nn.Linear(28 * 28, 128)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(128, 64)
self.relu2 = nn.ReLU()
self.fc3 = nn.Linear(64, 10) # 输出10个类别的分数
def forward(self, x):
x = self.flatten(x)
x = self.relu(self.fc1(x))
x = self.relu2(self.fc2(x))
x = self.fc3(x)
return x
3. 训练过程
import torch.optim as optim
# 初始化模型、损失函数和优化器
model = MNISTClassifier()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 假设有数据加载器 data_loader
for epoch in range(num_epochs):
for images, labels in data_loader:
# 前向传播
outputs = model(images)
loss = criterion(outputs, labels)
# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
七、深入理解 nn.Module
的一些重要概念
1. 参数访问
parameters()
:返回一个生成器,包含模型所有可训练的参数。named_parameters()
:返回一个生成器,生成(name, parameter)
对,方便查看参数名称和形状。
for name, param in model.named_parameters():
print(f'Parameter {name}: shape {param.shape}')
2. 模块访问
children()
:返回直接子模块的迭代器。modules()
:返回自身及所有子模块的迭代器。
for child in model.children():
print(child)
for module in model.modules():
print(module)
3. 保存和加载模型
-
保存模型状态:
torch.save(model.state_dict(), 'model.pth')
-
加载模型状态:
model = MNISTClassifier() model.load_state_dict(torch.load('model.pth'))
4. 自定义层和模块
通过继承 nn.Module
,可以创建自定义的层或模块。
class CustomLayer(nn.Module):
def __init__(self, in_features, out_features):
super(CustomLayer, self).__init__()
self.weight = nn.Parameter(torch.randn(in_features, out_features))
self.bias = nn.Parameter(torch.zeros(out_features))
def forward(self, x):
return torch.matmul(x, self.weight) + self.bias
八、nn.Module
的实践技巧
1. 使用 Sequential
快速构建模型
对于简单的模型,可以使用 nn.Sequential
将多个层按顺序组合。
model = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 10)
)
2. 模型的嵌套
可以将模块嵌套使用,构建复杂的网络结构。
class ComplexModel(nn.Module):
def __init__(self):
super(ComplexModel, self).__init__()
self.block1 = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3),
nn.ReLU()
)
self.block2 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=3),
nn.ReLU()
)
self.fc = nn.Linear(64 * 24 * 24, 10)
def forward(self, x):
x = self.block1(x)
x = self.block2(x)
x = x.view(x.size(0), -1) # 展平
x = self.fc(x)
return x
九、总结
nn.Module
是 PyTorch 构建神经网络的基础,提供了参数管理、子模块管理和前向传播等功能。- 通过继承
nn.Module
,可以方便地创建自定义模型或层,满足各种复杂的需求。 - 在使用
nn.Module
时,注意正确地定义__init__
和forward
方法,并确保在forward
方法中定义前向计算逻辑。 - PyTorch 提供了大量的内置模块,可以直接使用或作为自定义模块的基石。
- 善于利用
nn.Module
的特性和工具,可以大大提高模型开发的效率和代码的可读性。
十、参考示例:完整的训练脚本
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
# 定义超参数
batch_size = 64
learning_rate = 0.01
num_epochs = 5
# 数据集和数据加载器
train_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
# 定义模型
class MNISTClassifier(nn.Module):
def __init__(self):
super(MNISTClassifier, self).__init__()
self.flatten = nn.Flatten()
self.fc1 = nn.Linear(28 * 28, 128)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(128, 64)
self.relu2 = nn.ReLU()
self.fc3 = nn.Linear(64, 10)
def forward(self, x):
x = self.flatten(x)
x = self.relu(self.fc1(x))
x = self.relu2(self.fc2(x))
x = self.fc3(x)
return x
# 初始化模型、损失函数和优化器
model = MNISTClassifier()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate)
# 训练模型
for epoch in range(num_epochs):
for images, labels in train_loader:
# 前向传播
outputs = model(images)
loss = criterion(outputs, labels)
# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
# 保存模型
torch.save(model.state_dict(), 'mnist_classifier.pth')