在本教程中,您将学习如何使用称为空间变换器网络的视觉注意机制来扩充您的网络。你可以在DeepMind paper 阅读更多有关空间变换器网络的内容。

空间变换器网络是对任何空间变换的差异化关注的概括。空间变换器网络(简称STN)允许神经网络学习如何在输入图像上执行空间变换,以增强模型的几何不变性。例如,它可以裁剪感兴趣的区域,缩放并校正图像的方向。而这可能是一种有用的机制,因为CNN对于旋转和缩放以及更一般的仿射变换并不是不变的。

关于STN的最棒的事情之一是能够简单地将其插入任何现有的CNN,而且只需很少的修改。

from __future__ import print_function
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
import numpy as np plt.ion()   # 交互模式

1.加载数据

在这篇文章中,我们尝试了经典的 MNIST 数据集。使用标准卷积网络增强空间变换器网络。

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

# 训练数据集
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST(root='.', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])), batch_size=64, shuffle=True, num_workers=4)
# 测试数据集
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST(root='.', train=False, transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ])), batch_size=64, shuffle=True, num_workers=4)
  • 输出结果

Downloading http://yann.lecun.com/exdb/mnist/train-http://pytorch.panchuang.net/FourSection/images-idx3-ubyte.gz to ./MNIST/raw/train-http://pytorch.panchuang.net/FourSection/images-idx3-ubyte.gz
Extracting ./MNIST/raw/train-http://pytorch.panchuang.net/FourSection/images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to ./MNIST/raw/train-labels-idx1-ubyte.gz
Extracting ./MNIST/raw/train-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-http://pytorch.panchuang.net/FourSection/images-idx3-ubyte.gz to ./MNIST/raw/t10k-http://pytorch.panchuang.net/FourSection/images-idx3-ubyte.gz
Extracting ./MNIST/raw/t10k-http://pytorch.panchuang.net/FourSection/images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to ./MNIST/raw/t10k-labels-idx1-ubyte.gz
Extracting ./MNIST/raw/t10k-labels-idx1-ubyte.gz
Processing...
Done!

2.什么是空间变换器网络?

空间变换器网络归结为三个主要组成部分:

  • 本地网络(Localisation Network)是常规CNN,其对变换参数进行回归。不会从该数据集中明确地学习转换,而是网络自动学习增强全局准确性的空间变换。

  • 网格生成器( Grid Genator)在输入图像中生成与输出图像中的每个像素相对应的坐标网格。

  • 采样器(Sampler)使用变换的参数并将其应用于输入图像。

注意:我们使用最新版本的Pytorch,它应该包含affine_grid和grid_sample模块。

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.conv2_drop = nn.Dropout2d()
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)         # 空间变换器定位 - 网络
        self.localization = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=7),
            nn.MaxPool2d(2, stride=2),
            nn.ReLU(True),
            nn.Conv2d(8, 10, kernel_size=5),
            nn.MaxPool2d(2, stride=2),
            nn.ReLU(True)
        )         # 3 * 2 affine矩阵的回归量
        self.fc_loc = nn.Sequential(
            nn.Linear(10 * 3 * 3, 32),
            nn.ReLU(True),
            nn.Linear(32, 3 * 2)
        )         # 使用身份转换初始化权重/偏差
        self.fc_loc[2].weight.data.zero_()
        self.fc_loc[2].bias.data.copy_(torch.tensor([1, 0, 0, 0, 1, 0], dtype=torch.float))     # 空间变换器网络转发功能
    def stn(self, x):
        xs = self.localization(x)
        xs = xs.view(-1, 10 * 3 * 3)
        theta = self.fc_loc(xs)
        theta = theta.view(-1, 2, 3)         grid = F.affine_grid(theta, x.size())
        x = F.grid_sample(x, grid)         return x     def forward(self, x):
        # transform the input
        x = self.stn(x)         # 执行一般的前进传递
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1) model = Net().to(device)

3.训练模型

训练模型现在我们使用 SGD(随机梯度下降)算法来训练模型。网络正在以有监督的方式学习分类任务。同时,该模型以端到端的方式自动学习STN。

optimizer = optim.SGD(model.parameters(), lr=0.01)

