文 |AI_study
原标题:CNN Training Loop Explained - Neural Network Code Project
- 准备数据
- 建立模型
- 训练模型
- 建立训练 loop
- 分析模型的结果
单个 batch 进行训练
我们可以将单个 batch 训练的代码总结如下:
代码语言:javascript复制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())
输出
代码语言:javascript复制loss1: 2.3034827709198
loss2: 2.2825052738189697
您会注意到的一件事是,每次运行这段代码都会得到不同的结果。这是因为模型每次都是在顶部创建的,我们从以前的文章中知道模型的权重是随机初始化的。
现在让我们看看如何修改这段代码来使用所有的batch,从而使用整个训练集进行训练。
所有 batch的训练 (epoch)
现在,为了训练我们的数据加载器中可用的所有批次,我们需要做一些更改并添加额外的一行代码:
代码语言:javascript复制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循环来迭代所有batch 处理,而不是从数据加载器获取单个batch 处理。
因为我们的训练集中有60,000个样本,所以我们将有60,000 / 100 = 600次迭代。由于这个原因,我们将从循环中删除print语句,并跟踪总损失和最后打印它们的正确预测总数。
关于这600次迭代需要注意的一点是,到循环结束时,我们的权重将更新600次。如果我们提高batch_size这个数字会下降如果我们降低batch_size这个数字会上升。
最后,在我们对loss张量调用backward() 方法之后,我们知道梯度将被计算出来并添加到网络参数的grad属性中。因为这个原因,我们需要把这些梯度归零。我们可以使用优化器附带的zero_grad()方法来实现这一点。
我们已经准备好运行这段代码。这一次代码将花费更长的时间,因为循环将处理600个批。
代码语言:javascript复制epoch: 0 total_correct: 42104 loss: 476.6809593439102
我们得到了结果,我们可以看到60000中正确的总数是42104。
代码语言:javascript复制> total_correct / len(train_set)
0.7017333333333333
在只有一个epoch(一次完整的数据传递)之后,这已经很好了。即使我们做了一个epoch,我们仍然需要记住,权重被更新了600次,这取决于我们的批大小。如果让batch_batch的大小更大一些,比如10,000,那么权重只会更新 6 次,结果也不会很好。
多个 epoch的 训练
要执行多个epoch,我们所要做的就是将此代码放入for循环中。我们还将把epoch数添加到print语句中。
代码语言:javascript复制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的结果:
代码语言:javascript复制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
我们可以看到正确值的数量增加了,而loss减少了。
完整的训练 loop
将所有这些放在一起,我们可以将网络、优化器和train_loader从训练循环单元中提取出来。
代码语言:javascript复制network = Network()
optimizer = optim.Adam(network.parameters(), lr=0.01)
train_loader = torch.utils.data.DataLoader(
train_set
,batch_size=100
,shuffle=True
)
optimizer = optim.Adam(network.parameters(), lr=0.01)
代码语言:javascript复制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
)
接下来是可视化结果
我们现在应该很好地理解了训练循环以及如何使用PyTorch来构建它们。PyTorch很酷的一点是,我们可以像调试forward()函数那样调试训练循环代码。
在下一篇文章中,我们将看到如何获得训练集中每个样本的预测,并使用这些预测创建一个混淆矩阵。下节课见!
文章中内容都是经过仔细研究的,本人水平有限,翻译无法做到完美,但是真的是费了很大功夫,希望小伙伴能动动你性感的小手,分享朋友圈或点个“在看”,支持一下我 ^_^
英文原文链接是:
https://deeplizard.com/learn/video/XfYmia3q2Ow