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

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

640?wx_fmt=png

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

640?wx_fmt=png

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

torch 的张量运算

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

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

640?wx_fmt=png

        获取矩阵的大小:

print(x.size())

        torch.Size([2, 3])

        执行张量运算:

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

640?wx_fmt=png

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

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

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

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

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

        numpy 数组转为 torch 张量:

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

640?wx_fmt=png

        使用 .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 方法执行反向计算。

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

640?wx_fmt=png

        执行梯度计算:

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

640?wx_fmt=png

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

基于 torch 的 LeNet-5 训练 cifar10

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 数据集:

640?wx_fmt=png

        定义 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 x

net = Net()

        定义损失函数和优化器:

import torch.optim as optim
criterion = 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')

640?wx_fmt=png

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

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

640?wx_fmt=png

        看看 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 %

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

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

640?wx_fmt=png

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

参考资料:

http://pytorch.org/tutorials/

http://pytorch.apachecn.org/cn/tutorials/

往期精彩:


一个数据科学从业者的学习历程

640?
640?wx_fmt=jpeg
长按二维码.关注数据科学家养成记

640?wx_fmt=jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值