PyTorch - 26 - CNN训练循环说明 - 神经网络代码项目
Training With A Single Batch
在上一集中,我们了解到训练过程是一个迭代过程,并且为了训练神经网络,我们建立了所谓的训练循环。
- 准备数据
- 建立模型
- 训练模型
a. 建立训练循环 - 分析模型的结果
我们可以通过以下方式总结用于单批训练的代码:
network = Network()
train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
optimizer = optim.Adam(network.parameters(), lr=0.01)
batch = next(iter(train_loader)) # Get Batch
images, labels = batch
preds = network(images) # Pass Batch
loss = F.cross_entropy(preds, labels) # Calculate Loss
loss.backward() # Calculate Gradients
optimizer.step() # Update Weights
print('loss1:', loss.item())
preds = network(images)
loss = F.cross_entropy(preds, labels)
print('loss2:', loss.item())
输出:
loss1: 2.3034827709198
loss2: 2.2825052738189697
您会注意到的一件事是,每次运行此代码时,我们都会得到不同的结果。 这是因为每次都在顶部创建模型,并且从以前的帖子中我们知道,模型权重是随机初始化的。
现在让我们看看如何修改此代码以使用所有批次以及整个训练集进行训练。
Training With All Batches (Single Epoch)
现在,要训练数据加载器中所有可用的批次,我们需要进行一些更改并添加一行代码:
network = Network()
train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
optimizer = optim.Adam(network.parameters(), lr=0.01)
total_loss = 0
total_correct = 0
for batch in train_loader: # Get Batch
images, labels = batch
preds = network(images) # Pass Batch
loss = F.cross_entropy(preds, labels) # Calculate Loss
optimizer.zero_grad()
loss.backward() # Calculate Gradients
optimizer.step() # Update Weights
total_loss += loss.item()
total_correct += get_num_correct(preds, labels)
print(
"epoch:", 0,
"total_correct:", total_correct,
"loss:", total_loss
)
我们不会从数据加载器中获取单个批处理,而是创建一个for循环,该循环将遍历所有批处理。
由于我们的训练集中有60,000个样本,因此我们将有60,000 / 100 = 600次迭代。因此,我们将从循环内删除打印语句,并跟踪总损失和最后打印它们的正确预测的总数。
关于这600次迭代的注意事项是,到循环结束时,我们的权重将更新600次。如果增加batch_size,则该数字将减小;如果降低batch_size,则该数字将增大。
最后,在损耗张量上调用向后()方法后,我们知道将计算梯度并将其添加到网络参数的grad属性中。因此,我们需要将这些梯度归零。我们可以使用优化器随附的名为zero_grad()的方法来执行此操作。
我们准备运行此代码。这次代码将花费更长的时间,因为循环正在处理600个批次。
epoch: 0 total_correct: 42104 loss: 476.6809593439102
我们得到了结果,可以看到正确的总数为60,000,其中总数为42,104。
> total_correct / len(train_set)
0.7017333333333333
只需一个纪元(对数据进行一次完整传递),就可以了。即使我们做了一个纪元,我们仍然要记住,砝码已更新了600次,这取决于我们的批次大小。如果使我们的batch_batch大小更大,例如10,000,则权重将仅更新6次,结果将不尽人意。
Training With Multiple Epochs
要执行多个时期,我们要做的就是将这段代码放入for循环中。 我们还将纪元号添加到print语句中。
network = Network()
train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
optimizer = optim.Adam(network.parameters(), lr=0.01)
for epoch in range(10):
total_loss = 0
total_correct = 0
for batch in train_loader: # Get Batch
images, labels = batch
preds = network(images) # Pass Batch
loss = F.cross_entropy(preds, labels) # Calculate Loss
optimizer.zero_grad()
loss.backward() # Calculate Gradients
optimizer.step() # Update Weights
total_loss += loss.item()
total_correct += get_num_correct(preds, labels)
print(
"epoch", epoch,
"total_correct:", total_correct,
"loss:", total_loss
)
运行此代码后,我们将获得每个时期的结果:
epoch 0 total_correct: 43301 loss: 447.59147948026657
epoch 1 total_correct: 49565 loss: 284.43429669737816
epoch 2 total_correct: 51063 loss: 244.08825492858887
epoch 3 total_correct: 51955 loss: 220.5841210782528
epoch 4 total_correct: 52551 loss: 204.73878084123135
epoch 5 total_correct: 52914 loss: 193.1240530461073
epoch 6 total_correct: 53195 loss: 184.50964668393135
epoch 7 total_correct: 53445 loss: 177.78808392584324
epoch 8 total_correct: 53629 loss: 171.81662507355213
epoch 9 total_correct: 53819 loss: 166.2412590533495
我们可以看到正确值的数量增加而损失减少。
Complete Training Loop
综合所有这些,我们可以将网络,优化器和train_loader从训练循环单元中拉出来。
network = Network()
optimizer = optim.Adam(network.parameters(), lr=0.01)
train_loader = torch.utils.data.DataLoader(
train_set
,batch_size=100
,shuffle=True
)
这样一来,我们可以在不重置网络权重的情况下运行训练循环。
for epoch in range(10):
total_loss = 0
total_correct = 0
for batch in train_loader: # Get Batch
images, labels = batch
preds = network(images) # Pass Batch
loss = F.cross_entropy(preds, labels) # Calculate Loss
optimizer.zero_grad()
loss.backward() # Calculate Gradients
optimizer.step() # Update Weights
total_loss += loss.item()
total_correct += get_num_correct(preds, labels)
print(
"epoch", epoch,
"total_correct:", total_correct,
"loss:", total_loss
)
Visualizing The Results Is Next
现在,我们应该对训练循环以及如何使用PyTorch构建循环有了很好的了解。关于PyTorch的很酷的事情是,我们可以像使用forward()函数一样调试训练循环代码。
在下一个步骤中,我们将看到如何获取训练集中每个样本的预测,并使用这些预测创建混淆矩阵。下一个见!