分享

深度学习第23讲:PyTorch入门及快速上手指南

 LibraryPKU 2019-03-26

        在前面的理论讲解和网络实现中,我们断断续续的学习了 Tensorflow 和 keras 两个著名的深度学习框架。当然主要还是 Tensorflow,keras 的底层计算都是以 Tensorflow 为后端的。在正式进入下一环节的学习前,笔者先给 pytorch 入个门,至于系统的学习,还是需要依靠各种项目实战来锻炼。

      pytorch 是一款可以媲美于 Tensorflow 优秀的深度学习计算框架,但又相比于 Tensorflow 在语法上更具备灵活性。pytorch 原生于一款小众语言 lua,而后基于 python 版本后具备了强大的生命力。作为一款基于 python 的深度学习计算库,pytorch 提供了高于 numpy 的强大的张量计算能力和兼具灵活度和速度的深度学习研究功能。

        下面笔者就以 pytorch 基本张量运算、自动求导机制和基于 LeNet-5 的训练实例对 pytorch 进行一个快速的入门和上手。

torch 的张量运算

        和学习 Tensorflow 中的张量 tensor 一样,torch 的张量运算也可以理解为 numpy 科学计算的加强版。底层的计算逻辑基本一致,torch 张量的强大之处可以利用 GPU 来加速运算。
        创建一个 2x3 的矩阵:

x = torch.Tensor(2, 3)print(x)

        获取矩阵的大小:

print(x.size())

        torch.Size([2, 3])

        执行张量运算:

y = torch.rand(2, 3)print(x + y)

        或者是提供一种指定输出张量的运算语法:

result = torch.Tensor(2, 3)torch.add(x, y, out = result)print(result)

        当然 torch 也可以方便的与 numpy 数组进行转换。
        torch 张量转为 numpy 数组:

a = torch.ones(5).numpy()print(a)

        [1. 1. 1. 1. 1.]

        numpy 数组转为 torch 张量:

import numpy as npprint(torch.from_numpy(np.ones(5)))

        使用 .cuda 方法将 tensor 在 GPU 上运行:

if torch.cuda.is_available():    x = x.cuda()    y = y.cuda()    x + y

        由上述操作可见,torch 的张量运算和 numpy 一样非常简单,相较于 tensorflow 的张量运算要更加灵活。

自动求导

        在神经网络的反向传播中涉及了大量的求导运算,pytorch 中求导的核心计算模块 autograd 可以帮助我们快速实现复杂的求导运算。而求导运算又是建立在 torch 变量 Variable 基础之上的,Variable 对 torch 的 Tensor 进行了包装,当神经网络的结构和前向计算完成后,可以方便的对变量调用 backward 方法执行反向计算。
创建一个 Variable:

from torch.autograd import Variablex = Variable(torch.ones(2, 3), requires_grad = True)print(x)

        执行梯度计算:

y = x + 2z = y * y * 5out = z.mean()out.backward()print(x.grad)

      需要注意的是 torch 计算梯度时关于目标变量的梯度计算的表达方式为 Variable.grad

基于 torch 的 LeNet-5 训练 cifar10

        LeNet-5 网络我们在第 14 讲的时候已经对论文进行了详细的解读和实现。参看第 14 讲的链接:深度学习笔记14:CNN经典论文研读之Le-Net5及其Tensorflow实现
        数据准备和转换:

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

        torchvision 是用来服务于 torch 包的,用于生成、转换和准备预训练模型。cifar10 数据集:


        定义 LeNet-5 网络结构:

from torch.autograd import Variable
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 xnet = Net()

        定义损失函数和优化器:

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

        训练 LeNet-5:

for epoch in range(5):      running_loss = 0.0    for i, data in enumerate(trainloader, 0):        
       # get input data        inputs, labels = data        
       # variable the data        inputs, labels = Variable(inputs), Variable(labels)        
       # gradients zeros        optimizer.zero_grad()        
       # forward + backward + optimize        outputs = net(inputs)        loss = criterion(outputs, labels)        loss.backward()        optimizer.step()        
       # print model train info        running_loss += loss.data[0]        
       if i % 2000 == 1999:                print('[%d, %5d] loss: %.3f' %                  (epoch + 1, i + 1, running_loss / 2000))            running_loss = 0.0

print('Finished Training')

        在测试集上展示训练效果:

import matplotlib.pyplot as plt
def imshow(img):    img = img / 2 + 0.5        npimg = img.numpy()    plt.imshow(np.transpose(npimg, (1, 2, 0)))
# test the net on test datasets# ground truth
dataiter = iter(testloader)images, labels = dataiter.next()
# print image
imshow(torchvision.utils.make_grid(images))print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))


        看看 LeNet-5 的预测结果:

# the net predict result
outputs = net(Variable(images))_, predicted = torch.max(outputs.data, 1)print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]                              for j in range(4)))

        (‘Predicted: ‘, ‘  cat  ship  ship plane’)

        貌似训练效果很好。再来看一下模型在全部测试集上的表现:

# test on all test data
correct = 0
total = 0
for data in testloader:    images, labels = data    outputs = net(Variable(images))    _, predicted = torch.max(outputs.data, 1)    total += labels.size(0)    correct += (predicted == labels).sum()print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

        Accuracy of the network on the 10000 test images: 61 %
        准确率达到 61%,已经远超随机猜测的10%的准确率了。

        再看看模型在每一类别上的分类准确率的表现:

class_correct = list(0. for i in range(10))class_total = list(0. for i in range(10))
for data in testloader:    images, labels = data    outputs = net(Variable(images))    _, predicted = torch.max(outputs.data, 1)    c = (predicted == labels).squeeze()    
   for i in range(4):        label = labels[i]        class_correct[label] += c[i]        class_total[label] += 1

for i in range(10):    print('Accuracy of %5s : %2d %%' % (        classes[i], 100 * class_correct[i] / class_total[i]))

        可见模型在猫和鸟等小型动物上分类效果较差,在车船飞机等大型物体上效果较好。该实例来自于 pytorch 的官方 tutorial 60 分钟快速上手文档,能够让大家非常快速的入门学习 pytorch 。 在对神经网络的基本原理有深刻理解的基础上,对比之前的 tensorflow 和 keras,相信大家都能快速掌握 pytorch 。

参考资料:

http://pytorch.org/tutorials/

http://pytorch./cn/tutorials/

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多