美文网首页神经网络与深度学习程序员
pytorch4学习4:训练一个分类器

pytorch4学习4:训练一个分类器

作者: bdb87b292706 | 来源:发表于2018-05-07 23:06 被阅读65次

    现在已经知道了一个网络的结构搭建,正向反向传播以及梯度下降的训练方法。那么如何读入一组数据?
    首先使用现有的python工具包将训练数据读入存为numpy的形式,之后将numpy转换为pytorch使用的tensor:
    -图像:使用Pillow或者OpenCV
    -音频:使用scipy或者librosa

    在pytorch中提供了一个数据库的读取包torchvision,可以读取并使用一些常用的数据库,例如imagenet,cifar10,mnist等。

    下面将以cifar10为例,介绍如何训练一个分类器:
    首先使用torchvision工具包下载并调用cifar10数据库:(这一部分将在后面详细介绍,就不在此展开讲)

    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.utils.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')
    

    接下来,定义我们的分类网络:

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

    下面定义一下loss的计算,和反向传播的方法:

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

    接下来,开始我们的训练吧:

    for epoch in range(2):  # loop over the dataset multiple times
    
        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            # get the inputs
            inputs, labels = data
    
            # zero the parameter gradients
            optimizer.zero_grad()
    
            # forward + backward + optimize
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
    
            # print statistics
            running_loss += loss.item()
            if i % 2000 == 1999:    # print every 2000 mini-batches
                print('[%d, %5d] loss: %.3f' %
                      (epoch + 1, i + 1, running_loss / 2000))
                running_loss = 0.0
    
    print('Finished Training')
    

    接下来在测试集上进行一下测试:

    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('Accuracy of the network on the 10000 test images: %d %%' % (
        100 * correct / total))
    

    可以得到输出的结果:

    Accuracy of the network on the 10000 test images: 53 %
    

    下面再测试一下每一类的结果:

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

    输出为:

    Accuracy of plane : 60 %
    Accuracy of   car : 75 %
    Accuracy of  bird : 33 %
    Accuracy of   cat : 50 %
    Accuracy of  deer : 26 %
    Accuracy of   dog : 47 %
    Accuracy of  frog : 54 %
    Accuracy of horse : 66 %
    Accuracy of  ship : 48 %
    Accuracy of truck : 70 %
    

    如果使用GPU训练,可以简单的将net,和输入数据都放到GPU上即可。这个matlab的操作类似。
    首先使用

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

    得到GPU的编号
    之后使用

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

    将网络和数据放到GPU上。代码中测试的时候使用

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

    相关文章

      网友评论

      • 777c797427e3:你好,我使用文中提到的“device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")” 但却报错,报错内容为:
        AttributeError: module 'torch' has no attribute 'device'
        请问,这是什么问题呢?
        bdb87b292706:@Andy_yu 你是不是装的CPU的版本

      本文标题:pytorch4学习4:训练一个分类器

      本文链接:https://www.haomeiwen.com/subject/yfrbrftx.html