CIFAR-10分类,步骤如下:

1)使用torchvision加载并预处理CIFAR-10数据集

2)定义网络

3)定义损失函数和优化器

4)训练网络并更新网络参数

5)测试网络

CIFAR-10数据加载及预处理

CIFAR-10是一个常用的彩色图片数据集,它有10个类别airplane、automobile、bird、cat、deer、dog、frog、horse、ship和truck。每张图片都是3*32*32,也就是3通道彩色图片,分辨率为32*32。

import torch as t
import torchvision as tv
import torchvision.transforms as transforms
from torchvision.transforms import ToPILImage
show = ToPILImage()#可以把Tensor转成Image,方便可视化#第一次运行程序torchvision会自动下载CIFAR-10数据集
#大约100MB,需要花费一定的时间,
#如果已经下载有CIFAR-10,可通过root参数指定#定义对于数据的预处理
transform=transforms.Compose([transforms.ToTensor(),#转为Tensortransforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))#归一化
])#训练集
trainset = tv.datasets.CIFAR10(root='/B/CIFAR-10data/',train=True,download=True,transform=transform
)trainloader=t.utils.data.DataLoader(trainset,batch_size=4,shuffle=True,num_workers=2
)#测试集
testset = tv.datasets.CIFAR10 ('/B/CIFAR-10data/',train=False,download=True,transform=transform
)testloader = t.utils.data.DataLoader (testset,batch_size=4,shuffle=False,num_workers=2
)
classes=('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')#定义网络
import torch.nn as nn
import torch.nn.functional as F
import timestart = time.time ()  # 计时# 定义网络结构
class Net (nn.Module):def __init__(self):super (Net, self).__init__ ()self.conv1 = nn.Conv2d (3, 6, 5)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 = F.max_pool2d (F.relu (self.conv1 (x)), 2)x = F.max_pool2d (F.relu (self.conv2 (x)), 2)x = x.view (x.size ()[0], -1)x = F.relu (self.fc1 (x))x = F.relu (self.fc2 (x))x = self.fc3 (x)return xnet = Net ()
print (net)#定义优化和损失
# 定义优化和损失
loss_func = nn.CrossEntropyLoss ()  # 交叉熵损失函数
optimizer = t.optim.SGD (net.parameters (), lr=0.001, momentum=0.9)# 训练网络
for epoch in range (2):running_loss = 0for i, data in enumerate (trainloader, 0):inputs, labels = dataoutputs = net (inputs)loss = loss_func (outputs, labels)optimizer.zero_grad ()loss.backward ()optimizer.step ()running_loss += loss.item ()if i % 2000 == 1999:print ('epoch:', epoch + 1, '|i:', i + 1, '|loss:%.3f' % (running_loss / 2000))running_loss = 0.0
end = time.time ()
time_using = end - start
print ('finish training')
print ('time:', time_using)#测试结果correct = 0 #定义的预测正确的图片数
total = 0#总共图片个数
with t.no_grad():for data in testloader:images,labels = dataoutputs = net(images)_,predict = t.max(outputs,1)total += labels.size(0)correct += (predict == labels).sum()
print('测试集中的准确率为:%d%%'%(100*correct/total))

Dataloader是一个可迭代的对象,它将dataset返回的每一条数据样本拼接成一个batch,并提供多线程加速优化和数据打乱等操作。当程序对dataset的所有数据遍历完一遍之后,对Dataloader也完成了一次迭代。

此处训练了仅仅2个epoch(遍历完一遍数据集称为一个epoch),可观察网络是否有效。将测试图片输入网络,计算它的label,然后与实际label进行比较。

输出:

Files already downloaded and verified
Files already downloaded and verified
Net(
  (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
  (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)
)
epoch: 1 |i: 2000 |loss:2.156
epoch: 1 |i: 4000 |loss:1.826
epoch: 1 |i: 6000 |loss:1.693
epoch: 1 |i: 8000 |loss:1.574
epoch: 1 |i: 10000 |loss:1.527
epoch: 1 |i: 12000 |loss:1.476
epoch: 2 |i: 2000 |loss:1.391
epoch: 2 |i: 4000 |loss:1.360
epoch: 2 |i: 6000 |loss:1.349
epoch: 2 |i: 8000 |loss:1.326
epoch: 2 |i: 10000 |loss:1.300
epoch: 2 |i: 12000 |loss:1.291
finish training
time: 217.39351534843445
测试集中的准确率为:54%

我们已经可以看出效果,准确率为54%,但这只是一部分图片,我们再来看看在整个测试机上的效果。

训练的准确率远远比随机猜测的(准确率为10%)好,证明网络确实学到了东西。

在GPU上训练

就像之前把Tensor从CPU转到GPU一样,模型也可以从CPU转到GPU。

if t.cuda.is_available():net.cuda()images=images.cuda()labels=labels.cuda()output=net(Variable(images))loss=criterion(output,Variable(labels))