PyTorch实现:经典网络 AlexNet

PyTorch实现:经典网络 AlexNet

1. AlexNet 网络介绍

卷积神经网络从诞生之处就是为图像处理,直接原始图像的像素数据简单处理作为模型的输入的。而传统的神经网络和其它机器学习方法不会这样做,而是在图像数据进入模型之前,需要经过人手工精心设计特征提取方法,最后将提取的特征再作为模型的输入。
在卷积神经网络出现的早期,由于计算设备的原因,能用于训练的数据想对较少,而且有因为大型的卷积神经网络的大量参数,导致模型很难被有效训练。因此,在很长一段时间,神经网络都落后于其它的机器学习方法。
传统的机器学习方法,在收集到数据集之后,需要使用光学、几何学等领域的知识来指导手工对数据的预处理,然后通过标准的特征提取算法获取特征,最后将提取的特征送入选择的分类器中。随着技术的发展,另一种想法开始出现:特征的提取本身,也应该由模型通过学习来提取;特征可以有多个神经网络层来共同学习。由此,诞生的 AlexNet 最终使得卷积神经网络开始在图像领域超越其它机器学习方法。

2. AlexNet 网络架构

网络支持的输入的尺寸为:3×224×224。

2.1 特征提取网络

2.1.1 Conv2d(3, 96, kernel_size=11, stride=4, padding=1)
 使用一个11*11的卷积核窗口来捕捉对象,
 padding=1 边缘都向外扩充1,
 同时,步幅为4,以减少输出的高度和宽度,
 最后,在尺寸减小的同时,增加输出通道的数目。

Conv2d output shape: torch.Size([1, 96, 54, 54])

2.1.2 nn.ReLU()

使用 ReLU 激活函数,一方面,ReLU激活函数的计算更简单,它不需要如sigmoid激活函数那般复杂的求幂运算。 另一方面,当使用不同的参数初始化方法时,ReLU激活函数使训练模型更加容易。 当sigmoid激活函数的输出非常接近于0或1时,这些区域的梯度几乎为0,因此反向传播无法继续更新一些模型参数。 相反,ReLU激活函数在正区间的梯度总是1。 因此,如果模型参数没有正确初始化,sigmoid函数可能在正区间内得到几乎为0的梯度,从而使模型无法得到有效的训练。

ReLU output shape: torch.Size([1, 96, 54, 54])

2.1.3 nn.MaxPool2d(kernel_size=3, stride=2)

最大池化,使用 3*3 的窗口,步幅为2。

MaxPool2d output shape: torch.Size([1, 96, 26, 26])

2.1.4 nn.Conv2d(96, 256, kernel_size=5, padding=2)
 使用一个 5*5 的卷积核窗口来捕捉对象,
 padding=2 边缘都向外扩充2,保持输出尺寸不变,
 最后,在尺寸减小的同时,增加输出通道的数目。

torch.Size([1, 256, 26, 26])

2.1.5 nn.ReLU()

使用 ReLU 激活函数。

ReLU output shape: torch.Size([1, 256, 26, 26])

2.1.6 nn.MaxPool2d(kernel_size=3, stride=2)

最大池化,使用 3*3 的窗口,步幅为2。

MaxPool2d output shape: torch.Size([1, 256, 12, 12])

2.1.7 nn.Conv2d(256, 384, kernel_size=3, padding=1)
 使用一个 3*3 的卷积核窗口来捕捉对象,
 padding=2 边缘都向外扩充2,保持输出尺寸不变,
 最后,在尺寸减小的同时,增加输出通道的数目。

Conv2d output shape: torch.Size([1, 384, 12, 12])

2.1.8 nn.ReLU()

使用 ReLU 激活函数。

ReLU output shape: torch.Size([1, 384, 12, 12])

2.1.9 nn.Conv2d(384, 384, kernel_size=3, padding=1)
 使用一个 3*3 的卷积核窗口来捕捉对象,
 padding=2 边缘都向外扩充2,保持输出尺寸不变,
 最后,保持输出通道的数目不变。

Conv2d output shape: torch.Size([1, 384, 12, 12])

2.1.10 nn.ReLU()

使用 ReLU 激活函数。

ReLU output shape: torch.Size([1, 384, 12, 12])

2.1.11 nn.Conv2d384, 256, kernel_size=3, padding=1)
 使用一个 3*3 的卷积核窗口来捕捉对象,
 padding=2 边缘都向外扩充2,保持输出尺寸不变,
 最后,降低输出通道的数目。

Conv2d output shape: torch.Size([1, 256, 12, 12])

2.1.12 nn.ReLU()

使用 ReLU 激活函数。

ReLU output shape: torch.Size([1, 256, 12, 12])

2.1.13 nn.MaxPool2d(kernel_size=3, stride=2)

最大池化,使用 3*3 的窗口,步幅为2。

MaxPool2d output shape: torch.Size([1, 256, 5, 5])

2.1.14 nn.Flatten()

展开为一维特征。

Flatten output shape: torch.Size([1, 6400])

2.2 分类器

2.2.1 nn.Linear(6400, 4096),

线性层。

Linear output shape: torch.Size([1, 4096])

2.2.2 nn.ReLU()

使用 ReLU 激活函数。

ReLU output shape: torch.Size([1, 4096])

2.2.3 nn.Dropout(p=0.5)

连接层的输出数量很高,使用dropout层来减轻过拟合。

Dropout output shape: torch.Size([1, 4096])

2.2.4 nn.Linear(4096, 4096)

线性层。

Linear output shape: torch.Size([1, 4096])

2.2.5 nn.ReLU()

使用 ReLU 激活函数。

ReLU output shape: torch.Size([1, 4096])

2.2.6 nn.Dropout(p=0.5)

连接层的输出数量很高,使用dropout层来减轻过拟合。

Dropout output shape: torch.Size([1, 4096])

2.2.7 nn.Linear(4096, 10)

输出层。

Linear output shape: torch.Size([1, 10])

3. AlexNet 网络实现

class AlexNet(nn.Module):
    
    def __init__(self, num_classes):
        super(AlexNet, self).__init__()
        self.feature_extr = nn.Sequential(
            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=3, stride=2), 

            nn.Conv2d(96, 256, kernel_size=5, padding=2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=3, stride=2),

            nn.Conv2d(256, 384, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(384, 384, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=3, stride=2),

            nn.Flatten()
            
        )
        self.classifier = nn.Sequential(
            nn.Linear(6400, 4096), 
            nn.ReLU(),
            nn.Dropout(p=0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(),
            nn.Dropout(p=0.5),
            nn.Linear(4096, num_classes)
        )

    def forward(self, x):
        x = self.feature_extr(x)
        x = self.classifier(x)
        return x
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值