Analyse du réseau AlexNet
Annuaire d'articles
points forts
-
Pour la première fois, le GPU est introduit pour la formation à l'accélération du réseau, parmi lesquels, la figure suivante montre l'utilisation de deux GPU pour la formation
-
Utilisation de la fonction d'activation ReLU
-
Dans les deux premières couches de la couche entièrement connectée, Dropout est utilisé pour désactiver de manière aléatoire les neurones afin de réduire le surajustement
structure du réseau
La formule pour calculer la taille de la matrice après convolution est :
N = (W-F+P1+P2)/S+1
W
-La taille de l'image d'entrée W*W F
-La taille du noyau de convolution FxF ;
P1
: Le nombre de rembourrages au-dessus de l'image ; P2
: Le nombre de rembourrages sous l'image ; S
: La taille des pas
Conv1
Entrée : (3 224 224)
W=224,F=11,P=[1,2],S=4,N=(224-11+1+2)/4+1=55
Sortie : (96,55,55)
Maxpool1
Entrée : (96,55,55)
W=55,F=3,P=[0,0],S=2,N=(55-3)/2+1=27
Sortie : (96,27,27)
Conv2
Entrée : (96,27,27)
W=27,F=5,P=[2,2],S=1,N=(27-5+4)/1+1=27
Sortie : (256,27,27)
Maxpool2
Entrée : (256,27,27)
W=27,F=3,P=[0,0],S=2,N=(27-3)/2+1=13
Sortie : (256,13,13)
Conv3
Entrée : (256,13,13)
W=13,F=3,P=[1,1],S=1,N=(13-3+1+1)/1+1=13
Sortie : (384,13,13)
Conv4
Entrée : (384,13,13)
W=13,F=3,P=[1,1],S=1,N=(13-3+1+1)/1+1=13
Sortie : (384,13,13)
Conv5
Entrée : (384,13,13)
W=13,F=3,P=[1,1],S=1,N=(13-3+1+1)/1+1=13
Sortie : (256,13,13)
reproduction de code
class AlexNet(nn.Module):
def __init__(self,num_classes=1000,init_weights=False):
super(AlexNet, self).__init__()
# nn.Sequential 简化步骤
self.features = nn.Sequential(
# 特征提取层
# Input[3,224,224] output[48,55,55]
nn.Conv2d(3,48,kernel_size=11,stride=4,padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3,stride=2),
nn.Conv2d(48,128,kernel_size=5,padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3,stride=2),
nn.Conv2d(128,192,kernel_size=3,padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(192, 192, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(192, 128, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
self.classifier = nn.Sequential(
# 全连接层
nn.Dropout(p=0.5), # p:神经元随机失活的比例
nn.Linear(128*6*6,2048),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5),
nn.Linear(2048,2048),
nn.ReLU(inplace=True),
nn.Linear(2048,num_classes) # num_classes:分类的类别数
)
if init_weights:
self._initialize_weights()
def forward(self,x):
x = self.features(x)
x = torch.flatten(x,start_dim=1)
x = self.classifier(x)
return x
# 初始化权重
def _initialize_weights(self):
# 遍历整个modules
for m in self.modules():
# 发现有nn.Conv2d这个结构
if isinstance(m,nn.Conv2d):
# 凯明初始化权重
nn.init.kaiming_normal_(m.weight,mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias,0)
# 发现有nn.Linear,则使用正态分布初始化函数
elif isinstance(m,nn.Linear):
nn.init.normal_(m.weight,0,0.01)
nn.init.constant_(m.bias,0)