暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

经典卷积架构的PyTorch实现:AlexNet

南极Python 2021-05-11
2490

AlexNet

在2012年的Imagenet竞赛中,AlexNet以低于第二名10.8个百分点的top-5错误率赢得了冠军,自此以后,基于CNN的图像分类算法开始流行起来,深度学习时代到来了。

AlexNet的网络结构如上图所示。相比于之前的LeNet-5,AlexNet堆叠了更多的卷积块,从而网络更深。同时,它还引入了Dropout的技巧,以及ReLU激活函数等。

在AlexNet刚被提出时,受限于当时的算力,作者采用了多个GPU进行训练。而随着技术的发展,现在的算力已经可以在单卡上训练AlexNet了,且显存绰绰有余。

更多细节,将在代码实现中体现。

PyTorch 实现 AlexNet

代码实现时,去除了现在已经很少被使用的LRN(局部响应归一化);并且将最后一个池化层由最大池化改为自适应平均池化,这种池化方法可以将不同尺寸的输入图片固定到特定尺寸,于是就可以固定住该池化层后面紧挨着的第一个全连接层的参数(最后一个池化层到第一个全连接之间有一个flatten操作,由于池化层输出的尺寸是固定的,因此flatten后再输入到这个全连接层的神经元个数也是固定的),使用起来更加灵活。

import torch
import torch.nn as nn

class AlexNet(nn.Module):

    def __init__(self, num_classes: int = 1000) -> None:
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(364, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(64192, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(192384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        
        self.avgpool = nn.AdaptiveAvgPool2d((66))
        
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Flatten(start_dim=1),
            nn.Linear(256 * 6 * 64096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(40964096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes),
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.features(x)
        x = self.avgpool(x)
        x = self.classifier(x)
        return x

测试一下:

可以看到,对于输入的3*224*224
的图片,经过AlexNet后,得到了1000维的向量。

那这中间的shape变化情况是怎么样的呢?我们可以看一下:

all_layers=nn.ModuleList()
all_layers.extend(model.features)
all_layers.append(model.avgpool)
all_layers.extend(model.classifier)
x=torch.randn(4,3,224,224)
for layer in all_layers:
    x=layer(x)
    print('\nshape:  '+str(x.shape)+'   ####  layer:',layer)

输出信息便是shape每经过一层后的变化情况,如下:

参考:

  • [1] https://d2l.ai/chapter_convolutional-modern/alexnet.html
  • [2] https://en.wikipedia.org/wiki/AlexNet
  • [3] https://github.com/pytorch/vision/blob/master/torchvision/models/alexnet.py



重磅!南极Python交流群已成立,添加下方微信,备注加群即可进群。


                             感谢点赞,分享和在看的你!


文章转载自南极Python,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论