文章目录
- 一、基本概念
- 1、epoch
- 2、遍历DataLoader
- 二、神经网络训练过程代码详解
- 步骤一:选择并初始化优化器
- 步骤二:计算损失
- 步骤三:反向传播
- 步骤四:更新模型参数
- 步骤五:清空梯度
- 组合到训练循环中
一、基本概念
for epoch in range(total_epoch):for label_x,label_y in dataloader:pass
1、epoch
epoch
指的是整个数据集在训练过程中被完整地遍历一次。如果数据集被分成多个批次输入模型,则一个 epoch
完成后意味着所有的批次已被模型处理一次。epoch
的数目通常根据训练数据的大小、模型复杂度和任务需求来决定。每个 epoch
结束后,模型学到的知识会更加深入,但也存在过度学习(过拟合)的风险,特别是当 epoch
数目过多时。
即每一个epoch
会处理所有的batch
,epoch
也被称为训练周期。
2、遍历DataLoader
遍历DataLoader
,实际上就是每次取出一个batch
的数据。
二、神经网络训练过程代码详解
建议先理解:Module模块
步骤一:选择并初始化优化器
首先,根据模型的需求选择一个合适的优化器。不同的优化器可能适合不同类型的数据和网络架构。一旦选择了优化器,需要将模型的参数传递给它,并设置一些特定的参数,如学习率、权重衰减等。
import torch.optim as optim# 假设 model 是你的网络模型
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
在这个例子中,选择了随机梯度下降(SGD)作为优化器,并设置了学习率和动量。
步骤二:计算损失
在训练循环中,每次迭代都会处理一批数据,模型会根据这些数据进行预测,并计算损失。
criterion = torch.nn.CrossEntropyLoss() # 选择合适的损失函数
outputs = model(inputs) # 前向传播
loss = criterion(outputs, labels) # 计算损失
步骤三:反向传播
一旦有了损失,就可以使用 .backward()
方法来自动计算模型中所有可训练参数的梯度。
loss.backward()
这一步将计算损失函数相对于每个参数的梯度,并将它们存储在各个参数的 .grad
属性中。
步骤四:更新模型参数
使用优化器的 .step()
方法来根据计算得到的梯度更新参数。
optimizer.step()
这个调用会更新模型的参数,具体的更新方式取决于你选择的优化算法。
步骤五:清空梯度
在每次迭代后,需要手动清空梯度,以便下一次迭代。如果不清空梯度,梯度会累积,导致不正确的参数更新。
optimizer.zero_grad()
组合到训练循环中
将上述步骤组合到一个训练循环中,我们得到了完整的训练过程:
model = MyModel() #实例化神经网络层,调用继承自Module类的MyModel类的构造函数
criterion = torch.nn.CrossEntropyLoss() # 选择合适的损失函数,这里是交叉熵损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)# 定义优化器,传入模型参数
model.train()#切换至训练模式
for epoch in range(total_epochs):for inputs, labels in dataloader: # 从数据加载器获取数据inputs, labels = inputs.to(device), labels.to(device)# 前向传播outputs = model(inputs)# 计算损失loss = criterion(outputs, labels)# 反向传播和优化optimizer.zero_grad() # 清空之前的梯度loss.backward() # 反向传播# 优化参数optimizer.step() # 更新参数print(f'Epoch [{epoch+1}/{total_epochs}], Loss: {loss.item()}')
-
loss.item()
- 在 PyTorch 中,
loss
是一个torch.Tensor
对象。当计算模型的损失时,这个对象通常只包含一个元素(一个标量值),它代表了当前批次数据的损失值。loss.item()
方法是从包含单个元素的张量中提取出那个标量值作为 Python 数值。这是很有用的,因为它允许你将损失值脱离张量的形式进行进一步的处理或输出,比如打印、记录或做条件判断。
- 在 PyTorch 中,
-
print(f'Epoch [{epoch+1}/{total_epochs}], Loss: {loss.item()}')
- 这行代码是用来在训练过程中输出当前
epoch
的编号和该epoch
的损失值。这对于监控训练进程和调试模型非常有帮助。具体来说:epoch+1
:由于计数通常从 0 开始,所以+1
是为了更自然地显示(从 1 开始而不是从 0 开始)。{total_epochs}
:这是训练过程中总的epoch
数。{loss.item()}
:如前所述,这表示当前批次的损失值,作为一个标量数值输出。
- 这行代码是用来在训练过程中输出当前