PyTorch 卷积神经网络

卷积

PyTorch 卷积神经网络
  卷积实则是一种特征映射,解决了在线性全连接层下的参数维度过大的问题。同时卷积也来源于人类视觉局部性的感受区域。 参数共享是卷积神经网络的一个重要特征,也极大地减少了参数维度。
PyTorch 卷积神经网络
  卷积一次来源于信号处理上两个函数之间的卷积运算,操作可视化后类似。
PyTorch 卷积神经网络

卷积神经网络

notation

PyTorch 卷积神经网络

  1. Input channels
  2. Kernel channels: 2ch
  3. Kernel size
  4. Stride 步幅。
  5. Padding 填充。

multi-Kernel

PyTorch 卷积神经网络

LeNet-5

PyTorch 卷积神经网络

卷积层的作用效果

PyTorch 卷积神经网络
  从图片来看卷积层的作用效果,浅层次的卷积越能捕捉图片细节特征,往后就可以捕捉图片的局部特征。

nn.Conv2d

#Class API     in_channels, out_channels(number of kernel)
layer = nn.Conv2d(2, 16, kernel_size=3, stride=1, padding=0)
x = torch.rand(1, 2, 28, 28)
out = layer.forward(x)
out.shape   # torch.Size([1, 16, 26, 26])
out_ = layer(x) #python provide magic to call __call__
out_.shape   # torch.Size([1, 16, 26, 26])
layer.weight.shape   # torch.Size([16, 2, 3, 3])
layer.bias.shape   #torch.Size([16])

F.conv2d

#Functional API
x = torch.rand(1, 3, 28, 28)
w = torch.rand(16, 3, 5, 5)
b = torch.rand(16)
out = F.conv2d(x, w, b, stride=1, padding=1)
out.shape   #torch.Size([16, 3, 26, 26])

池化层

pooling

pooling is also called down sample.
池化层为了缩减数据维度。

pooling 策略:

  1. Max Pooling.
  2. Avg Pooling.
layer = nn.Conv2d(2, 16, kernel_size=3, stride=1, padding=1)
x = torch.rand(1, 2, 28, 28)
out = layer(x) #python provide magic to call __call__
out.shape   # torch.Size([1, 16, 28, 28])

# Class API
layerPooling = nn.AvgPool2d(2, stride=4)
outPClassAPI = layerPooling(out)
outPClassAPI.shape   # torch.Size([1, 16, 7, 7])

# Functional API
outPFuncAPI = F.max_pool2d(out, 2, stride=4)
outPFuncAPI.shape   # torch.Size([1, 16, 7, 7])

upsample

  upsample 可以看做是图片的放大。
PyTorch 卷积神经网络

layer = nn.Conv2d(2, 16, kernel_size=3, stride=1, padding=1)
x = torch.rand(1, 2, 28, 28)
out = layer(x) #python provide magic to call __call__
out.shape   # torch.Size([1, 16, 28, 28])

out = F.interpolate(out, scale_factor=2, mode='nearest')
out.shape   # torch.Size([1, 16, 56, 56])

ReLu

PyTorch 卷积神经网络

layer = nn.Conv2d(2, 16, kernel_size=3, stride=1, padding=1)
x = torch.rand(1, 2, 28, 28)
out = layer(x) #python provide magic to call __call__
out.shape   # torch.Size([1, 16, 28, 28])
out.min()   # tensor(-1.2756, grad_fn=<MinBackward1>)

layer = nn.ReLU(inplace=True)
out = layer(out)
out.shape   # torch.Size([1, 16, 28, 28])
out.min()   tensor(0., grad_fn=<MinBackward1>)

batch norm

  Batch normalization 广泛应用于深度学习,CNN,RNN.

使用原因

PyTorch 卷积神经网络
   通过 BatchNorm 极大地避免使用 Sigmoid 函数时的梯度弥散情况,加快迭代收敛速度。

feature scale

  更利于搜索最优解

image Normlization

normlize = transforms.Normalize(mean=[0.485, 0.456, 0.406]
								std=[0.229, 0.224, 0.225]) #RGB

Batch Normlization

常见的 norm 类型:

PyTorch 卷积神经网络
  可以看出来 Batch Normlization 只保留 channel 的统计数据 mean 以及 varience.

PyTorch 卷积神经网络

PyTorch 卷积神经网络
  Batch Normlization 只会平移和缩放数据。

x = torch.rand(100, 16, 784)
layer = nn.BatchNorm1d(16)
out = layer(x)
out.shape   # torch.Size([100, 16, 784])
layer.running_mean.shape   # torch.Size([16])
layer.running_var.shape   # torch.Size([16])

  Class Variables, 查看类变量

vars(layer)
# 'affine': True,    otherwise weight=1, bias=0 not update
# 'training': True,    not test mode

  Batch Normlization 在 training 以及 test 行为不一样。
  因为在test时, 数据没有 Batch 统计单个数据 没有意义,因此只会使用 全局的 mean 以及 varience .且 weight 以及 bias 是不需要更新的。

layer.eval()     # 'training': False,
hatx = torch.rand(1, 16, 7, 7)
test = layer(hatx)

使用效果

PyTorch 卷积神经网络

使用优势

  1. 加快收敛速度
  2. 更好的效果
  3. 模型更健壮
    • 稳定性
    • 学习率过大

