dpn网络的pytorch实现方式

1. DPN网络概述

DPN(Dual Path Network)作为一种深度卷积神经网络,它在ResNet架构的基础上,引入了多个不同层次的特征,大大提升了神经网络的准确率。DPN 网络通过融合不同卷积核大小的特征图,得到更稳定的模型,避免了单一网络结构的过拟合。此外,DPN网络的结构,从旁支结构到中间并联结构,更好地保持了网络的平衡和全局信息的传递,因此具有比ResNet更优秀的表现。

2. PyTorch实现DPN网络

2.1 DPN模型结构

DPN的结构如下图所示:

图1:DPN网络结构

DPN网络由两部分组成:第一部分是一个主干网络,其由多个连续的DPN块组成;第二部分则是全局的平均池化和分类层。各DPN块的结构如下图所示:

图2:DPN块结构

DPN块由两个完全不同的路径组成,从而保持了网络的平衡和全局信息的传递。其中,第一条路径由一个带有1×1卷积的变换层和两个带有3×3卷积的变换层组成;第二个路径则由两个带有1×1和3×3卷积的变换层组成。这两个路径得到的特征图被concat起来,以增加网络的宽度和信息量。

2.2 DPN网络的实现

PyTorch实现DPN网络的代码如下所示,这里展示的是DPN92模型的实现,它依据上述结构,包含3个主要部分:DPN块、DPN主干、DPN分类器。

import torch.nn as nn

class DPNBlock(nn.Module):

def __init__(self, in_channels, mid_channels, out_channels, groups):

super(DPNBlock, self).__init__()

self.conv1x1_1 = nn.Conv2d(in_channels, mid_channels, kernel_size=1)

self.parallel_conv3x3 = nn.Sequential(

nn.Conv2d(mid_channels, mid_channels, kernel_size=3, stride=1, padding=1, groups=groups),

nn.Conv2d(mid_channels, out_channels, kernel_size=1)

)

self.conv1x1_2 = nn.Conv2d(in_channels, out_channels, kernel_size=1)

self.bn = nn.BatchNorm2d(2*out_channels)

self.relu = nn.ReLU(inplace=True)

def forward(self, x):

out = self.conv1x1_1(x)

out = self.parallel_conv3x3(out)

merge = self.conv1x1_2(x)

merge = self.bn(torch.cat([out, merge], dim=1))

return self.relu(merge)

class DPN(nn.Module):

def __init__(self, cfg, in_channels=3, os=32):

super(DPN, self).__init__()

self.os = os

self.in_channels = in_channels

# 前64个通道数为64的标准Block,输出128个

self.conv1 = nn.Conv2d(self.in_channels, 64, kernel_size=3, stride=2, padding=1, bias=False)

self.bn1 = nn.BatchNorm2d(64)

self.relu = nn.ReLU(inplace=True)

self.pool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)

# 连续的DPN块

self.layer1 = self._make_layer(cfg[0], 64, 256, 64)

self.layer2 = self._make_layer(cfg[1], 256, 512, 128, stride=2)

self.layer3 = self._make_layer(cfg[2], 512, 1024, 256, stride=2)

self.layer4 = self._make_layer(cfg[3], 1024, 2048, 512, stride=2)

# 分类层

self.avgpool = nn.AvgPool2d(kernel_size=7, stride=1)

self.fc = nn.Linear(2048, 1000)

def forward(self, x):

x = self.conv1(x)

x = self.bn1(x)

x = self.relu(x)

x = self.pool1(x)

x = self.layer1(x)

x = self.layer2(x)

x = self.layer3(x)

x = self.layer4(x)

x = self.avgpool(x)

x = self.fc(x)

return x

def _make_layer(self, num_layers, in_channels, mid_channels, out_channels, stride=1):

layers = [DPNBlock(in_channels, mid_channels, out_channels, groups=32)]

for i in range(num_layers-1):

layers.append(DPNBlock(out_channels*2, mid_channels, out_channels, groups=32))

return nn.Sequential(*layers)

def dpn92():

cfg = {

'num_blocks': [3,4,20,3],

'plane': [256,512,1024,2048],

'dpn_groups': 32,

'num_classes': 1000

}

return DPN(cfg, in_channels=3, os=32)

接下来,我们可以使用上述DPN92的网络结构来训练我们的数据集。

3. 总结

DPN网络的提出,思路简单,但取得了很好的效果。它在保持ResNet网络的优点不变的前提下,通过途径结构等技巧,使得网络具有更大的感受野,局部组件的高重复性也实现了融合,为后续深度学习的一系列模型提供了新的思路和实践经验。

后端开发标签