padding和卷积的区别_卷积神经网络之Alexnet

ca6abd7124272e9dc9b51f35f5d44d7c.png

一、[Lenet](https://zhuanlan.zhihu.com/p/116181964)

二、[Alexnet](https://zhuanlan.zhihu.com/p/116197079)

三、[VGG](https://zhuanlan.zhihu.com/p/116197079)

前言

2012 年, AlexNet 横空出世。这个模型的名字来源于论⽂第一作者的姓名 Alex Krizhevsky。AlexNet 使⽤了 8 层卷积神经⽹络,并以很⼤的优势赢得了 ImageNet 2012 图像识别挑战赛冠军。

一、Alexnet网络结构

Alexnet模型由5个卷积层和3个池化Pooling 层 ,其中还有3个全连接层构成。AlexNet 跟 LeNet 结构类似,但使⽤了更多的卷积层和更⼤的参数空间来拟合⼤规模数据集 ImageNet。它是浅层神经⽹络和深度神经⽹络的分界线。

b97c59de1bfd3318000f6fc4f8e60d6c.png

05b184b6e3153cda3ab0ba2881af55f5.png
Alexnet网络结构

特点:

  • 1、在每个卷机后面添加了Relu激活函数,解决了Sigmoid的梯度消失问题,使收敛更快。
  • 2、使用随机丢弃技术(dropout)选择性地忽略训练中的单个神经元,避免模型的过拟合(也使用数据增强防止过拟合)
  • 3、添加了归一化LRN(Local Response Normalization,局部响应归一化)层,使准确率更高。
  • 4、重叠最大池化(overlapping max pooling),即池化范围 z 与步长 s 存在关系 z>s 避免平均池化(average pooling)的平均效应

补充

LRN与BN的区别:https://www.jianshu.com/p/ef689144c86e

深入理解Bachnormlization:https://zhuanlan.zhihu.com/p/87117010

简单的理解:BN是数据层面,LRN是通道层面,LRN是作用于卷积的一种优化,一般用于激活函数ReLU函数之后的一层。

二、Alexnet的keras实现

def AlexNet():
    model = Sequential()
    model.add(Conv2D(96,(11,11),strides=(4,4),input_shape=(227,227,3),padding='valid',activation='relu',kernel_initializer='uniform'))
    model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))
    model.add(Conv2D(256,(5,5),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
    model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))
    model.add(Conv2D(384,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
    model.add(Conv2D(384,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
    model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
    model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))
    model.add(Flatten())
    model.add(Dense(4096,activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(4096,activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(1000,activation='softmax'))
    return model

在实际使用过程中,通常会加入BN层,重新定义卷积层::BN应用在深度神经网络中最主要的作用是加速神经网络训练,并使模型训练更加稳定(可以适应大的学习率,对参数初始化不敏感),避免了人工适应调整网络超参数。

def Conv_block(layer, filters, kernerl_size=(3, 3), strides=(1, 1), padding="valid", name=None):
    x = Conv2D(filters=filters, kernel_size=kernel_size, strides=strides, padding=padding, name=name)(layer)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)
    return x

三、Alexnet的pytorch实现

import time
import torch
from torch import nn, optim
import torchvision


class AlexNet(nn.Module):
    def __init__(self):
        super(AlexNet, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 96, 11, 4), # in_channels, out_channels, kernel_size, stride, padding
            nn.ReLU(),
            nn.MaxPool2d(3, 2), # kernel_size, stride
            # 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
            nn.Conv2d(96, 256, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(3, 2),
            # 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。
            # 前两个卷积层后不使用池化层来减小输入的高和宽
            nn.Conv2d(256, 384, 3, 1, 1),
            nn.ReLU(),
            nn.Conv2d(384, 384, 3, 1, 1),
            nn.ReLU(),
            nn.Conv2d(384, 256, 3, 1, 1),
            nn.ReLU(),
            nn.MaxPool2d(3, 2)
        )

         # 这里全连接层的输出个数比LeNet中的大数倍。使用丢弃层来缓解过拟合
        self.fc = nn.Sequential(
            nn.Linear(256*5*5, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            # 输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000
            nn.Linear(4096, 10),
        )

    def forward(self, img):
        feature = self.conv(img)
        output = self.fc(feature.view(img.shape[0], -1))
        return output

Pytorch 源码中实现了LRN的操作,可以看到与Alexnet论文中的方法略有不同,α所乘的项由所有数值的平方和变成了所有数值的均值,但无论是使用均值还是平方和,两者都起到了 lateral inhibition(横向抑制)的作用。

def local_response_norm(input, size, alpha=1e-4, beta=0.75, k=1.):
    # type: (Tensor, int, float, float, float) -> Tensor
    r"""Applies local response normalization over an input signal composed of
    several input planes, where channels occupy the second dimension.
    Applies normalization across channels.

    See :class:`~torch.nn.LocalResponseNorm` for details.
    """
    dim = input.dim()
    if dim < 3:
        raise ValueError('Expected 3D or higher dimensionality 
                         input (got {} dimensions)'.format(dim))
    div = input.mul(input).unsqueeze(1)
    if dim == 3:
        div = pad(div, (0, 0, size // 2, (size - 1) // 2))
        div = avg_pool2d(div, (size, 1), stride=1).squeeze(1)
    else:
        sizes = input.size()
        div = div.view(sizes[0], 1, sizes[1], sizes[2], -1)
        div = pad(div, (0, 0, 0, 0, size // 2, (size - 1) // 2))
        div = avg_pool3d(div, (size, 1, 1), stride=1).squeeze(1)
        div = div.view(sizes)
    div = div.mul(alpha).add(k).pow(beta)
    return input / div

下面我们用pytorch简单实现以下BN层(仅训练阶段)

import torch

class BatchNorm2d(torch.nn.Module):

    def __init__(self, channel, eps=1e-5, affine=True, momentum=0.9):
        super().__init__()

        # 初始化训练参数
        self.gamma = torch.nn.Parameter(torch.ones(1, channel, 1, 1))
        self.beta = torch.nn.Parameter(torch.zeros(1, channel, 1, 1))
        self.eps = eps
        self.affine = affine
        self.momentum = momentum

        self.register_buffer('running_mean', torch.zeros(channel))
        self.register_buffer('running_var', torch.ones(channel))


    def forward(self, input):
        # input shape must be (n, c, h, w)
        if self.training:
            means = input.mean((0, 2, 3), keepdim=True)
            vars = ((input-means)**2).sum((0, 2, 3), keepdim=True)
            self.running_mean = self.momentum * self.running_mean + (1-self.momentum) * means
            self.running_var = self.momentum * self.running_var + (1-self.momentum) * vars
        else:
            means = self.running_mean
            vars = self.running_var

        output = (input - means) / torch.sqrt(vars + self.eps)
        if self.affine:
            output =  output* self.gamma + self.beta
        return output

五、ZF-net

ZFNet是2013ImageNet分类任务的冠军,其网络结构没什么改进,只是调了调参,性能较Alex提升了不少。ZF-Net只是将AlexNet第一层卷积核由11变成7,步长由4变为2,第3,4,5卷积层转变为384,384,256。

ZF-net的keras实现:

def ZF_Net():
    model = Sequential()  
    model.add(Conv2D(96,(7,7),strides=(2,2),input_shape=(224,224,3),padding='valid',activation='relu',kernel_initializer='uniform'))  
    model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))  
    model.add(Conv2D(256,(5,5),strides=(2,2),padding='same',activation='relu',kernel_initializer='uniform'))  
    model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))  
    model.add(Conv2D(384,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))  
    model.add(Conv2D(384,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))  
    model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))  
    model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))  
    model.add(Flatten())  
    model.add(Dense(4096,activation='relu'))  
    model.add(Dropout(0.5))  
    model.add(Dense(4096,activation='relu'))  
    model.add(Dropout(0.5))  
    model.add(Dense(1000,activation='softmax'))  
    return model

我是尾巴~

每日一句毒鸡汤:

没知觉的开始,猜不到的结局!不能攥在手心的无奈都是源于自己的无能,越是害怕失去的东西往往总是如愿以偿,第一次的自负,第二次的无知,第三次的莫名其妙,或许一切都是自己想太多,表面上的东西过于华丽,根本看不清真相。自己做出的每一个选择都是有代价的,至于回报,要么感觉理所当然,要么感觉自作自受!一念之差,或许结果相同,但心理经历却天差地别。很多事情在经历过之后很长时间才发现原来一切都那么巧合,就像被安排好的一样!

本次推荐:

一款好用的文字OCR识别软件:天若OCR

天若OCR文字识别​tianruoocr.cn
46daff7ac35a81d056a0edc3c75f9dc9.png

继续加油~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值