def train(epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)         optimizer.zero_grad()
        output = model(data)
        loss = F.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        if batch_idx % 500 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))
#
# 一种简单的测试程序,用于测量STN在MNIST上的性能。.
# def test():
    with torch.no_grad():
        model.eval()
        test_loss = 0
        correct = 0
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)             # 累加批量损失
            test_loss += F.nll_loss(output, target, size_average=False).item()
            # 获取最大对数概率的索引
            pred = output.max(1, keepdim=True)[1]
            correct += pred.eq(target.view_as(pred)).sum().item()         test_loss /= len(test_loader.dataset)
        print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'
              .format(test_loss, correct, len(test_loader.dataset),
                      100. * correct / len(test_loader.dataset)))

4.可视化 STN 结果

现在,我们将检查我们学习的视觉注意机制的结果。

我们定义了一个小辅助函数,以便在训练时可视化变换。

def convert_http://pytorch.panchuang.net/FourSection/image_np(inp):
    """Convert a Tensor to numpy http://pytorch.panchuang.net/FourSection/image."""
    inp = inp.numpy().transpose((1, 2, 0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    inp = std * inp + mean
    inp = np.clip(inp, 0, 1)
    return inp # 我们想要在训练之后可视化空间变换器层的输出
# 我们使用STN可视化一批输入图像和相应的变换批次。
def visualize_stn():
    with torch.no_grad():
        # Get a batch of training data
        data = next(iter(test_loader))[0].to(device)         input_tensor = data.cpu()
        transformed_input_tensor = model.stn(data).cpu()         in_grid = convert_http://pytorch.panchuang.net/FourSection/image_np(
            torchvision.utils.make_grid(input_tensor))         out_grid = convert_http://pytorch.panchuang.net/FourSection/image_np(
            torchvision.utils.make_grid(transformed_input_tensor))         # Plot the results side-by-side
        f, axarr = plt.subplots(1, 2)
        axarr[0].imshow(in_grid)
        axarr[0].set_title('Dataset http://pytorch.panchuang.net/FourSection/images')         axarr[1].imshow(out_grid)
        axarr[1].set_title('Transformed http://pytorch.panchuang.net/FourSection/images') for epoch in range(1, 20 + 1):
    train(epoch)
    test() # 在某些输入批处理上可视化STN转换
visualize_stn() plt.ioff()
plt.show()
  • 输出结果

