3.搭建分类器-pytorch与自然语言处理

课程链接:Python人工智能20个小时玩转NLP自然语言处理【黑马程序员】_哔哩哔哩_bilibili

目的:对不同的输入图像进行识别并分类。采用CIFAR10数据集,进行单分类任务

目录

总体步骤:

一、数据集处理

1.1 下载数据集

1.2 展示数据集

二、定义卷积神经网络

2.1 构建卷积神经网络的类

2.2 定义损失函数与优化器

2.3 在训练集中训练模型

2.4 在测试集中测试模型

2.5分类别测试模型准确率

 小节


总体步骤:

1、使用torchvision下载CIFAR10数据集

2、定义卷积神经网络

3、定义损失函数

4、在训练集上训练模型

5、在测试集上测试模型

一、数据集处理

1.1 下载数据集

import torch
import torchvision
import torchvision.transforms as transforms
#transforms包要将torchvision中[0,1]数据格式转化为[-1,1]的标准张量格式
#首先创建数据转换器,将参数转化为tensor需要的格式并且将数据变为[-1,1]中
transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize(0.5,0.5,0.5),(0.5,0.5,0.5)])

#数据的load与提取,数据位置放在当前代码目录下的data中,下载的是训练集train=True,并且下载好的数据用transform进行转换
trainset=torchvision.datasets.CIFAR10(root="./data",train=True,download=True,transform=transform)
#数据要DataLoader封装,便于pytorch后续操作,迭代器设置后续一次性访问四条数据,suffle=True表示数据打乱,并且多个线程加速数据读取
trainloader=torch.utils.data.DataLoader(trainset,batch_size=4,suffle=True,num_workers=2)
#测试集train=False,测试数据不需要打乱所以suffle=False
testset=torchvision.datasets.CIFAR10(root="./data",train=False,download=True,transform=transform)
testloader=torch.utils.data.DataLoader(testset,batch_size=4,suffle=False,num_workers=2)
#10个标签
classes=("plane","car","bird","cat","deer","dog","frog","horse","ship","truck")

#课程中一直使用Linux ls 命令用于显示指定工作目录下的内容。如果Windows下载报错可以将num_workers设置为0

1.2 展示数据集

#展示训练集图片
import matplitlib.pyplot as plt
import numpy as np

#构建展示图片的函数,标准的数据的处理展示函数
def imshow(img)
  img=img/2+0.5#规范化
  npimg=img.numpy()#tensor转换为numpy
  plt.imshow(np.transpose(npimg,(1,2,0)))#维度转换
  plt.show()

#直接使用封装的数据迭代器trainloader的iter
dataiter=iter(trainloader)
#读取images,lables
images,lables=dataiter.next()

#以网格的形式展示图片
imshow(torchvision.utils.make_grid(images))
#以字符串的形式打印标签
print("".join("%5s"%classes[labels[j]] for j in range(4)))

二、定义卷积神经网络

2.1 构建卷积神经网络的类

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.module):
  def __init__(self):
    #两个卷积层,一个池化层,三个全连接层
    super(Net,self).__init__()
    self.conv1=nn.Conv2d(3,6,5)#输入3,输出6,kernel5
    self.conv2=nn.Conv2d(6,16,5)
    self.pool=nn.MaxPool2d(2,2)#最大化池化窗口2*2
    self.fc1=nn.Linear(16*5*5,120)
    self.fc2=nn.Linear(120,84)    
    self.fc3=nn.Linear(84,10)#分类器最终的分类结果是10类!

  def forward(self,x):
    x=self.pool(F.relu(self.conv1(x)))#经历第一层卷积层并激活和池化
    x=self.pool(F.relu(self.conv2(x)))#第二层激活+池化
    x=x.view(-1,16*5*5)#将三维张量缩减为2维,以适配全连接层的输入
    x=F.relu(self.fc1(x))
    x=F.relu(self.fc2(x))
    x=self.fc3(x)#经历最后一个全连接层
    return x

net=Net()#类的实例化
print(net)

2.2 定义损失函数与优化器

*这里采用的是交叉熵的损失函数和随机梯度下降优化器

#采用交叉熵损失函数和随机梯度下降优化器
import torch.optim as optim
criterion=nn.CrossEntropyLoss()
#多分类任务最好的损失函数:交叉熵损失函数,随机梯度下降优化器
optimizer=optim.SGD(net.parameters(),lr=0.001,momentum=0.9)#实例化类,设置学习率

2.3 在训练集中训练模型

*注意梯度下降算法需要迭代式训练,即需要一个批次一个批次来

for epoch in range(2):
#数据集遍历两轮,并用loss记录损失
  running_loss=0.0
  for i,data in enumerate(trainloader,0):
#data取出来分成两部分,一部分是图片的张量inputs,一部分是标签labels
  inputs,lable=data
#梯度清零
  optimizer.zero_grad()
  outputs=net(inputs)
  loss=criteron(outputs,labels)#交叉熵比较output和label
#反向传播+参数更新
  loss.backward()
  optimizer.step()
#打印信息,观察并监督代码的运行
  running_loss+=loss.item()
  if(i+1)%2000==0#每隔两千轮打印一次
    print('[%d,%5d] loss:%.3f'% (epoch+1,i+1,running_loss/2000))\
#打印到几个epoch,到几个轮,以及损失
    running_loss=0.0

print('Finished Training')


PATH="./cifar_net,pth"#设置一个保存路径在当前文件夹下
torch.save(net.state_dict(),PATH)#保存的是状态字典

2.4 在测试集中测试模型

先仅仅测试4张图看看demo

#首先取一个批次的数据展示图片,和前面训练集中展示图片是一样的
dataiter=iter(testloader)
images,lables=dataiter.next()
#以网格的形式展示图片
imshow(torchvision.utils.make_grid(images))
#标签以字符串的形式打印
print("GroundTruth:","".join("%5s"%classes[labels[j]] for j in range(4)))

#加载图片并对测试图片进行预测
net=Net()#首先实例化类对象
net.load_state_dict(torch.load(PATH))#在原来的路径中加载这个状态字典
#代码理解是首先load一个torch的path,然后从这个torch中把状态字典load进来

outputs=net(images)
predicted=torch.max(outputs,1)#贪心算法,选取最大概率类别
#每个批次的四个值都列一遍
print("Predicted:","".join("%5"%classes[predicted[j]] for j in range(4)))

对所有的测试集进行测试:

correct=0
total=0
with torch.mo_grad():#不进行卷积
  for data in testloader:
    images,labels=data#图片和标签
    outputs=net(images)
    predicted=torch.max(outputs.data,1)#1表示第一个维度
    total+=labels.size(0)#看总共遍历了多少样本
    correct+=(predicted==labels).sum().item()#累加成功样本个数,sum中真的按照1来加,假的为0
print("Accuracy of the network on the 10000 test images: %d%%"%(100*correct/total)
#最终以百分号形式打印

 原教程中代码有-,这里不理解啥意思?也没有运行,找时间调试一下更改这里

2.5分类别测试模型准确率

class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
  for data in testloader:
    images, labels = data
    outputs = net (images)#将图片放进网络,得到output
    predicted = torch.max(outputs, 1)
    c= (predicted == labels) . squeeze)
    for i in range(4) :#分别对四个类别进行统计
      label = labels[i]
      class_correct[label] += c[i].item()
      class_total[label] += 1
#打印不同类别的准确率
for i in range(10):
  print('Accuracy of %5s:%2d %%'%(classes[i], 100*class_correct[i]/class_total[i]))

#net.to(device)将数据和模型转换到GPU上面

 小节


版权声明:本文为qq_42035862原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。