AlexNet模型简介

    技术2022-07-13  66

    2012年AlexNet在ImageNet竞赛中以超过第二名10.9个百分点的绝对优势一举夺冠,自此,深度学习和卷积神经网络一举成名,一直火到了今天。

    模型组成

    输入层5个卷积层3个全链接层

    从上图还可以看到网络有两个分支,这是因为当时硬件条件有限,一块GPU显存不够所以使用了两块GPU分别训练,在最后的全连接层进行特征融合得到最后的结果。

    因为网络上比较流行上面这个图,但其实我个人更喜欢下面这个图,在逻辑和过程上更加清楚。

    AlexNet 各层的详细描述

    输入层: 输入大小为224 x 224的3通道图像,实际上会经过预处理变为227X227X3

    第1层:卷积层(卷积、池化)

        使用96个大小为11 x 11 x 3的卷积核,分两组(每组48个),按步长4个像素对输入层进行卷积运算,得到两组55 x 55 x48 的卷积结果。

        对卷积结果使用ReLu激活函数,得到激活结果。

        对激活结果使用窗口为3 x 3、步长为2个像素的重叠最大池化,得到27 x 27 x 48的池化结果。

        对池化结果使用局部响应归一化操作,得到27 x 27 x 48的归一化结果。

    第2层:卷积层(卷积、池化)

        使用256个大小为27 x 27 x 48的卷积核,分两组(每组128个),按步长1个像素对第2层的归一化结果进行卷积运算,得到两组27 x 27 x 128 的卷积结果。

        对卷积结果使用ReLu激活函数,得到激活结果。

        对两组 27 x 27 x 128的激活结果使用窗口为3 x 3、步长为2个像素的重叠最大池化,得到两组13 x 13 x 128的池化结果。

        对池化结果使用局部响应归一化操作,得到两组13 x 13 x128 的归一化结果。

    第3层:卷积层

        使用384个大小为13 x 13 x 256的卷集核,分两组,按步长为1个像素对上一层归一化结果卷积运算,得到两组13 x 13 x 192的卷积结果。

        对卷积结果使用ReLu激活函数,得到激活结果。

    第4层:卷积层

        使用384个大小为13 x 13 x 192的卷集核,分两组,按步长为1个像素对上一层的激活结果进行卷积运算,得到两组两组 13 x 13 x 192 的卷积结果。

        对卷积结果使用ReLu激活函数,得到激活结果

    第5层:卷积层(卷积、池化)

        使用256个大小为13 x 13 x 192的卷积核分两组,按步长为1个像素,对上一层的激活结果卷积运算,得到两组 13 x 13 x128卷积结果。

        对卷积结果使用ReLu激活函数,得到激活结果。

        对激活结果,进行窗口为3 x 3,步长为2个像素的重叠最大池化,得到两组13 x 3 x 128的池化结果。

    第6层: 全链接层

        使用4096个神经元分两组,对上一层的池化结果全链接处理。

        对全链接结果使用ReLu激活函数。

        对激活结果使用概率为0.5的dropout操作,得到dropout结果。

    第7层: 全链接层

        使用4096个神经元分两组,对上一层的池化结果全链接处理。

        对全链接结果使用ReLu激活函数。

        对激活结果使用概率为0.5的dropout操作,得到dropout结果。

    第8层: 输出层

        1000路的软最大输出层,用来覆盖1000类的标签分布。

    AlexNet 的贡献

    ReLU激活函数

    Dropout

    LRN

    数据增强

    代码实现

    from tensorflow.keras import layers, models, Model, Sequential def AlexNet_v1(im_height=224, im_width=224, class_num=1000): # tensorflow中的tensor通道排序是NHWC # 使用函数形式构建模型,必须加上输入层 input_image = layers.Input(shape=(im_height, im_width, 3), dtype="float32") # output(None, 224, 224, 3) x = layers.ZeroPadding2D(((1, 2), (1, 2)))(input_image) # output(None, 227, 227, 3) x = layers.Conv2D(48, kernel_size=11, strides=4, activation="relu")(x) # output(None, 55, 55, 48) x = layers.MaxPool2D(pool_size=3, strides=2)(x) # output(None, 27, 27, 48) x = layers.Conv2D(128, kernel_size=5, padding="same", activation="relu")(x) # output(None, 27, 27, 128) x = layers.MaxPool2D(pool_size=3, strides=2)(x) # output(None, 13, 13, 128) x = layers.Conv2D(192, kernel_size=3, padding="same", activation="relu")(x) # output(None, 13, 13, 192) x = layers.Conv2D(192, kernel_size=3, padding="same", activation="relu")(x) # output(None, 13, 13, 192) x = layers.Conv2D(128, kernel_size=3, padding="same", activation="relu")(x) # output(None, 13, 13, 128) x = layers.MaxPool2D(pool_size=3, strides=2)(x) # output(None, 6, 6, 128) x = layers.Flatten()(x) # output(None, 6*6*128) x = layers.Dropout(0.2)(x) # 为下一层的Dense层加入dropout x = layers.Dense(2048, activation="relu")(x) # output(None, 2048) x = layers.Dropout(0.2)(x) x = layers.Dense(2048, activation="relu")(x) # output(None, 2048) x = layers.Dense(class_num)(x) # output(None, 5), 在这里是可以用layers.Dense(10, activation="softmax"),从而省略后面的softmax层 predict = layers.Softmax()(x) model = models.Model(inputs=input_image, outputs=predict) return model class AlexNet_v2(Model): def __init__(self, class_num=1000): super(AlexNet_v2, self).__init__() self.features = Sequential([ layers.ZeroPadding2D(((1, 2), (1, 2))), # output(None, 227, 227, 3) layers.Conv2D(48, kernel_size=11, strides=4, activation="relu"), # output(None, 55, 55, 48) layers.MaxPool2D(pool_size=3, strides=2), # output(None, 27, 27, 48) layers.Conv2D(128, kernel_size=5, padding="same", activation="relu"), # output(None, 27, 27, 128) layers.MaxPool2D(pool_size=3, strides=2), # output(None, 13, 13, 128) layers.Conv2D(192, kernel_size=3, padding="same", activation="relu"), # output(None, 13, 13, 192) layers.Conv2D(192, kernel_size=3, padding="same", activation="relu"), # output(None, 13, 13, 192) layers.Conv2D(128, kernel_size=3, padding="same", activation="relu"), # output(None, 13, 13, 128) layers.MaxPool2D(pool_size=3, strides=2)]) # output(None, 6, 6, 128) self.flatten = layers.Flatten() self.classifier = Sequential([ layers.Dropout(0.2), layers.Dense(1024, activation="relu"), # output(None, 2048) layers.Dropout(0.2), layers.Dense(128, activation="relu"), # output(None, 2048) layers.Dense(class_num), # output(None, 5) layers.Softmax() ]) def call(self, inputs, **kwargs): x = self.features(inputs) x = self.flatten(x) x = self.classifier(x) return x

     

    Processed: 0.011, SQL: 9