【论文笔记】Network In Network

本文介绍了Network In Network (NiN)结构,一种利用多层感知机替代传统卷积层的深度学习模型。该模型通过引入mlpconv层增强特征抽象,并采用全局平均池化层替代全连接层以减少过拟合,提升模型解释性和泛化能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

    CNN中用到的卷积滤波器对于潜在的数据块来说是一个通用的线性模型(GLM),我们认为GLM抽象的层次比较低。用一个更强大的非线性函数逼近器作为“微型网络”取代GLM能提高模型的抽象能力。在NiN中我们的微型网络选用的是一个多层感知机。从网络结构的角度来看我们相当于增加了一个称之为mlpconv的网络层,它和线性的卷积层类似,都是将局部感受野映射为一个特征向量。Mlpconv使用一个包含了多个全连接层和非线性激活函数的多层感知机(MLP)将输入数据块映射为输出特征向量。通过像CNN那样在输入数据上滑动MLP从而得到特征图(feature maps),并将其导入到下一层网络。NiN的整体结构可以看作是多个mlpconv层的叠加。

    我们使用一个全局池化层(global average pooling layer)取代最终的全连接层,对最后一层mlpconv的输出特征图通过一个全局池化层进行空间平均作为分类置信度,结果向量直接导入到softmax分类器。全局池化层相比全连接层更具有可解释性,因为它将特征图和分类做了对应。除此之外,全连接层更容易过拟合并且严重依赖于dropout正则化,而全局池化层它自身就相当于一个正则化器,原生的具备防止过拟合的功能。

CNN

    经典的卷积神经网络由交替堆叠的卷积层和空间池化层构成。卷积层通过卷积滤波器再紧跟着一个非线性激活函数(rectifier、sigmoid、tanh等等)生成特征图。拿线性修正器来说,特征图可以由以下公式计算得到:

其中,(i,j)表示特征图中像素点的坐标,Xi,j表示以(i,j)为中心点的输入数据块,k表示特征图的通道索引。

Network In Network

    首先,强调一下我们提出的“Network In Network”结构中的核心组件:MLP卷积层和全局池化层。

  • MLP Convolution Layers

    考虑到潜在概念(latent concepts)没有先验信息,使用通用的函数逼近器来做局部数据的特征提取是可取的,它能够更加接近于潜在概念的抽象表达。羟向基和多层感知机是两种比较著名的通用函数逼迫器。我们之所以选择多层感知机有两方面的原因。首先,多层感知机与卷积神经网络兼容,也是基于反向传播算法进行训练。其次,多层感知机自身就可以是一个深度模型,这与特征重用的思想一致。在这篇论文中,我们提出的用于取代卷积层的新的网络层称之为mlpconv,其计算公式如下。

n表示多层感知机的层数,激活函数为修正线性单元。

注:修正线性函数神经网络中常用的一种激活函数,公式表示为:f(x) = max(0, x)。它被认为是更加符合神经元信号激励原理。采用了修正线性函数作为激活函数的单元被称之为修正线性单元。

 

  • Global Average Pooling

    传统的卷积神经网络中,最后一层卷积层形成的特征图将被向量化并导入到全连接层,紧接一个softmax逻辑回归层。这一结构桥接了卷积结构和传统的神经网络分类器。卷积结构被当作特征提取器,而结果特征通过传统神经网络的方式进行分类。然而,使用全连接层容易过拟合,因而限制了整体网络的泛化性能。

    这篇文章中,我们提出了另一策略,在CNN中用全局平均池化来取代传统的全连接层。意思就是,在mlpconv层之后对于每一个对应的分类生成一个特征图,我们对每一个特征图进行全局平均池化,结果向量直接导入到softmax层。优点在上文中已经提及,这里不再复述。

 

  • Network In Network Structure

    NiN的整体结构是一个mlpconv层的堆叠,结构的顶部是一个全局平均池化层和目标成本层。可以在mlpconv层之间增加降采样层。下图展示了一个3层mlpconv层的NiN结构。在每一个mlpconv层中包含3层感知器。NiN和微型网络的层数可以针对特定的任务进行灵活地调整。

 

要在UNet的桥接部分加入空洞卷积,可以在解码器的各个层之间插入空洞卷积层。下面是一个示例代码,展示如何在UNet的桥接部分加入空洞卷积: ```python import torch import torch.nn as nn from torchvision.models import densenet121 class UNet(nn.Module): def __init__(self, in_channels, out_channels): super(UNet, self).__init__() # 替换UNet的主干网络为DenseNet self.densenet = densenet121(pretrained=True) # 调整DenseNet的输入通道数 self.densenet.features.conv0 = nn.Conv2d(in_channels, 64, kernel_size=7, stride=2, padding=3, bias=False) # 定义UNet的其他层 self.encoder1 = self.densenet.features.denseblock1 self.encoder2 = self.densenet.features.denseblock2 self.encoder3 = self.densenet.features.denseblock3 self.encoder4 = self.densenet.features.denseblock4 # 定义解码器和空洞卷积层 self.decoder4 = nn.Sequential( nn.ConvTranspose2d(1024, 512, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(512), nn.ReLU(), nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=2, dilation=2), nn.BatchNorm2d(512), nn.ReLU() ) self.decoder3 = nn.Sequential( nn.ConvTranspose2d(512, 256, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(256), nn.ReLU(), nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=2, dilation=2), nn.BatchNorm2d(256), nn.ReLU() ) self.decoder2 = nn.Sequential( nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(128), nn.ReLU(), nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=2, dilation=2), nn.BatchNorm2d(128), nn.ReLU() ) self.decoder1 = nn.Sequential( nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(64), nn.ReLU(), nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=2, dilation=2), nn.BatchNorm2d(64), nn.ReLU() ) self.upsample = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) self.final_conv = nn.Conv2d(64, out_channels, kernel_size=1) def forward(self, x): # 编码器部分 encoder1 = self.encoder1(x) encoder2 = self.encoder2(encoder1) encoder3 = self.encoder3(encoder2) encoder4 = self.encoder4(encoder3) # 解码器部分 decoder4 = self.decoder4(encoder4) decoder3 = self.decoder3(decoder4 + encoder3) decoder2 = self.decoder2(decoder3 + encoder2) decoder1 = self.decoder1(decoder2 + encoder1) # 上采样 upsampled = self.upsample(decoder1) # 输出层 output = self.final_conv(upsampled) return output ``` 在上面的代码中,我们在解码器的各个层之间插入了一个空洞卷积层。空洞卷积通过在卷积操作中引入空洞(dilation)参数,可以扩大卷积核的感受野,从而增加网络的感知能力。 请注意,上面的代码中只是示例,你可以根据需要调整空洞卷积层的参数和位置。 希望这可以回答你的问题!如果你还有其他问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值