3.4 pytorch
    pytorch是torch的python版本,是由facebook开源的神经网络框架。pytorch虽然是深度学习框架中的后起之秀,但是发展极其迅猛。pytorch提供了numpy风格的tensor操作,熟悉numpy操作的用户非常容易上手。我们以解决经典的手写数字识别的问题为例,介绍pytorch的基本使用方法,代码路径为:
    https://github.com/duoergun0729/adversarial_examples/blob/master/code/2-pytorch.ipynb
    1. 加载相关库
    加载处理经典的手写数字识别问题相关的python库:
    import os
    import torch
    import torchvision
    from torch.autograd import variable
    import torch.utils.data.dataloader as data
    2. 加载数据集
    pytorch中针对常见的数据集进行了封装,免去了用户手工下载的过程并简化了预处理的过程。这里需要特别指出的是,pytorch中每个tensor包括输入节点,并且都可以有自己的梯度值,因此训练数据集要设置为train=true,测试数据集要设置为train=false:
    train_data = torchvision.datasets.mnist(
    'dataset/mnist-pytorch', train=true,
    transform=torchvision.transforms.totensor(), download=true
    )
    test_data = torchvision.datasets.mnist(
    'dataset/mnist-pytorch', train=false,
    transform=torchvision.transforms.totensor()
    )
    如果需要对数据进行归一化,可以进一步使用transforms.normalize方法:
    transform=transforms.compose([torchvision.transforms.totensor(),
    torchvision.transforms.normalize([0.5], [0.5])])
    第一次运行该程序时,pytorch会从互联网直接下载数据集并处理:
    downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
    downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
    downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
    downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
    processing... done!
    3. 定义网络结构
    使用与keras类似的网络结构,即两层隐藏层结构,不过使用batchnorm层替换了dropout层,在抵御过拟合的同时加快了训练的收敛速度。在pytorch中定义网络结构,通常需要继承torch.nn.module类,重点是在forward中完成前向传播的定义,在init中完成主要网络层的定义:
    class net(torch.nn.module):
    def __init__(self):
    super(net, self).__init__()
    self.dense = torch.nn.sequential(
    #全连接层
    torch.nn.linear(784, 512),
    #batchnorm层
    torch.nn.batchnorm1d(512),
    torch.nn.relu(),
    torch.nn.linear(512, 10),
    torch.nn.relu()
    ) def forward(self, x):
    #把输出转换成大小为784的一维向量
    x = x.view(-1, 784)
    x=self.dense(x)
    return torch.nn.functional.log_softmax(x, dim=1)
    最后可视化网络结构,细节如图3-7所示。
    图3-7 pytorch处理mnist的网络结构图
    4. 定义损失函数和优化器
    损失函数使用交叉熵crossentropyloss,优化器使用adam,优化的对象是全部网络参数:
    optimizer = torch.optim.adam(model.parameters())
    loss_func = torch.nn.crossentropyloss()
    5. 训练与验证
    pytorch的训练和验证过程是分开的,在训练阶段需要把训练数据进行前向传播后,使用损失函数计算训练数据的真实标签与预测标签之间损失值,然后显示调用反向传递backward(),使用优化器来调整参数,这一操作需要调用optimizer.step():
    for i, data in enumerate(train_loader):
    inputs, labels = data
    inputs, labels = inputs.to(device), labels.to(device)
    # 梯度清零
    optimizer.zero_grad()
    # 前向传播
    outputs = model(inputs)
    loss = loss_func(outputs, labels)
    #反向传递
    loss.backward()
    optimizer.step()
    每轮训练需要花费较长的时间,为了让训练过程可视化,可以打印训练的中间结果,比如每100个批次打印下平均损失值:
    # 每训练100个批次打印一次平均损失值
    sum_loss += loss.item()
    if (i+1) % 100 == 0:
    print('epoch=%d, batch=%d loss: %.04f'% (epoch + 1, i+1, sum_loss / 100))
    sum_loss = 0.0
    验证阶段要手工关闭反向传递,需要通过torch.no_grad()实现:
    # 每跑完一次epoch,测试一下准确率进入测试模式,禁止梯度传递
    with torch.no_grad():
    correct = 0
    total = 0
    for data in test_loader:
    images, labels = data
    images, labels = images.to(device), labels.to(device)
    outputs = model(images)
    # 取得分最高的那个类
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum()
    print('epoch=%d accuracy=%.02f%%' % (epoch + 1, (100 * correct /
    total)))
    经过20轮训练,在测试集上准确度达到了97.00%:
    epoch=20, batch=100 loss: 0.0035
    epoch=20, batch=200 loss: 0.0049
    epoch=20, batch=300 loss: 0.0040
    epoch=20, batch=400 loss: 0.0042
    epoch=20 accuracy=97.00%
    pytorch保存的模型文件后缀为pth:
    torch.save(model.state_dict(), 'models/pytorch-mnist.pth')

章节目录

智能系统与技术丛书·AI安全之对抗样本入门所有内容均来自互联网,一曲书屋只为原作者兜哥的小说进行宣传。欢迎各位书友支持兜哥并收藏智能系统与技术丛书·AI安全之对抗样本入门最新章节