📜  卷积神经网络模型的训练

📅  最后修改于: 2020-11-11 01:05:09             🧑  作者: Mango

卷积神经网络模型的训练

在最后一个主题中,我们实现了CNN模型。现在,我们的下一个任务是训练它。为了训练我们的CNN模型,我们将涉及CUDA张量类型,该类型将实现与CPU张量相同的函数,但它们可用于计算。

有以下步骤来训练我们的CNN模型:

步骤1:

在培训部分的第一步,我们将借助torch.device()指定设备。我们将检查CUDA;如果CUDA可用,那么我们使用Cuda,否则我们将使用CPU。

device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

第2步:

下一步,我们将模型分配给设备的方式为:

model=LeNet.to(device)

第三步:

现在,我们将定义损失函数。损失函数的定义方式与我们之前使用深度神经网络模型所定义的方式相同。

criteron=nn.CrossEntropyLoss()

之后,我们将使用熟悉的优化器,即Adam作为

optimizer=torch.optim.Adam(model.parameters(),lr=0.00001) 

第四步:

在下一步中,我们将指定时期数。我们初始化历元数,并使用绘图分析每个历元的损失。我们将初始化两个列表,即loss_history和正确的历史记录。

epoch=12
loss_history=[]
correct_history=[]

步骤5:

我们将从迭代每个纪元开始,对于每个纪元,我们都必须迭代由培训加载者提供给我们的每个培训批次。每个训练批次在训练加载器中的一列火车中包含一百张图像和一百个标签,如下所示:

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:

为了跟踪每个时期的损失,我们将初始化一个变量损失,即running_loss。对于按批次计算的每个损失,我们必须将每个批次的总数相加,然后在每个时期计算最终损失。

loss+=loss1.item()

现在,我们将整个时期的累积亏损添加到我们的亏损清单中。为此,我们在循环语句之后使用else语句。因此,一旦for循环完成,便会调用else语句。在这条else语句中,我们将print在该特定时期为整个数据集计算的累积损失。

epoch_loss=loss/len(training_loader)
loss_history.append(epoch_loss)  

步骤11:

在下一步中,我们将发现网络的准确性。我们将初始化正确的变量,并将值分配为零。我们将模型对每个训练图像的预测与图像的实际标签进行比较,以显示在一个时期内其中有多少是正确的。

对于每个图像,我们将采用最大得分值。在这种情况下,将返回一个元组。它返回的第一个值是实际的最高值-最大分数,该分数由模型针对这批图像中的每个单个图像得出。因此,我们对第一个元组值不感兴趣,而第二个将对应于该模型做出的顶级预测,我们称其为pred。它将返回该图像的最大值的索引。-

 _,preds=torch.max(outputs,1)

步骤12:

每个图像输出将是索引范围从0到9的值的集合,以使MNIST数据集包含从0到9的类。由此可以看出,出现最大值的预测对应于模型所做的预测。我们将模型所做的所有这些预测与图像的实际标签进行比较,以查看其中有多少是正确的。

correct+=torch.sum(preds==labels.data)

这将为每批图像给出正确的预测数量。我们将以与epoch loss相同的方式定义epoch的精度,并printepoch loss和Accuracy作为

epoch_acc=correct.float()/len(training_loader)  
print('training_loss:{:.4f},{:.4f}'.format(epoch_loss,epoch_acc.item()))

这将产生预期的结果:

步骤13:

现在,我们将整个时期的准确性附加到我们的correct_history列表中,为了更好地可视化,我们将时期损失和准确性绘制为

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()