Train Epoch: 1 [0/60000 (0%)]   Loss: 2.336866
Train Epoch: 1 [32000/60000 (53%)]      Loss: 0.841600 Test set: Average loss: 0.2624, Accuracy: 9212/10000 (92%) Train Epoch: 2 [0/60000 (0%)]   Loss: 0.527656
Train Epoch: 2 [32000/60000 (53%)]      Loss: 0.428908 Test set: Average loss: 0.1176, Accuracy: 9632/10000 (96%) Train Epoch: 3 [0/60000 (0%)]   Loss: 0.305364
Train Epoch: 3 [32000/60000 (53%)]      Loss: 0.263615 Test set: Average loss: 0.1099, Accuracy: 9677/10000 (97%) Train Epoch: 4 [0/60000 (0%)]   Loss: 0.169776
Train Epoch: 4 [32000/60000 (53%)]      Loss: 0.408683 Test set: Average loss: 0.0861, Accuracy: 9734/10000 (97%) Train Epoch: 5 [0/60000 (0%)]   Loss: 0.286635
Train Epoch: 5 [32000/60000 (53%)]      Loss: 0.122162 Test set: Average loss: 0.0817, Accuracy: 9743/10000 (97%) Train Epoch: 6 [0/60000 (0%)]   Loss: 0.331074
Train Epoch: 6 [32000/60000 (53%)]      Loss: 0.126413 Test set: Average loss: 0.0589, Accuracy: 9822/10000 (98%) Train Epoch: 7 [0/60000 (0%)]   Loss: 0.109780
Train Epoch: 7 [32000/60000 (53%)]      Loss: 0.172199 Test set: Average loss: 0.0629, Accuracy: 9814/10000 (98%) Train Epoch: 8 [0/60000 (0%)]   Loss: 0.078934
Train Epoch: 8 [32000/60000 (53%)]      Loss: 0.156452 Test set: Average loss: 0.0563, Accuracy: 9839/10000 (98%) Train Epoch: 9 [0/60000 (0%)]   Loss: 0.063500
Train Epoch: 9 [32000/60000 (53%)]      Loss: 0.186023 Test set: Average loss: 0.0713, Accuracy: 9799/10000 (98%) Train Epoch: 10 [0/60000 (0%)]  Loss: 0.199808
Train Epoch: 10 [32000/60000 (53%)]     Loss: 0.083502 Test set: Average loss: 0.0528, Accuracy: 9850/10000 (98%) Train Epoch: 11 [0/60000 (0%)]  Loss: 0.092909
Train Epoch: 11 [32000/60000 (53%)]     Loss: 0.204410 Test set: Average loss: 0.0471, Accuracy: 9857/10000 (99%) Train Epoch: 12 [0/60000 (0%)]  Loss: 0.078322
Train Epoch: 12 [32000/60000 (53%)]     Loss: 0.041391 Test set: Average loss: 0.0634, Accuracy: 9796/10000 (98%) Train Epoch: 13 [0/60000 (0%)]  Loss: 0.061228
Train Epoch: 13 [32000/60000 (53%)]     Loss: 0.137952 Test set: Average loss: 0.0654, Accuracy: 9802/10000 (98%) Train Epoch: 14 [0/60000 (0%)]  Loss: 0.068635
Train Epoch: 14 [32000/60000 (53%)]     Loss: 0.084583 Test set: Average loss: 0.0515, Accuracy: 9853/10000 (99%) Train Epoch: 15 [0/60000 (0%)]  Loss: 0.263158
Train Epoch: 15 [32000/60000 (53%)]     Loss: 0.127036 Test set: Average loss: 0.0493, Accuracy: 9851/10000 (99%) Train Epoch: 16 [0/60000 (0%)]  Loss: 0.083642
Train Epoch: 16 [32000/60000 (53%)]     Loss: 0.028274 Test set: Average loss: 0.0461, Accuracy: 9867/10000 (99%) Train Epoch: 17 [0/60000 (0%)]  Loss: 0.076734
Train Epoch: 17 [32000/60000 (53%)]     Loss: 0.034796 Test set: Average loss: 0.0409, Accuracy: 9864/10000 (99%) Train Epoch: 18 [0/60000 (0%)]  Loss: 0.122501
Train Epoch: 18 [32000/60000 (53%)]     Loss: 0.152187 Test set: Average loss: 0.0474, Accuracy: 9860/10000 (99%) Train Epoch: 19 [0/60000 (0%)]  Loss: 0.050512
Train Epoch: 19 [32000/60000 (53%)]     Loss: 0.270055 Test set: Average loss: 0.0416, Accuracy: 9878/10000 (99%) Train Epoch: 20 [0/60000 (0%)]  Loss: 0.073357
Train Epoch: 20 [32000/60000 (53%)]     Loss: 0.017542 Test set: Average loss: 0.0713, Accuracy: 9816/10000 (98%)

脚本的总运行时间:1分48.736秒

PyTorch 官方60分钟教程的配套视频教程已经上线B站,欢迎观看,关注:

https://www.bilibili.com/video/av66421076

欢迎关注磐创博客资源汇总站:

http://docs.panchuang.net/

欢迎关注PyTorch官方中文教程站:

http://pytorch.panchuang.net/

