13 定义优化器

13 定义优化器

在使用 PyTorch 进行模型训练时,选择和定义合适的优化器是模型优化的重要步骤。优化器主要用于更新模型的权重,以最小化损失函数。PyTorch 提供了多种优化器,比如 SGDAdamRMSprop 等。

1. 导入必要的库

在开始之前,确保你已经安装了 PyTorch,并且导入了必要的库。

1
2
3
import torch
import torch.nn as nn
import torch.optim as optim

2. 创建模型

首先,我们需要定义一个简单的神经网络模型。这里我们使用一个简单的全连接神经网络作为示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(10, 5) # 输入维度为10,输出维度为5
self.fc2 = nn.Linear(5, 1) # 输入维度为5,输出维度为1

def forward(self, x):
x = torch.relu(self.fc1(x)) # 使用 ReLU 激活函数
x = self.fc2(x)
return x

# 实例化模型
model = SimpleNN()

3. 定义损失函数

在训练神经网络之前,我们需要定义一个损失函数。损失函数用于评估模型的输出与真实标签之间的差距。

1
criterion = nn.MSELoss()  # 使用均方误差损失函数

4. 选择优化器

在 PyTorch 中,可以通过 optim 模块选择不同的优化器。这里我们展示如何定义常用的 SGD(随机梯度下降)和 Adam 优化器。

4.1 定义 SGD 优化器

1
optimizer = optim.SGD(model.parameters(), lr=0.01)  # lr 为学习率

4.2 定义 Adam 优化器

1
optimizer = optim.Adam(model.parameters(), lr=0.001)  # 使用 Adam 优化器

5. 训练模型

在训练过程中,我们需要循环调用 optimizer.step() 来更新模型的参数,同时使用 optimizer.zero_grad() 清除之前的梯度。

以下是一个简单的训练循环示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 假设我们有数据输入和目标输出
inputs = torch.randn(10) # 随机生成输入数据
target = torch.tensor([1.0]) # 假设目标值为 1

# 训练过程
for epoch in range(100): # 进行 100 次迭代
# 清除旧的梯度
optimizer.zero_grad()

# 前向传播
output = model(inputs)

# 计算损失
loss = criterion(output, target)

# 反向传播
loss.backward()

# 更新参数
optimizer.step()

# 输出损失
print(f'Epoch {epoch + 1}, Loss: {loss.item()}')

6. 小结

选择优化器对于模型训练的效果至关重要。PyTorch 中提供了多种优化器,你可以根据具体任务和数据集的特点选择合适的优化器。在实际应用中,通常需要尝试不同的优化器及其超参数(例如学习率 lr)来寻找最佳的配置。

通过此章节的学习,你应该理解了如何定义和使用 PyTorch 中的优化器,从而帮助模型进行有效的训练。

前向传播与反向传播

前向传播与反向传播

在这一节中,我们将详细讨论 前向传播反向传播 的概念,以及如何在 PyTorch 中实现它们。

1. 前向传播

1.1 前向传播的概念

前向传播 是指数据从输入层经过各个层的计算,最终生成输出的过程。在深度学习模型中,前向传播是通过将输入乘以权重、添加偏置并经过激活函数来计算输出的。

1.2 实现前向传播

设想我们有一个简单的神经网络,包含一个输入层和一个输出层。我们将使用 PyTorch 来实现这一过程。以下是实现前向传播的简单示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import torch
import torch.nn as nn

# 定义一个简单的神经网络
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.linear = nn.Linear(2, 1) # 输入层有2个节点,输出层有1个节点

def forward(self, x):
return self.linear(x) # 前向传播

# 创建模型实例
model = SimpleNN()

# 输入数据
input_data = torch.tensor([[1.0, 2.0]]) # 1个样本,2个特征

# 进行前向传播
output = model(input_data)
print(f'Output: {output.item()}')

在上面的代码中,我们定义了一个有两个输入特征和一个输出的简单神经网络,并进行了前向传播操作。

2. 反向传播

2.1 反向传播的概念

反向传播 是优化模型的关键过程,它通过计算损失函数相对于每个参数的梯度来更新模型的权重。通过反向传播,我们可以使用梯度下降方法来减少预测值和真实值之间的误差。

2.2 实现反向传播

以下是实现反向传播的步骤:

  1. 定义损失函数:选择一个损失函数来评估模型的输出。
  2. 计算梯度:使用 backward() 方法计算梯度。
  3. 更新权重:使用优化器(例如 SGD 或 Adam)来更新权重。

