目录
本文为学习记录和备忘录,对代码进行了详细注释,以供学习。
内容来源:
★github: https://github.com/WZMIAOMIAO/deep-learning-for-image-processing
★b站:https://space.bilibili.com/18161609/channel/index
★CSDN:https://blog.csdn.net/qq_37541097
1. AlexNet网络详解
1.1 AlexNet网络概述
AlexNet是2012年ILSVRC 2012(ImageNet Large Scale Visual Recognition Challenge)竞赛的冠军网络。
论文链接:ImageNet Classification with Deep Convolutional Neural Networks
AlexNet网络的亮点:
- 首次利用 GPU 进行网络加速训练。
- 使用了 ReLU 激活函数,而不是传统的 Sigmoid 激活函数以及 Tanh 激活函数。
- 使用了 LRN 局部响应归一化(Local Response Normalization)。
- 在全连接层的前两层中使用了 Dropout 随机失活神经元操作,以减少过拟合。
1.2 Dropout
- 使用 Dropout 的方式在网络正向传播过程中随机失活一部分神经元,可以减少过拟合。
- 过拟合:根本原因是特征维度过多,模型假设过于复杂,参数过多,训练数据过少,噪声过多,导致拟合的函数完美的预测训练集,但对新数据的测试集预测结果差。 过度的拟合了训练数据,而没有考虑到泛化能力。
1.3 AlexNet网络结构和详细参数
- 卷积计算公式:
经卷积后的矩阵尺寸大小计算公式为:N = (W − F + 2P ) / S + 1
其中输入图片大小 W×W;Filter大小 F×F;步长 S;padding的像素数 P。
详细参数如下表:
2. Pytorch搭建
对于代码的解释都在注释中,方便对照查看学习。
2.1 model.py
- nn.Sequential()可以将一系列层结构进行打包,组合成新的模块,对于网络层次多的网络,借助其精简代码.
- 在这里的卷积中,padding只能传入两种类型的变量,一种是int整型,一种是tuple类型。如果传入的是int整型,如padding=1,则会在上方、下方各补1行0,左侧、右侧各补1列0。如果传入tuple类型的话,如tuple:(1, 2),1代表上下方各补1行0,2代表左右侧各补2列0。
如果想精确地在左侧补1列,右侧补2列的话,则需要nn.ZeroPad2d((1, 2, 1, 2)),左侧补1列,右侧补2列,上方补1行,下方补2行。 - 卷积或池化计算结果为小数时:卷积层向下取整,池化层向上取整。
- nn.ReLU(inplace=True), 其中的inplace可理解为增加计算量且降低内存使用量的一种方法。
- nn.Dropout(p=0.5), 其中0.5代表神经元失活比例,默认等于0.5。
- x = torch.flatten(x, start_dim=1) ,完成的是展平操作,从index=1开始(torch的tensor排列顺序为[batch,channel,height,width]),即从channel这个维度开始展平,展成一个一维向量,也可用view(x.shape[0],-1)来完成展平。
模型部分全部代码如下:
import torch.nn as nn
import torch
class AlexNet(nn.Module):
def __init__(self, num_classes=1000, init_weights=False):
super(AlexNet, self).__init__()
self.features = nn.Sequential( # nn.Sequential可以将一系列层结构进行打包,组合成新的模块,对于网络层次多的网络,借助其精简代码
# 取名为features,代表专门提取图像特征的结构
nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2), # input[3, 224, 224] output[48, 55, 55]
nn.ReLU(inplace=True), # inplace可理解为增加计算量且降低内存使用量的一种方法
nn.MaxPool2d(kernel_size=3, stride=2), # output[48, 27, 27]
nn.Conv2d(48, 128, kernel_size=5, padding=2), # output[128, 27, 27]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 13, 13]
nn.Conv2d(128, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
nn.Conv2d(192, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
nn.Conv2d(192, 128, kernel_size=3, padding=1), # output[128, 13, 13]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 6, 6]
# AlexNet架构为:Conv1,Maxpool1,Conv2,Maxpool2,Conv3,Conv4,Conv5,Maxpool3
)
self.classifier = nn.Sequential( # 借助nn.Sequential将全连接层打包为新的模块
nn.Dropout(p=0.5), # 在展平与FC1之间加上Dropout,0.5代表失活比例,默认等于0.5
nn.Linear(128 * 6 * 6, 2048), # output size:[6, 6, 128],且FC1节点数为2048
nn