PyTorch 教程-卷积神经网络模型的训练

在上一个主题中,我们实现了我们的CNN模型。现在,我们的下一个任务是对其进行训练。为了训练我们的CNN模型,我们将使用CUDA张量类型,它将执行与CPU张量相同的功能,但用于计算。
训练我们的CNN模型的步骤如下:
步骤1:
在训练部分的第一步中,我们将使用torch.device()来指定设备。我们将检查CUDA是否可用,如果可用,则使用CUDA,否则使用CPU。
device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
步骤2:
在接下来的步骤中,我们将将我们的模型分配给我们的设备:
model=LeNet.to(device)
步骤3:
现在,我们将定义我们的损失函数。损失函数的定义方式与我们在先前的深度神经网络模型中定义的方式相同。
criteron=nn.CrossEntropyLoss()
之后,我们将使用熟悉的优化器,即Adam:
optimizer=torch.optim.Adam(model.parameters(),lr=0.00001)
步骤4:
在接下来的步骤中,我们将指定epochs的数量。我们初始化epochs的数量,并在每个epoch处分析损失并绘制图表。我们将初始化两个列表,即loss_history和correct_history。
epoch=12
loss_history=[]
correct_history=[]
步骤5:
我们将从迭代每个epoch开始,对于每个epoch,我们必须迭代通过训练加载器提供给我们的每个单个训练批次。每个训练批次包含一百张图像以及一百个标签,如下所示:
for e in range(epochs):
for input, labels in training_loader:
步骤6:
我们正在处理卷积神经网络,其中输入首先被传递。我们将图像传递给四个维度,因此无需将其展平。
由于我们已经将模型分配给我们的设备,因此我们也将输入和标签分配给我们的设备。
input=input.to(device)
labels=labels.to(device)
现在,通过这些输入,我们得到输出:
outputs=model(inputs)
步骤7:
在接下来的步骤中,我们将执行与之前在图像识别中所做的优化算法相同的优化算法。
loss1=criteron(outputs,labels)
optimizer.zero_grad()
loss1.backward()
optimizer.step()
步骤8:
为了跟踪每个epoch的损失,我们将初始化一个变量loss,即running_loss。对于为每个批次计算的每个损失,我们必须将它们全部添加到每个单个批次的所有批次中,然后在每个epoch处计算整个数据集的最终损失。
loss+=loss1.item()
现在,我们将将整个epoch的累积损失附加到我们的损失列表中。为此,在循环语句之后,我们使用一个else语句。因此,一旦for循环结束,那么将调用else语句。在这个else语句中,我们将打印在特定epoch处计算的整个数据集的累积损失。
epoch_loss=loss/len(training_loader)
loss_history.append(epoch_loss)
步骤11:
在接下来的步骤中,我们将找到网络的准确性。我们将初始化correct变量并将其值设为零。我们将比较模型对每个训练图像进行的预测与图像的实际标签,以显示在一个epoch内有多少个图像被正确分类。
对于每个图像,我们将取得最大分数值。在这种情况下,将返回一个元组。它返回的第一个值是实际的最高值 - 模型对该批图像中的每个图像进行的最高分数。因此,我们对第一个元组值不感兴趣,而第二个值将对应于模型做出的顶部预测,我们将其称为preds。它将返回该图像的最大值的索引。
_,preds=torch.max(outputs,1)
步骤12:
每个图像输出将是一个值范围从0到9的索引集合,因此MNIST数据集包含从0到9的类。因此,最大值发生的位置对应于模型的预测。我们将比较模型对图像的实际标签所做的所有这些预测,以查看它们中有多少是正确的。
correct+=torch.sum(preds==labels.data)
这将为每个单个图像批次提供正确预测的数量。我们将以与epoch loss相同的方式定义epoch accuracy并打印epoch loss和accuracy:
epoch_acc=correct.float()/len(training_loader)
print('training_loss:{:.4f},{:.4f}'.format(epoch_loss,epoch_acc.item()))
这将给出如下预期结果:
步骤13:
现在,我们将将整个epoch的准确性附加到我们的correct_history列表中,并为更好的可视化,我们将绘制epoch loss和accuracy:
plt.plot(loss_history,label='Running Loss History')
plt.plot(correct_history,label='Running correct History')
完整代码:
import torch
import matplotlib.pyplot as plt
import numpy as np
import torch.nn.functional as func
import PIL.ImageOps
from torch import nn
from torchvision import datasets,transforms
device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
transform1=transforms.Compose([transforms.Resize((28,28)),transforms.ToTensor(),transforms.Normalize((0.5,),(0.5,))])
training_dataset=datasets.MNIST(root='./data',train=True,download=True,transform=transform1)
training_loader=torch.utils.data.DataLoader(dataset=training_dataset,batch_size=100,shuffle=True)
class LeNet(nn.Module):
def __init__(self):
super().__init__()
self.conv1=nn.Conv2d(1,20,5,1)
self.conv2=nn.Conv2d(20,50,5,1)
self.fully1=nn.Linear(4*4*50,500)
self.fully2=nn.Linear(500,10)
def forward(self,x):
x=func.relu(self.conv1(x))
x=func.max_pool2d(x,2,2)
x=func.relu(self.conv2(x))
x=func.max_pool2d(x,2,2)
x=x.view(-1,4*4*50) #Reshaping the output into desired shape
x=func.relu(self.fully1(x)) #Applying relu activation function to our first fully connected layer
x=self.fully2(x) #We will not apply activation function here because we are dealing with multiclass dataset
return x
model=LeNet().to(device)
criteron=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.00001)
epochs=12
loss_history=[]
correct_history=[]
for e in range(epochs):
loss=0.0
correct=0.0
for e in range(epochs):
loss=0.0
correct=0.0
for inputs,labels in training_loader:
inputs=inputs.to(device)
labels=labels.to(device)
outputs=model(inputs)
loss1=criteron(outputs,labels)
optimizer.zero_grad()
loss1.backward()
optimizer.step()
_,preds=torch.max(outputs,1)
loss+=loss1.item()
correct+=torch.sum(preds==labels.data)
else:
epoch_loss=loss/len(training_loader)
epoch_acc=correct.float()/len(training_loader)
loss_history.append(epoch_loss)
correct_history.append(epoch_acc)
print('training_loss:{:.4f},{:.4f}'.format(epoch_loss,epoch_acc.item()))
plt.plot(loss_history,label='Running Loss History')
plt.plot(correct_history,label='Running correct History')
plt.show()