下面是实现反向传播的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 假设我们有一个目标值
target = torch.tensor([[1.0]]) # 真实目标

# 定义损失函数
criterion = nn.MSELoss()

# 计算损失
loss = criterion(output, target)
print(f'Loss: {loss.item()}')

# 反向传播
model.zero_grad() # 清空之前的梯度
loss.backward() # 计算梯度

# 更新权重
with torch.no_grad(): # 不追踪梯度
for param in model.parameters():
param -= 0.01 * param.grad # 使用简单的梯度下降更新规则

# 打印更新后的权重
print(f'Updated weights: {[param.data for param in model.parameters()]}')

在上面的代码中,我们计算了损失,并通过调用 loss.backward() 来执行反向传播。然后我们使用一个简单的梯度下降方法手动更新了模型的权重。

3. 小结

  • 前向传播 是网络计算输出的过程,而 反向传播 是通过计算梯度来优化网络参数的过程。
  • PyTorch 提供了简单而强大的方式来实现这两种过程,允许我们快速构建和训练深度学习模型。

通过理解和实现前向传播与反向传播,你将能够动态地构建复杂的神经网络,并应用于各种机器学习任务。

15 训练循环

15 训练循环

在使用 PyTorch 进行模型训练时,训练循环 是一个核心概念。它决定了如何通过多次迭代数据来优化模型参数。以下是一些关键步骤和细节,帮助你从零开始理解和实现训练循环。

1. 初始化模型和数据

在训练开始之前,我们需要定义模型、数据集和优化器。通常,这些操作在循环开始之前完成。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

# 定义模型
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.fc = nn.Linear(10, 1) # 输入尺寸为 10,输出尺寸为 1

def forward(self, x):
return self.fc(x)

# 创建数据集
X = torch.randn(100, 10) # 100 个样本,每个样本有 10 个特征
y = torch.randn(100, 1) # 100 个目标值
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=16, shuffle=True)

# 初始化模型、损失函数和优化器
model = SimpleNN()
criterion = nn.MSELoss() # 均方误差损失
optimizer = optim.SGD(model.parameters(), lr=0.01) # 随机梯度下降优化

2. 训练循环

基本结构

训练循环通常包括以下几个部分:

  1. 迭代数据批次
  2. 前向传播
  3. 计算损失值
  4. 反向传播
  5. 更新模型参数
  6. 记录和输出信息

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
num_epochs = 5  # 总共训练的周期(epoch)数

for epoch in range(num_epochs):
for batch_idx, (data, target) in enumerate(dataloader):

# ------- 1. 前向传播 -------
output = model(data) # 将输入数据传入模型

# ------- 2. 计算损失 -------
loss = criterion(output, target) # 计算损失值

# ------- 3. 清零梯度 -------
optimizer.zero_grad() # 清除之前的梯度

# ------- 4. 反向传播 -------
loss.backward() # 计算当前梯度

# ------- 5. 更新参数 -------
optimizer.step() # 更新模型参数

# ------- 6. 输出信息 -------
if batch_idx % 10 == 0: # 每 10 个批次输出一次信息
print(f'Epoch [{epoch + 1}/{num_epochs}], Step [{batch_idx + 1}/{len(dataloader)}], Loss: {loss.item():.4f}')

3. 注意事项

  • 清零梯度:每个训练循环开始前,使用 optimizer.zero_grad() 清空旧的梯度。否则累积的梯度会导致模型参数更新不准确。

  • 损失函数:选择合适的损失函数是关键,它会影响模型的训练效果。例如,分类问题通常使用交叉熵损失,而回归问题则使用均方误差损失。

  • 学习率:选择合适的学习率(如lr)可以显著影响训练速度和最终模型的性能。使用优化器的学习率调度器可以自动调整学习率。

4. 评估模型

在训练循环结束后,通常需要对模型进行评估(验证集或测试集)。这可以帮助我们了解模型的泛化能力。

示例代码

1
2
3
4
5
6
7
8
9
10
# 在验证集上评估模型
model.eval() # 设定模型为评估模式
with torch.no_grad(): # 不计算梯度
total_loss = 0
for val_data, val_target in val_dataloader: # val_dataloader 是你的验证集 DataLoader
val_output = model(val_data)
val_loss = criterion(val_output, val_target)
total_loss += val_loss.item()

print(f'Validation Loss: {total_loss / len(val_dataloader):.4f}')

通过理解和实现 训练循环,你可以在 PyTorch 中高效地训练神经网络模型。这些步骤和示例代码将帮助你在实践中应用这一重要概念。