一、torch.nn
概述与设计哲学
torch.nn
是 PyTorch 提供的一个模块化工具集,专为构建和训练神经网络设计。其核心设计理念包括:
模块化:通过 nn.Module
基类,用户可以像搭积木一样组合各种层、激活函数和损失函数,构建复杂模型。
动态计算图:PyTorch 的动态计算图(eager execution)允许在运行时定义和修改网络结构,适合研究和快速原型开发。
灵活性与控制力:用户可以轻松自定义层、损失函数或前向传播逻辑,同时保留对底层张量操作的访问权限。
易用性:预定义的层和工具(如卷积、BatchNorm、优化器)简化了开发流程,适合初学者和专家。
torch.nn
的核心组件包括:
层(Layers):如 nn.Linear
、nn.Conv2d
等。
激活函数:如 nn.ReLU
、nn.Softmax
等。
损失函数:如 nn.MSELoss
、nn.CrossEntropyLoss
等。
容器:如 nn.Sequential
、nn.ModuleList
等。
正则化工具:如 nn.Dropout
、nn.BatchNorm2d
等。
接下来,将逐一深入讲解这些组件,辅以数学公式、代码示例和实际应用。
二、nn.Module
:神经网络的核心基类
1. 原理与功能
nn.Module
是所有神经网络模块的基类,无论是简单的全连接层还是复杂的 Transformer 模型,都继承自它。其核心功能包括:
参数管理:自动跟踪模型中的 torch.nn.Parameter
(如权重和偏置),并通过 parameters()
或 named_parameters()
方法访问。
层次结构:支持嵌套模块,允许构建复杂的网络结构。
前向传播:通过定义 forward
方法实现数据流。
设备管理:通过 .to(device)
将模型和参数移动到指定设备(如 GPU)。
训练/评估模式:通过 .train()
和 .eval()
切换模式,影响 Dropout 和 BatchNorm 的行为。
数学背景:
一个神经网络层通常表示为 y = f ( W x + b ) y = f(Wx + b) y=f(Wx+b),其中 W W W 和 b b b 是可学习的参数, f f f 是激活函数。
nn.Module
负责管理 W W W 和 b b b,并在反向传播时计算梯度 ∂ L ∂ W frac{partial L}{partial W} ∂W∂L 和 ∂ L ∂ b frac{partial L}{partial b} ∂b∂L。
2. 实现细节
当定义一个继承 nn.Module
的类时,PyTorch 会:
自动注册所有子模块(如 nn.Linear
)和参数(如 nn.Parameter
)。
在调用 model.parameters()
时,递归收集所有可学习的参数。
在调用 model(x)
时,自动执行 forward
方法。
代码示例:实现一个简单的两层神经网络
import torch
import torch.nn as nn
class TwoLayerNet(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(TwoLayerNet, self).__init__()
self.layer1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.layer2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = self.layer1(x)
x = self.relu(x)
x = self.layer2(x)
return x
# 实例化模型
model = TwoLayerNet(input_size=10, hidden_size=20, output_size=2)
x = torch.randn(32, 10) # 批次大小32,输入10维
output = model(x) # 输出形状为 (32, 2)
print(model)
输出:
TwoLayerNet(
(layer1): Linear(in_features=10, out_features=20, bias=True)
(relu): ReLU()
(layer2): Linear(in_features=20, out_features=2, bias=True)
)
3. 参数管理
nn.Module
自动管理参数。例如,nn.Linear
的权重和偏置是 nn.Parameter
类型的张量,PyTorch 会跟踪它们并在优化时更新。
查看参数:
for name, param in model.named_parameters():
print(f"Parameter: {
name}, Shape: {
param.shape}")
输出:
Parameter: layer1.weight, Shape: torch.Size([20, 10])
Parameter: layer1.bias, Shape: torch.Size([20])
Parameter: layer2.weight, Shape: torch.Size([2, 20])
Parameter: layer2.bias, Shape: torch.Size([2])
4. 自定义模块
通过继承 nn.Module
,可以实现自定义逻辑。例如,添加一个残差连接:
class ResidualBlock(nn.Module):
def __init__(self, dim):
super(ResidualBlock, self).__init__()
self.fc1 = nn.Linear(dim, dim)
self.fc2 = nn.Linear(dim, dim)
self.relu = nn.ReLU()
def forward(self, x):
residual = x
out = self.fc1(x)
out = self.relu(out)
out = self.fc2(out)
out += residual # 残差连接
return out
三、常用神经网络层
以下是 torch.nn
中常见的层,包含数学原理、参数说明、代码示例和应用场景。
1. 全连接层:nn.Linear
数学原理:
实现线性变换: y = W x + b y = Wx + b y=Wx+b
W ∈ R o u t _ f e a t u r e s × i n _ f e a t u r e s W in mathbb{R}^{out\_features imes in\_features} W∈Rout_features×in_features, b ∈ R o u t _ f e a t u r e s b in mathbb{R}^{out\_features} b∈Rout_features
输入 x ∈ R b a t c h _ s i z e × i n _ f e a t u r e s x in mathbb{R}^{batch\_size imes in\_features} x∈Rbatch_size×in_features,输出 y ∈ R b a t c h _ s i z e × o u t _ f e a t u r e s y in mathbb{R}^{batch\_size imes out\_features} y∈Rbatch_size×out_features
参数:
in_features
:输入维度。
out_features
:输出维度。
bias
:是否包含偏置(默认 True)。
代码示例:
linear = nn.Linear(10, 5)
x = torch.randn(32, 10) # 批次大小32
y = linear(x) # 输出形状 (32, 5)
print(y.shape)
应用场景:
多层感知机(MLP)的核心层。
分类任务的最后一层(如 logits 输出)。
注意事项:
输入张量的最后一维必须匹配 in_features
。
权重和偏置会自动初始化(通常为均匀分布或 Kaiming 初始化)。
2. 卷积层:nn.Conv2d
数学原理:
对输入特征图进行二维卷积操作:
y [ i , j ] = ∑ c = 0 C − 1 ∑ m = 0 K h − 1 ∑ n = 0 K w − 1 x [ c , i + m , j + n ] ⋅ w [ c , m , n ] + b y[i,j] = sum_{c=0}^{C-1} sum_{m=0}^{K_h-1} sum_{n=0}^{K_w-1} x[c, i+m, j+n] cdot w[c, m, n] + b y[i,j]=∑c=0C−1∑m=0Kh−1∑n=0Kw−1x[c,i+m,j+n]⋅w[c,m,n]+b
C C C:输入通道数, K h , K w K_h, K_w Kh,Kw:卷积核高度和宽度。
参数:
in_channels
:输入通道数。
out_channels
:输出通道数。
kernel_size
:卷积核大小(如 3 或 (3,3))。
stride
:步幅(默认 1)。
padding
:填充(默认 0)。
dilation
:膨胀系数(用于空洞卷积)。
代码示例:
conv = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1)
x = torch.randn(32, 3, 28, 28) # 批次大小32,3通道,28x28图像
y = conv(x) # 输出形状 (32, 16, 28, 28)
print(y.shape)
输出形状计算:
H o u t = ⌊ H i n + 2 ⋅ p a d d i n g − k e r n e l _ s i z e s t r i d e ⌋ + 1 H_{out} = leftlfloor frac{H_{in} + 2 cdot padding – kernel\_size}{stride}
ight
floor + 1 Hout=⌊strideHin+2⋅padding−kernel_size⌋+1
对于上述示例, H o u t = ⌊ 28 + 2 ⋅ 1 − 3 1 ⌋ + 1 = 28 H_{out} = lfloor frac{28 + 2 cdot 1 – 3}{1}
floor + 1 = 28 Hout=⌊128+2⋅1−3⌋+1=28。
应用场景:
图像分类(CNN,如 ResNet)。
目标检测(YOLO)、图像分割(U-Net)。
注意事项:
输入形状为 (batch_size, in_channels, height, width)
。
确保输入通道数与 in_channels
匹配。
3. 池化层:nn.MaxPool2d
, nn.AvgPool2d
数学原理:
最大池化:取窗口内的最大值。
平均池化:取窗口内的平均值。
输出尺寸计算与卷积类似。
参数:
kernel_size
:池化窗口大小。
stride
:步幅(默认等于 kernel_size
)。
padding
:填充(默认 0)。
代码示例:
pool = nn.MaxPool2d(kernel_size=2, stride=2)
x = torch.randn(32, 16, 28, 28)
y = pool(x) # 输出形状 (32, 16, 14, 14)
print(y.shape)
应用场景:
降低特征图分辨率,减少计算量。
增强特征的平移不变性。
4. 循环神经网络层:nn.RNN
, nn.LSTM
, nn.GRU
数学原理(以 RNN 为例):
对于时间步 t t t,隐藏状态更新:
h t = tanh ( W i h x t + W h h h t − 1 + b ) h_t = anh(W_{ih}x_t + W_{hh}h_{t-1} + b) ht=tanh(Wihxt+Whhht−1+b)
LSTM 和 GRU 引入门机制(如遗忘门、输入门)以解决长依赖问题。
参数:
input_size
:输入特征维度。
hidden_size
:隐藏状态维度。
num_layers
:层数。
batch_first
:是否将批次维度放在第一维(默认 False)。
代码示例:
rnn = nn.RNN(input_size=10, hidden_size=20, num_layers=2, batch_first=True)
x = torch.randn(32, 5, 10) # 批次大小32,序列长度5,特征维度10
h0 = torch.randn(2, 32, 20) # 初始隐藏状态
output, hn = rnn(x, h0) # output: (32, 5, 20), hn: (2, 32, 20)
print(output.shape, hn.shape)
应用场景:
自然语言处理(文本分类、机器翻译)。
时间序列预测。
注意事项:
输入形状为 (seq_len, batch_size, input_size)
或 (batch_size, seq_len, input_size)
(若 batch_first=True
)。
初始化隐藏状态 h 0 h_0 h0 的形状必须正确。
5. 正则化层:nn.BatchNorm2d
, nn.Dropout
(1)nn.BatchNorm2d
数学原理:
对每个通道的特征进行归一化:
y = x − μ σ 2 + ϵ ⋅ γ + β y = frac{x – mu}{sqrt{sigma^2 + epsilon}} cdot gamma + eta y=σ2+ϵ
x−μ⋅γ+β
μ , σ 2 mu, sigma^2 μ,σ2:批次均值和方差, γ , β gamma, eta γ,β:可学习参数。
参数:
num_features
:输入通道数。
eps
:防止除零的小值(默认 1e-5)。
momentum
:用于更新运行均值和方差。
代码示例:
bn = nn.BatchNorm2d(16)
x = torch.randn(32, 16, 28, 28)
y = bn(x)
应用场景:
加速训练,稳定梯度。
常用于深层 CNN。
(2)nn.Dropout
数学原理:
在训练时,以概率 p p p 随机将输入置零:
y = x ⋅ Bernoulli ( 1 − p ) 1 − p y = frac{x cdot ext{Bernoulli}(1-p)}{1-p} y=1−px⋅Bernoulli(1−p)
测试时不应用 Dropout。
参数:
p
:丢弃概率(默认 0.5)。
代码示例:
dropout = nn.Dropout(p=0.5)
x = torch.randn(32, 10)
y = dropout(x)
应用场景:
防止过拟合。
常用于全连接层或深层网络。
四、激活函数
激活函数为神经网络引入非线性,torch.nn
提供了多种激活函数:
ReLU: f ( x ) = max ( 0 , x ) f(x) = max(0, x) f(x)=max(0,x)
nn.ReLU()
优点:简单、计算快,缓解梯度消失。
缺点:可能导致“神经元死亡”(负值区域梯度为 0)。
变体:nn.LeakyReLU
, nn.PReLU
。
Sigmoid: f ( x ) = 1 1 + e − x f(x) = frac{1}{1 + e^{-x}} f(x)=1+e−x1
nn.Sigmoid()
输出范围 (0, 1),适合二分类。
缺点:梯度消失,输出非零中心。
Tanh: f ( x ) = tanh ( x ) f(x) = anh(x) f(x)=tanh(x)
输出范围 (-1, 1),零中心化。
常用于 RNN 的隐藏状态。
Softmax: f ( x i ) = e x i ∑ j e x j f(x_i) = frac{e^{x_i}}{sum_j e^{x_j}} f(xi)=∑jexjexi
nn.Softmax(dim=-1)
用于多分类,输出概率分布。
通常与 nn.CrossEntropyLoss
配合使用(后者内部包含 Softmax)。
为什么需要 dim:
在 PyTorch 中,输入张量通常是多维的(例如,批次数据 [batch_size, num_classes] 或更高维张量)。
dim 参数指定了 Softmax 归一化的维度。例如:
如果 dim=1,Softmax 会在张量的第二个维度(通常是类别维度)上计算概率分布。
如果 dim=0,Softmax 会在第一个维度(例如批次维度)上计算,但这在分类任务中较少见。
不指定 dim 会导致 PyTorch 无法确定归一化的维度,尤其在输入张量维度大于 1 时。
特别说明:如果 dim=-1
含义:设置 dim=-1 告诉 PyTorch 在张量的最后一个维度上执行 Softmax 归一化。-1 是 Python 中常用的索引方式,表示倒数第一个维度。
为什么常用 dim=-1:
语义匹配:在许多深度学习任务中,最后一个维度通常是需要归一化的维度,例如:
分类任务的 logits:[batch_size, num_classes],最后一个维度是 num_classes。
Transformer 注意力分数:[batch_size, num_heads, seq_len, seq_len],最后一个维度是注意力分数的归一化维度。
通用性:dim=-1 使代码对张量维度的数量更鲁棒。例如,无论是 2D 张量 [batch_size, num_classes] 还是 3D 张量 [batch_size, channels, num_classes],dim=-1 始终作用于最后一个维度(通常是类别维度)。
社区惯例:PyTorch 生态(例如 torchvision、Hugging Face 的 Transformer 模型)常使用 dim=-1,因为它直观且适用于大多数分类和概率归一化任务。
代码示例:
relu = nn.ReLU()
sigmoid = nn.Sigmoid()
x = torch.tensor([-1.0, 0.0, 1.0])
print(relu(x)) # tensor([0.0, 0.0, 1.0])
print(sigmoid(x)) # tensor([0.2689, 0.5000, 0.7311])
五、损失函数
损失函数衡量模型预测与真实标签的差距,torch.nn
提供多种损失函数:
均方误差:nn.MSELoss
L = 1 N ∑ ( y − y ^ ) 2 L = frac{1}{N} sum (y – hat{y})^2 L=N1∑(y−y^)2
适用于回归任务。
交叉熵损失:nn.CrossEntropyLoss
结合 LogSoftmax 和负对数似然:
L = − ∑ i = 1 C y i log ( y ^ i ) L = -sum_{i=1}^C y_i log(hat{y}_i) L=−∑i=1Cyilog(y^i)
适用于多分类任务,输入为 logits(不需要显式 Softmax)。
为什么不需要显式 Softmax?
nn.CrossEntropyLoss
内部集成了 Softmax 和负对数似然(NLL)损失的计算。输入的 logits(未归一化的原始分数)会先经过 Softmax 函数转换为概率分布,再计算负对数似然损失。这种设计提高了数值稳定性和计算效率。
具体来说,Softmax 函数将 logits 转换为概率:
y ^ i = exp ( z i ) ∑ j = 1 C exp ( z j ) hat{y}_i = frac{exp(z_i)}{sum_{j=1}^C exp(z_j)} y^i=∑j=1Cexp(zj)exp(zi)
其中 z i z_i zi 是第 i i i 类的 logit。
随后,负对数似然损失取目标类的对数概率的负值。如果直接在模型输出后手动应用 Softmax,会导致重复计算,且可能引入数值不稳定问题(例如,指数运算可能导致溢出)。因此,nn.CrossEntropyLoss
要求输入未经 Softmax 的 logits,由其内部完成归一化和损失计算。
这种方式还避免了在反向传播中重复计算 Softmax 的梯度,优化了计算图的效率。
二元交叉熵:nn.BCELoss
, nn.BCEWithLogitsLoss
适用于二分类任务,nn.BCEWithLogitsLoss
结合 Sigmoid。
代码示例:
criterion = nn.CrossEntropyLoss()
outputs = torch.randn(32, 10) # 批次大小32,10个类别
labels = torch.randint(0, 10, (32,))
loss = criterion(outputs, labels)
print(loss.item())
注意事项:
确保输入和标签的形状匹配。
对于分类任务,标签通常是整数(nn.CrossEntropyLoss
)或浮点数(nn.BCELoss
)。
六、容器
torch.nn
提供几种容器,用于组织网络结构:
nn.Sequential:
按顺序堆叠层,前向传播自动按序执行。
适合简单的线性网络。
代码示例:
model = nn.Sequential(
nn.Linear(10, 20),
nn.ReLU(),
nn.Linear(20, 2)
)
x = torch.randn(32, 10)
y = model(x) # 输出形状 (32, 2)
nn.ModuleList:
存储模块列表,适合动态或循环结构。
不会自动定义 forward
方法。
代码示例:
class MyNet(nn.Module):
def __init__(self, dims):
super(MyNet, self).__init__()
self.layers = nn.ModuleList([nn.Linear(dims[i], dims[i+1]) for i in range(len(dims)-1)])
self.relu = nn.ReLU()
def forward(self, x):
for layer in self.layers:
x = self.relu(layer(x))
return x
model = MyNet([10, 20, 5])
nn.ModuleDict:
存储模块字典,适合按名称访问。
代码示例:
class MyNet(nn.Module):
def __init__(self):
super(MyNet, self).__init__()
self.layers = nn.ModuleDict({
'fc1': nn.Linear(10, 20),
'fc2': nn.Linear(20, 5)
})
def forward(self, x):
x = self.layers['fc1'](x)
x = self.layers['fc2'](x)
return x
七、构建与训练神经网络的完整流程
以下是一个完整的示例,展示如何使用 torch.nn
构建、训练和评估一个 CNN,用于 MNIST 手写数字分类。
1. 准备数据
使用 torchvision
加载 MNIST 数据集。
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
# 数据预处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
# 加载数据集
train_dataset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
2. 定义模型
class ConvNet(nn.Module):
def __init__(self):
super(ConvNet, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.fc1 = nn.Linear(64 * 7 * 7, 128)
self.fc2 = nn.Linear(128, 10)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.5)
def forward(self, x):
x = self.pool(self.relu(self.conv1(x))) # 输出: (batch, 32, 14, 14)
x = self.pool(self.relu(self.conv2(x))) # 输出: (batch, 64, 7, 7)
x = x.view(-1, 64 * 7 * 7) # 展平
x = self.relu(self.fc1(x))
x = self.dropout(x)
x = self.fc2(x)
return x
model = ConvNet()
3. 设置损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
4. 训练模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
num_epochs = 5
for epoch in range(num_epochs):
model.train()
total_loss = 0
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
# 前向传播
outputs = model(images)
loss = criterion(outputs, labels)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch [{
epoch+1}/{
num_epochs}], Loss: {
total_loss/len(train_loader):.4f}")
5. 评估模型
model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"Test Accuracy: {
100 * correct / total:.2f}%")
预期结果:
训练 5 个 epoch 后,测试准确率通常可达 98% 以上。
八、进阶主题
1. 参数初始化
参数初始化对模型收敛至关重要。torch.nn.init
提供多种初始化方法:
Xavier 初始化(适合 Sigmoid/Tanh):
W ∼ Uniform ( − 6 n i n + n o u t , 6 n i n + n o u t ) W sim ext{Uniform}(-sqrt{frac{6}{n_{in} + n_{out}}}, sqrt{frac{6}{n_{in} + n_{out}}}) W∼Uniform(−nin+nout6
,nin+nout6
)
Kaiming 初始化(适合 ReLU):
W ∼ Normal ( 0 , 2 n i n ) W sim ext{Normal}(0, sqrt{frac{2}{n_{in}}}) W∼Normal(0,nin2
)
代码示例:
def init_weights(m):
if isinstance(m, nn.Linear) or isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.zeros_(m.bias)
model.apply(init_weights)
2. 自定义损失函数
通过继承 nn.Module
,可以定义自定义损失函数。例如,带 L2 正则化的损失:
class CustomLoss(nn.Module):
def __init__(self, l2_weight=0.01):
super(CustomLoss, self).__init__()
self.l2_weight = l2_weight
self.ce_loss = nn.CrossEntropyLoss()
def forward(self, outputs, labels, model):
ce = self.ce_loss(outputs, labels)
l2 = sum(p.pow(2.0).sum() for p in model.parameters())
return ce + self.l2_weight * l2
criterion = CustomLoss(l2_weight=0.01)
3. 动态网络结构
PyTorch 的动态计算图允许在 forward
中根据输入调整网络结构。例如,动态层数:
class DynamicNet(nn.Module):
def __init__(self, input_size, hidden_size):
super(DynamicNet, self).__init__()
self.fc = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
def forward(self, x, num_layers=1):
for _ in range(num_layers):
x = self.fc(x)
x = self.relu(x)
return x
4. 模型保存与加载
保存整个模型:
torch.save(model, "model.pt")
model = torch.load("model.pt")
仅保存参数(推荐):
torch.save(model.state_dict(), "model_state.pth")
model.load_state_dict(torch.load("model_state.pth"))
5. 调试技巧
检查形状:
print(x.shape) # 在 forward 中打印张量形状
检查梯度:
for name, param in model.named_parameters():
print(f"{
name}.grad: {
param.grad.norm()}")
模型结构:
使用 torchsummary
查看模型:
from torchsummary import summary
summary(model, input_size=(1, 28, 28)) # 对于 ConvNet
九、常见问题与解决方案
维度不匹配:
问题:RuntimeError: size mismatch
解决:检查每一层的输入输出形状,确保匹配。例如,nn.Linear
的输入维度必须与上一层输出一致。
梯度消失/爆炸:
解决:使用适当的初始化(如 Kaiming)、BatchNorm 或梯度裁剪:
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
过拟合:
解决:增加 Dropout、L2 正则化(optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
)或数据增强。
训练/评估模式混淆:
问题:Dropout 在测试时生效。
解决:确保测试时调用 model.eval()
,训练时调用 model.train()
。
十、学习建议与资源
实践项目:
实现经典模型:LeNet、VGG、ResNet。
参与 Kaggle 比赛:MNIST、CIFAR-10、NLP 任务。
使用 torchvision.models
加载预训练模型,尝试迁移学习。
阅读资料:
PyTorch 官方文档:https://pytorch.org/docs/stable/nn.html
《Deep Learning with PyTorch》:全面介绍 PyTorch 的书籍。
GitHub 上的 PyTorch 示例:https://github.com/pytorch/examples
调试工具:
torchinfo
:比 torchsummary
更强大的模型结构可视化工具。
TensorBoard:可视化损失和准确率:
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter()
writer.add_scalar("Loss/train", loss.item(), epoch)
社区与论坛:
PyTorch 论坛:https://discuss.pytorch.org/
十一、总结
torch.nn
是 PyTorch 构建神经网络的核心模块,提供了从基本层到复杂模型的全面支持。通过深入理解 nn.Module
的机制、掌握常用层(如 nn.Linear
、nn.Conv2d
)、激活函数、损失函数和容器,可以灵活构建各种深度学习模型。结合数学原理、代码实践和调试技巧,能够应对从简单 MLP 到复杂 CNN/RNN 的开发任务。
暂无评论内容