PyTorch 系列教程之空间变换器网络的更多相关文章

  1. Pytorch系列教程

    介绍 不久前Pytorch发布了1.0版本,官网的doc页也更新了.这里说下官网的教程很实用,边学pytorch搭网络边学NLP-图像等领域的先进技术. 官网的教程都是英文的,本人就用这个系列博客做个 ...

  2. Pytorch系列教程-使用Seq2Seq网络和注意力机制进行机器翻译

    前言 本系列教程为pytorch官网文档翻译.本文对应官网地址:https://pytorch.org/tutorials/intermediate/seq2seq_translation_tutor ...

  3. Pytorch系列教程-使用字符级RNN生成姓名

    前言 本系列教程为pytorch官网文档翻译.本文对应官网地址:https://pytorch.org/tutorials/intermediate/char_rnn_generation_tutor ...

  4. Pytorch系列教程-使用字符级RNN对姓名进行分类

    前言 本系列教程为pytorch官网文档翻译.本文对应官网地址:https://pytorch.org/tutorials/intermediate/char_rnn_classification_t ...

  5. pytorch空间变换网络

    pytorch空间变换网络 本文将学习如何使用称为空间变换器网络的视觉注意机制来扩充网络.可以在DeepMind paper 阅读更多有关空间变换器网络的内容. 空间变换器网络是对任何空间变换的差异化 ...

  6. 数据挖掘入门系列教程(十一)之keras入门使用以及构建DNN网络识别MNIST

    简介 在上一篇博客:数据挖掘入门系列教程(十点五)之DNN介绍及公式推导中,详细的介绍了DNN,并对其进行了公式推导.本来这篇博客是准备直接介绍CNN的,但是想了一下,觉得还是使用keras构建一个D ...

  7. 数据挖掘入门系列教程(十二)之使用keras构建CNN网络识别CIFAR10

    简介 在上一篇博客:数据挖掘入门系列教程(十一点五)之CNN网络介绍中,介绍了CNN的工作原理和工作流程,在这一篇博客,将具体的使用代码来说明如何使用keras构建一个CNN网络来对CIFAR-10数 ...

  8. 从零搭建Pytorch模型教程(三)搭建Transformer网络

    ​ 前言 本文介绍了Transformer的基本流程,分块的两种实现方式,Position Emebdding的几种实现方式,Encoder的实现方式,最后分类的两种方式,以及最重要的数据格式的介绍. ...

  9. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

随机推荐

  1. 一个简单的爬取b站up下所有视频的所有评论信息的爬虫

    心血来潮搞了一个简单的爬虫,主要是想知道某个人的b站账号,但是你知道,b站在搜索一个用户时,如果这个用户没有投过稿,是搜不到的,,,这时就只能想方法搞到对方的mid,,就是 space.bilibil ...

  2. 一起了解 .Net Foundation 项目 No.12

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. Cecil Cecil 是 ...

  3. ES6 常用知识点总结

    ES6常用知识总结 之前总结了es5中js的一些知识点.这段时间看了石川blue老师讲解的es6课程,结合阮一峰老师的es6教程,随手做了一些笔记和总结分享给大家.内容还是es6主要的知识点,基本没有 ...

  4. 前端每日实战:7# 视频演示如何用纯 CSS 创作一个 3D 文字跑马灯特效

    效果预览 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. https://codepen.io/zhang-ou/pen/GdrrZq 可交互视频教程 此视频是可以交 ...

  5. [LeetCode] 面试题59 - II. 队列的最大值

    题目: 分析: 本题要求三个方法的时间复杂度都是O(1),对于push_back和pop_front都是好实现的 但是对于max_value,正常情况下要进行遍历才能获得最大值,那么如何才能在O(1) ...

  6. 前端解决跨域问题的终极武器——Nginx反向代理

    提到代理,分为:正向代理和反向代理. 正向代理:就是你访问不了Google,但是国外有个VPN可以访问Google,你访问VPN后叫它访问Google,然后把数据传给你. 正向代理隐藏了真实的客户端. ...

  7. Flink系列之状态及检查点

    Flink不同于其他实时计算的框架之处是它可以提供针对不同的状态进行编程和计算.本篇文章的主要思路如下,大家可以选择性阅读. 1. Flink的状态分类及不同点. 2. Flink针对不同的状态进行编 ...

  8. 一起了解 .Net Foundation 项目 No.17

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. Peachpie Comp ...

  9. 第一个爬虫经历----豆瓣电影top250(经典案例)

    因为要学习数据分析,需要从网上爬取数据,所以开始学习爬虫,使用python进行爬虫,有好几种模拟发送请求的方法,最基础的是使用urllib.request模块(python自带,无需再下载),第二是r ...

  10. (转)GNU风格ARM汇编语法指南(非常详细)5

    原文地址:http://zqwt.012.blog.163.com/blog/static/120446842010111482417545/ 6.GNU汇编程序中的常数 <1>    十 ...