本次练习使用torchvision下载 cifar10数据 步骤为: 1定义卷积神经网络 2定义损失函数 3在训练集上训练模型 4在测试集上测试模型 5更改GPU训练
# 第一步
# 导入torchvision包下载数据集
import torch
import torchvision
import torchvision.transforms as transforms
##下载数据集并对图片进行调整,因为torch数据集的输出是PILImage格式,数据域在[0,1],
# 我们需要将其转换成标准数据域[-1,1]的张量格式
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))]
)
trainset = torchvision.datasets.CIFAR10(root='./data',train=True,
download=Ture,transform=transform)
trainloader = torch.utils.data.DataLoader(trainset,batch_size=4,
shuffle=True,num_workers=2)#
# 放进dataloader,分为训练集,4个小批次,打乱,使用两个线程
testset = torchvision.datasets.CIFAR10(root='./data',train=False,
download=True,transform=transform)
testloader = torch.utils.data.DataLoader(testset,batch_size=4,
shuffle=False,num_workers=2)#测试不用打乱
# 标签
classer=('plane','car','bird','cat',
'deer','dog','frog','horse','ship','truck')
数据集准备完了,可以查看一下:
## 导入画图包和numpy
import matplotlib.pyplot as plt
import numpy as np
#构建展示图片的函数
def imshow(img):
img=img/2+0.5#规整化
npimg=img.numpy()#tensor转化为array
plt.imshow(np.transpose(npimg,(1,2,0)))#
plt.show()
# 从数据迭代器中读取一张照片
dataiter = iter(trainloader)#迭代器
images, labels =dataiter.next()#.next()就能读出来
#展示图片
imshow(torchvision.utils.make_grid(images))
#打印标签label
print(' '.join('%5s' % classer[labels[j]] for j in range(4)))
下面定义卷积神经网络
## 定义卷积神经网络
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)
self.pool=nn.MaxPool2d(2,2)
self.conv2=nn.Conv2d(6,16,5)
self.fc1=nn.Linear(16*5*5,120)
self.fc2=nn.Linear(120,84)
self.fc3=nn.Linear(84,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)
x=F.relu(self.fc1(x))
x=F.relu(self.fc2(x))
x=self.fc3(x)
return x
net=Net()
print(net)
Net(
(conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
下面定义损失函数
## 定义损失函数
#使用交叉熵损失函数和随机梯度下降优化器
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.8)#传入所有参数,随机梯度下降,学习率0.01,冲量0.8
CPU训练模型
## 在训练集上训练模型
#采用基于梯度下降的优化算法,需要多个轮次的迭代训练
for epoch in range(3):#一轮训练多次
running_loss=0
for i ,data in enumerate(trainloader,0):
#data中包含图像张量input以及标签
input , labels =data
#首先将优化器梯度清零
optimizer.zero_grad()
#输入张量引入网络,得到输出张量output
outputs=net(input)
#利用输出和标签计算loss损失
loss = criterion(outputs,labels)
#反向传播+参数更新,
loss.backward()
optimizer.step()
#打印轮次和损失值
running_loss += loss.item()
if (i+1) % 200 ==0:
print('[%d,%5d] loss: %.3f' %
(epoch +1 , i+1 ,running_loss /2000))
running_loss =0.0
print("Finished Training")
部分结果
[3,11200] loss: 0.126
[3,11400] loss: 0.122
[3,11600] loss: 0.125
[3,11800] loss: 0.128
[3,12000] loss: 0.117
[3,12200] loss: 0.127
[3,12400] loss: 0.116
Finished Training
保存模型参数
##设定模型的保存位置
PATH="./cifar_net.pth"
# 保存模型的字典
torch.save(net.state_dict(),PATH)
跑测试集,先用一个batch测试
##在测试集上测试模型
# 第一步展示测试集中的若干图片
dataiter = iter (testloader)
image ,labels =dataiter.next()
#打印原始图片
imshow(torchvision.utils.make_grid(image))
#打印真实的标签
print("Groundtruth: "," ".join('%5s' % classer[labels[j]] for j in range(4)))
## 加载模并对测试图片进行预测
# 首先实例化模型的类对象
net = Net()
# 加载训练阶段保存好的模型的状态字典(也就是参数值)
net.load_state_dict(torch.load(PATH))
#利用模型对图片进行预测
outputs=net(image)
#共有10个类别,采用模型计算出的概率最大的作为预测的类别
_,predicted = torch.max(outputs,1)
#打印预测标签的结果
print("Predicted:"," ".join("%5s" % classer[predicted[j]] for j in range(4)))
Predicted: cat ship ship ship
可以看到,第四个预测错了,下面在所有集合上进行测试
## 在全部测试集合上的表现
correct=0
total=0
with torch.no_grad():
for data in testloader:
images,labels=data
outputs=net(images)
_,predicted=torch.max(outputs.data,1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print("10000张测试图片的网络准确率:%d %%" %(
100*correct/total
))
10000张测试图片的网络准确率:55 %
每个分类下准确率,这项更细致,很多函数建议查一查,或者可以把中间变量打印出来看一看,我有很多搞不懂,然后打印出来就搞懂了
## 每个分类下的准确率
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)
_,predicted=torch.max(outputs,1)
# max _返回最大值,predicted返回最大值索引,1是按照行
c= (predicted ==labels).squeeze()#sequeeze是什么?去掉维度为1的维度
# c每次输出TF共4个一维
for i in range(4):
label= labels[i]
class_correct[label] +=c[i].item()
class_total[label]+=1
for i in range(10):
print("%5s 的准确率为:%2d %%" %(
classer[i],100*class_correct[i]/class_total[i]
))
lane 的准确率为:59 %
car 的准确率为:51 %
bird 的准确率为:44 %
cat 的准确率为:26 %
deer 的准确率为:44 %
dog 的准确率为:36 %
frog 的准确率为:77 %
horse 的准确率为:73 %
ship 的准确率为:67 %
truck 的准确率为:75 %
首先定义设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
cuda:0##我有一块小破显卡
然后将模型和数据放进GPU(下面井号包裹住的就是重要的)
###########################333
net.to(device)
####################
## 在训练集上训练模型
#采用基于梯度下降的优化算法,需要多个轮次的迭代训练
for epoch in range(3):#一轮训练多次
running_loss=0
for i ,data in enumerate(trainloader,0):
#data中包含图像张量input以及标签
##########################################################
input , labels =data[0].to(device), data[1].to(device)
##########################################################
#首先将优化器梯度清零
optimizer.zero_grad()
#输入张量引入网络,得到输出张量output
outputs=net(input)
#利用输出和标签计算loss损失
loss = criterion(outputs,labels)
#反向传播+参数更新,
loss.backward()
optimizer.step()
#打印轮次和损失值
running_loss += loss.item()
if (i+1) % 200 ==0:
print('[%d,%5d] loss: %.3f' %
(epoch +1 , i+1 ,running_loss /2000))
running_loss =0.0
print("Finished Training")
结束