分享

AlexNet网络的结构详解与实现

 太极混元天尊 2018-04-29

一:AlexNet网络结构

在2012年ImageNet图像分类任务竞赛中AlexNet一鸣惊人,对128万张1000个分类的预测结果大大超过其他算法模型准确率,打败其它非DNN网络一鸣惊人。AlexNet包括5个卷积层与三个全连接层,与今天动则十几层、几十层甚至成百上千层相比,简直是太简单、太容易理解啦。AlexNet网络一共有八层。前面5层是卷积层,后面3层是全连接层,整个网络结构显示如下:

各个层结构如下:

输入图像大小为224x244x3 的彩色RGB图像

  • CONV表示卷积层

  • LRN 表示局部响应归一化

  • POOL表示池化层

  • FC表示全连接层

  • ReLU表示激活函数

  • Dropout表示参与训练神经元百分比,针对全连接层。

卷积层与池化层步长与填充方式:

采用ReLU激活函数,基于CIFAR-10数据集,训练收敛速度相比tanh激活函数提升6倍。图示如下:

作者在2GPU上进行训练,所以paper中对上述完整的网络结构进行了差分,分别在2个GTX580 GPU上运行,基于ILSVRC-2000与ILSVRC-2012数据集进行了测试。很多文章中不加说明的将作者Paper中网络结构贴到文章中以后看文章了解AlexNet的读者都一头雾水,因为文章内容描述跟网络结构根本对不上,因此误导了不少人。

二:AlexNet网络实现

基于tensorflow,很容易实现一个AlexNet网络,本人把它定义成一个单独的Python类,方便大家创建使用它,完整的AlexNet网络代码实现如下

  1. import tensorflow as tf

  2. class AlexNet_CNN:

  3.    def __init__(self, x, keep_prob, num_class, skip_layer):

  4.        self.X = x

  5.        self.KEEP_PROB = keep_prob

  6.        self.NUM_CLASS = num_class

  7.        self.SKIP_LAYER = skip_layer

  8.        print('AlexNet Network...')

  9.    def create(self):

  10.        with tf.name_scope('conv1') as scope:

  11.            kernel = tf.Variable(tf.truncated_normal([11, 11, 3, 96], dtype=tf.float32, stddev=1e-1), name='weights1')

  12.            conv1 = tf.nn.conv2d(self.X, kernel, strides=[1, 4, 4, 1], padding='VALID')

  13.            lrn1 = tf.nn.lrn(conv1,depth_radius=2,bias=1.0,alpha=1e-05,beta=0.75)

  14.            pool1 = tf.nn.max_pool(lrn1, ksize=[1, 3, 3, 1],

  15.                           strides=[1, 2, 2, 1],

  16.                           padding='SAME', name='pool1')

  17.            print('pool1', pool1.shape)

  18.        with tf.name_scope('conv2') as scope:

  19.            kernel = tf.Variable(tf.truncated_normal([5, 5, 96, 256], dtype=tf.float32, stddev=1e-1), name='weights2')

  20.            conv2 = tf.nn.conv2d(pool1, kernel, strides=[1, 1, 1, 1], padding='SAME')

  21.            lrn2 = tf.nn.lrn(conv2, depth_radius=2, bias=1.0, alpha=1e-05, beta=0.75)

  22.            pool2 = tf.nn.max_pool(lrn2, ksize=[1, 3, 3, 1],

  23.                                   strides=[1, 2, 2, 1],

  24.                                   padding='VALID', name='pool2')

  25.            print('pool2',pool2.shape)

  26.        with tf.name_scope('conv3') as scope:

  27.            kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 384], dtype=tf.float32, stddev=1e-1), name='weights3')

  28.            conv3 = tf.nn.conv2d(pool2, kernel, strides=[1, 1, 1, 1], padding='SAME')

  29.            print('conv3',conv3.shape)

  30.        with tf.name_scope('conv4') as scope:

  31.            kernel = tf.Variable(tf.truncated_normal([3, 3, 384, 384], dtype=tf.float32, stddev=1e-1), name='weights4')

  32.            conv4 = tf.nn.conv2d(conv3, kernel, strides=[1, 1, 1, 1], padding='SAME')

  33.            print('conv4',conv4.shape)

  34.        with tf.name_scope('conv5') as scope:

  35.            kernel = tf.Variable(tf.truncated_normal([3, 3, 384, 256], dtype=tf.float32, stddev=1e-1), name='weights5')

  36.            conv5 = tf.nn.conv2d(conv4, kernel, strides=[1, 1, 1, 1], padding='SAME')

  37.            pool5 = tf.nn.max_pool(conv5, ksize=[1, 3, 3, 1],

  38.                                   strides=[1, 2, 2, 1],

  39.                                   padding='VALID', name='pool5')

  40.        with tf.name_scope('fc6') as scope:

  41.            print('pool5', pool5.shape)

  42.            flattened = tf.reshape(pool5, [-1, 6 * 6 * 256])

  43.            weights = tf.Variable(tf.random_normal([6*6*256, 4096]))

  44.            biases = tf.Variable(tf.random_normal([4096]))

  45.            # Matrix multiply weights and inputs and add bias

  46.            act = tf.nn.xw_plus_b(flattened, weights, biases, name='fc6')

  47.            fc6 = tf.nn.relu(act)

  48.            dp6 = tf.nn.dropout(fc6,keep_prob=self.KEEP_PROB)

  49.        with tf.name_scope('fc7') as scope:

  50.            weights = tf.Variable(tf.random_normal([4096, 4096]))

  51.            biases = tf.Variable(tf.random_normal([4096]))

  52.            # Matrix multiply weights and inputs and add bias

  53.            act = tf.nn.xw_plus_b(dp6, weights, biases, name='fc7')

  54.            fc7 = tf.nn.relu(act)

  55.            dp7 = tf.nn.dropout(fc7, keep_prob=self.KEEP_PROB)

  56.        with tf.name_scope('fc8') as scope:

  57.            weights = tf.Variable(tf.random_normal([4096, self.NUM_CLASS]))

  58.            biases = tf.Variable(tf.random_normal([self.NUM_CLASS]))

  59.            # Matrix multiply weights and inputs and add bias

  60.            act = tf.nn.xw_plus_b(dp7, weights, biases, name='fc8')

  61.        return act

运行之后结构显示:

卷积层输出与论文上完全一致。


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多