📜  神经网络在图像识别中的实现

📅  最后修改于: 2020-11-11 01:00:19             🧑  作者: Mango

神经网络在图像识别中的实现

我们的下一个任务是在先前标记的图像的帮助下训练神经网络,以对新的测试图像进行分类。因此,我们将使用nn模块来构建神经网络。

有以下步骤来实现神经网络进行图像识别:

步骤1:

在第一步中,我们将定义用于创建神经模型实例的类。此类将从nn模块继承,因此我们首先必须导入nn包。

from torch import nn 
class classifier (nn.Module):

我们的类后面将有一个init()方法。在init()中,第一个参数将始终为self,第二个参数将为我们将调用的输入节点数,第三个参数将为隐藏层中的节点数,第四个参数将为第二个隐藏节点中的节点数层,最后一个参数将是输出层中的节点数。

def __init__(self,input_layer,hidden_layer1,hidden_layer2,output_layer):

第2步:

在第二步中,我们回想起init()方法来提供各种方法和属性,然后初始化输入层,隐藏层和输出层。有一件事记得我们将处理完全连接的神经网络。所以

super(),__init__()
self.linear1=nn.Linear(input_layer,hidden_layer1)
self.linear2=nn.Linear(hidden_layer1,hidden_layer2)
self.linear3=nn.Linear(hidden_layer2,output_layer) 
def __init__(self,input_layer,hidden_layer1,hidden_layer2,output_layer):

第三步:

现在,我们进行预测,但是在此之前,我们将导入torch.nn.functional程序包,然后将使用forward()函数并将self作为第一个参数,并将x用作我们将尝试进行的任何输入预测。

import torch.nn.functional as func
def forward(self,x):

现在,无论将要通过forward()函数传递的任何输入都将传递给linear1对象,我们将使用relu函数而不是Sigmoid。此输出将作为输入输入到第二个隐藏层,第二个隐藏层的输出将输入到输出层,并返回最后一层的输出。

注意:如果要处理多类数据集,则不会在输出层中应用任何激活函数。

x=func.relu(self.linear1(x))
x=func.relu(self.linear2(x))
x=self.linear3(x)
return x

第四步:

在下一步中,我们将设置模型构造函数。根据我们的初始化程序,我们必须设置输入尺寸,隐藏层尺寸和输出尺寸。

图像的像素强度将被馈送到我们的输入层。由于每个图像都是28 * 28像素,总共784像素,将被馈送到我们的神经网络。因此,我们将传递784作为第一个参数,我们将在第一和第二隐藏层中采用125和60个节点,在输出层中,我们将采用10个节点。所以

model=classification1(784,125,65,10)

步骤5:

现在,我们将定义损失函数。 nn.CrossEntropyLoss()用于多类分类。此函数是log_softmax()函数和NLLLoss()的组合,对数似然损失为负。无论n个类的训练和分类问题如何,我们都使用交叉熵。这样,它利用对数概率,因此我们传递的是行输出,而不是softmax激活函数的输出。

criteron=nn.CrossEntropyLoss()

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

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

步骤6:

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

loss_history=[]
correct_history=[] 

步骤7:

我们将从迭代每个纪元开始,对于每个纪元,我们都必须迭代由培训加载者提供给我们的每个培训批次。每个训练批次在火车装载机中的火车中包含一百张图像以及一百张标签

for e in range(epochs):
    for input, labels in training_loader: 

步骤8:

当我们遍历一批图像时,我们必须将它们展平,并且必须借助view方法来重塑它们。

根据神经网络的结构,我们的输入值将乘以将输入层连接到第一个隐藏层的权重矩阵。要进行这种乘法,我们必须使图像一维。我们必须将其展平为784像素的单行,而不是每个图像都是28行乘2列。

inputs=input.view(input.shape[0],-1)

现在,借助这些输入,我们得到的输出为

outputs=model(inputs) 

步骤9:

借助输出,我们将计算总分类交叉熵损失,最终将输出与实际标签进行比较。我们还将根据交叉熵准则确定误差。在执行培训通过的任何部分之前,我们必须像以前一样设置优化程序。

loss1=criteron(outputs,labels)
optimizer.zero_grad()
loss1.backward()
optimizer.step() 

步骤10:

为了跟踪每个时期的损失,我们将初始化一个变量损失,即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
from torch import nn
from torchvision import datasets, transforms

transform1=transforms.Compose([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)
def im_convert(tensor):
    image=tensor.clone().detach().numpy()
    image=image.transpose(1,2,0)
    print(image.shape)
    image=image*(np.array((0.5,0.5,0.5))+np.array((0.5,0.5,0.5)))
    image=image.clip(0,1)
    return image
dataiter=iter(training_loader)
images,labels=dataiter.next()
fig=plt.figure(figsize=(25,4))
for idx in np.arange(20):
    ax=fig.add_subplot(2,10,idx+1)
    plt.imshow(im_convert(images[idx]))
    ax.set_title([labels[idx].item()])
class classification1(nn.Module):
    def __init__(self,input_layer,hidden_layer1,hidden_layer2,output_layer):
        super().__init__()
        self.linear1=nn.Linear(input_layer,hidden_layer1)
        self.linear2=nn.Linear(hidden_layer1,hidden_layer2)
        self.linear3=nn.Linear(hidden_layer2,output_layer)
    def forward(self,x):
        x=func.relu(self.linear1(x))
        x=func.relu(self.linear2(x))
        x=self.linear3(x)
        return x
model=classification1(784,125,65,10)
criteron=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.0001)
epochs=12
loss_history=[]
correct_history=[]
for e in range(epochs):
    loss=0.0
    correct=0.0
    for input,labels in training_loader:
        inputs=input.view(input.shape[0],-1)
        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()))