zoukankan      html  css  js  c++  java
  • Training a classifier

    你已经学习了如何定义神经网络,计算损失和执行网络权重的更新。

    现在你或许在思考。

    What about data?

    通常当你需要处理图像,文本,音频,视频数据,你能够使用标准的python包将数据加载进numpy数组。之后你能够转换这些数组到torch.*Tensor。

    • 对于图片,类似于Pillow,OPenCV的包很有用
    • 对于音频,类似于scipy和librosa的包
    • 对于文字,无论是基于原生python和是Cython的加载,或者NLTK和SpaCy都有效

    对于视觉,我们特意创建了一个包叫做torchvision,它有常见数据集的数据加载,比如ImageNet,CIFAR10,MNIST等,还有图片的数据转换,torchvision.datasets和torch.utils.data.Dataloader。

    这提供了很方便的实现,避免了写样板代码。

    对于这一文章,我们将使用CIFAR10数据集。它拥有飞机,汽车,鸟,猫,鹿,狗,雾,马,船,卡车等类别。CIFAR-10的图片尺寸为3*32*32,也就是3个颜色通道和32*32个像素。

    Training  an image classifier

     我们将按照顺序执行如下步骤:

    1. 使用torchvision加载并且标准化CIFAR10训练和测试数据集
    2. 定义一个卷积神经网络
    3. 定义损失函数
    4. 使用训练数据训练网络
    5. 使用测试数据测试网络

    1.加载并标准化CIFAR10

    使用torchvision,加载CIFAR10非常简单

    import torch
    import torchvision
    import torchvision.transforms as transforms

    torchvision数据集的输出是PIL图片库图片,范围为[0,1]。我们将它们转换为tensor并标准化为[-1,1]。

    import torch
    import torchvision
    import torchvision.transforms as transforms
    
    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=True,transform=transform) trainloader=torch.data.Dataloader(trainset,batch_size=4,shuffle=True,num_workers=2)
    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)
    classes
    = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    out:
    Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
    Files already downloaded and verified

     我们来观察一下训练集图片

    import matplotlib.pyplot as plt
    import numpy as np
    
    def imshow(img):
        img=img/2+0.5
        npimg=img.numpy()
        plt.imshow(np.transpose(npimg,(1,2,0)))
    
    dataiter=iter(trainloader)
    images,labels=dataiter.next()
    
    imshow(torchvision.utils.make_grid(images))
    plt.show()
    print(''.join('%5s'%classes[labels[j]] for j in range(4)))

     

    out:
    truck truck  dog truck

     2.定义卷积神经网络

    从前面神经网络章节复制神经网络,并把它改成接受3维图片输入(而不是之前定义的一维图片)。

    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()

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

    我们使用分类交叉熵损失和带有动量的SGD

    import torch.optim as optim
    criterion = nn.CrossEntropyLoss()
    optimizer=optim.SGD(net.parameters(),lr=0.001,momentum=0.9)

    4.训练网络

    我们只需要简单地迭代数据,把输入喂进网络并优化。

    import torch.optim as optim
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.9)
    
    for epoch in range(2):
        running_loss=0.0
        for i,data in enumerate(trainloader,0):
            inputs,labels=data
            optimizer.zero_grad()
            outputs=net(inputs)
            loss=criterion(outputs,labels)
            loss.backward()
            optimizer.step()
    
            running_loss+=loss.item()
            if i%2000==1999:
                print('[%d, %5d] loss: %.3f' %(epoch + 1, i + 1, running_loss / 2000))
                running_loss=0
    print('Finished Training')
    out:
    [1,  2000] loss: 2.208
    [1,  4000] loss: 1.797
    [1,  6000] loss: 1.627
    [1,  8000] loss: 1.534
    [1, 10000] loss: 1.508
    [1, 12000] loss: 1.453
    [2,  2000] loss: 1.378
    [2,  4000] loss: 1.365
    [2,  6000] loss: 1.326
    [2,  8000] loss: 1.309
    [2, 10000] loss: 1.290
    [2, 12000] loss: 1.262
    Finished Training

    4.在测试数据集上测试网络

    我们已经遍历了两遍训练集来训练网络。需要检查下网络是不是已经学习到了什么。

    我们将检查神经网络输出的预测标签是否与真实标签相同。如果预测是正确的,我们将这一样本加入到正确预测的列表。

    我们先来熟悉一下训练图片。

    dataiter=iter(testloader)
    images,labes=dataiter.next()
    
    imshow(torchvision.utils.make_grid(images))
    plt.show()
    print('GroundTruth: ',' '.join('%5s' % classes[labels[j]] for j in range(4)))

    out:
    GroundTruth:  plane  deer   dog horse

     ok,现在让我们看一下神经网络认为这些样本是什么。

    outputs=net(images)

     输出是10个类别的量值,大的值代表网络认为某一类的可能性更大。所以我们来获得最大值得索引:

    _,predicted=torch.max(outputs,1)
    print("Predicted: ",' '.join('%5s' %classes[predicted[j]] for j in range(4)))
    out:
    Predicted:   bird   dog  deer horse

     让我们看看整个数据集上的模型表现。

    out:
    Accuracy of the network on the 10000 test images: 54 %

     这看起来要好过瞎猜,随机的话只要10%的准确率(因为是10类)。看来网络是学习到了一些东西。

    我们来继续看看在哪些类上的效果好,在哪些类上的效果比较差:

    out:
    Accuracy of plane : 56 %
    Accuracy of   car : 70 %
    Accuracy of  bird : 27 %
    Accuracy of   cat : 16 %
    Accuracy of  deer : 44 %
    Accuracy of   dog : 64 %
    Accuracy of  frog : 61 %
    Accuracy of horse : 73 %
    Accuracy of  ship : 68 %
    Accuracy of truck : 61 %

    好了,接下来该干点啥?

    我们怎样将这个神经网络运行在GPU上呢?

    Trainning on GPU

    就像你怎么把一个Tensor转移到GPU上一样,现在把神经网络转移到GPU上。

    如果我们有一个可用的CUDA,首先将我们的设备定义为第一个可见的cuda设备:

    device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print(device)
    out:
    cuda:0

     剩下的章节我们假定我们的设备是CUDA。

    之后这些方法将递归到所有模块,将其参数和缓冲区转换为CUDA张量:

    net.to(device)

     记得你还需要在每步循环里将数据转移到GPU上:

    inputs,labels=inputs.to(device),labels.to(device)

    为什么没注意到相对于CPU巨大的速度提升?这是因为你的网络还非常小。

    练习:尝试增加你网络的宽度(第一个nn.Conv2d的参数2应该与第二个nn.Conv2d的参数1是相等的数字),观察你得到的速度提升。

    达成目标:

    • 更深一步理解Pytorch的Tensor库和神经网络
    • 训练一个小神经网络来分类图片

     Trainning on multiple GPUs

    如果你想看到更加显著的GPU加速,请移步:https://pytorch.org/tutorials/beginner/blitz/data_parallel_tutorial.html

  • 相关阅读:
    去除字符串中多余空格
    day02-03 字符编码
    eclipse与myeclipse区别
    xz解压和zip解压
    yum安装
    防火墙
    查看和操作HBA卡
    复制linux虚拟机后网卡不能用的解决方法
    关闭IPv6
    更改root密码
  • 原文地址:https://www.cnblogs.com/Thinker-pcw/p/9637411.html
Copyright © 2011-2022 走看看