经典的神经网络

ImageNet dataset 224x224

PyTorch 卷积神经网络

LeNet-5

Yann LeCun
PyTorch 卷积神经网络
上世纪80年代产物,用于手写字体识别,精度优秀。

AlexNet

Geoffrey Hinton

  1. GTX 580
    • 3GB x 2
  2. 11 x 11
  3. 8 layers

PyTorch 卷积神经网络

1x1 convolution

  1. less computation 2. c in => c out

GoogLeNet

PyTorch 卷积神经网络
综合不同 size’s kernel 的感受野。
PyTorch 卷积神经网络

虽然深度学习随着网络层数的增加精度上有了明显的提升,但也不能无限制的增加
网络层数,否则 training 难度增加,精度不升反降。ResNet 很好地解决了这一问题。

PyTorch 卷积神经网络

ResNet

深度残差网络

PyTorch 卷积神经网络
提出短路层,寻找梯度回传的捷径。将新的 Unit 进行叠加形成 ResNet.

PyTorch 卷积神经网络

新的 Unit 单元,shape 不能变。将短路权利交给网络。

PyTorch 卷积神经网络
为什么叫残差(Residual)?
PyTorch 卷积神经网络

层数性能比较:
PyTorch 卷积神经网络

DenseNet

PyTorch 卷积神经网络

nn.Module 类

   当我们自己定义网络层时,必须继承 nn.Module 父类。常用的线性层,卷积层等 PyTorch 官方已经写好。

class MyLinear(nn.Module):

    def __init__(self, inp, outp):
        super(MyLinear, self).__init__()

        # requires_grad = True
        self.w = nn.Parameter(torch.randn(outp, inp))
        self.b = nn.Parameter(torch.randn(outp))

    def forward(self, x):
        x = x @ self.w.t() + self.b
        return x

Magic

  1. Every Layer is nn.Module
    • nn.Linear
    • nn.BatchNorm2d
    • nn.Conv2d
  2. nn.Module is nested in nn.Module

   使用 nn.Module 的好处:

  1. 可以使用大量现成的网络层。
    • Linear
    • ReLu
    • Sigmoid
    • Conv2d
    • ConvTransposed2d
    • Dropout
    • etc.
  2. Container 容器
    • net(x)
  self.model = nn.Sequential(
            nn.Linear(784, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 10),
            nn.LeakyReLU(inplace=True),
        )
  1. 有效管理参数
  net.parameters()   # iterator
  net.named_parameters   # auto-named weight and bias  iterator
  1. Modules
    • modules: all nodes
    • children: direct children
  class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()

        self.net = nn.Sequential(BasicNet(),
                                 nn.ReLU(),
                                 nn.Linear(3, 2))

    def forward(self, x):
        return self.net(x)


modules: net Sequential(
(0): BasicNet(
    (net): Linear(in_features=4, out_features=3, bias=True)
    )
(1): ReLU()
(2): Linear(in_features=3, out_features=2, bias=True)
)

modules: net.0 BasicNet(
              (net): Linear(in_features=4, out_features=3, bias=True)
               )
modules: net.0.net Linear(in_features=4, out_features=3, bias=True)

modules: net.1 ReLU()
modules: net.2 Linear(in_features=3, out_features=2, bias=True)
  1. GPU 加速
  device = torch.device('cuda')
  net = Net()
  net.to(device)
  1. 保存与加载中间数据
  net.load_state_dict(torch.load('ckpt.mdl'))
  ...train...
  torch.save(net.state_dict(), 'ckpt.mdl')
  1. train&test 状态切换方便。
  # train
  net.train()
  ...
  # test
  net.eval()
  1. 实现我们自己的类。
class Flatten(nn.Module):

    def __init__(self):
        super(Flatten, self).__init__()

    def forward(self, input):
        return input.view(input.size(0), -1)

class TestNet(nn.Module):

    def __init__(self):
        super(TestNet, self).__init__()

        self.net = nn.Sequential(nn.Conv2d(1, 16, stride=1, padding=1),
                                 nn.MaxPool2d(2, 2),
                                 Flatten(),
                                 nn.Linear(1*14*14, 10))

def forward(self, x):
        return self.net(x)
  1. 自己实现的线性层
class MyLinear(nn.Module):

    def __init__(self, inp, outp):
        super(MyLinear, self).__init__()

        # requires_grad = True
        self.w = nn.Parameter(torch.randn(outp, inp))
        self.b = nn.Parameter(torch.randn(outp))

    def forward(self, x):
        x = x @ self.w.t() + self.b
        return x

数据增强

  确保深度学习的深度网络有良好的表现,防止过拟合的重要标准就是要使用的是大数据集。

Flip

PyTorch 卷积神经网络

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.RandomHorizontalFlip(),
                       transforms.RandomVerticalFlip(),
                   ])),

Rotation

PyTorch 卷积神经网络

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.RandomRotation(15),
                       transforms.RandomRotation([90, 180, 270]),
                   ]))

Scale

PyTorch 卷积神经网络

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.Resize([32, 32]),
                   ])),

Crop part

PyTorch 卷积神经网络

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.RandomCrop([28, 28]),
                   ])),

Noise

PyTorch 卷积神经网络
pytorch 没有 加入高斯白噪点的 API,可人为加上高斯分布图片实现 图片的随机噪声。