1.6 例子:CIFAR-10分类

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(),#转为Tensor
    transforms.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 time

start = 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 x


net = 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 = 0
    for i, data in enumerate (trainloader, 0):
        inputs, labels = data

        outputs = 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 = data
        outputs = 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))

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值