专栏首页贾志刚-OpenCV学堂AlexNet网络的结构详解与实现

AlexNet网络的结构详解与实现

一: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网络代码实现如下

import tensorflow as tf


class AlexNet_CNN:

    def __init__(self, x, keep_prob, num_class, skip_layer):
        self.X = x
        self.KEEP_PROB = keep_prob
        self.NUM_CLASS = num_class
        self.SKIP_LAYER = skip_layer
        print("AlexNet Network...")

    def create(self):
        with tf.name_scope("conv1") as scope:
            kernel = tf.Variable(tf.truncated_normal([11, 11, 3, 96], dtype=tf.float32, stddev=1e-1), name='weights1')
            conv1 = tf.nn.conv2d(self.X, kernel, strides=[1, 4, 4, 1], padding='VALID')
            lrn1 = tf.nn.lrn(conv1,depth_radius=2,bias=1.0,alpha=1e-05,beta=0.75)
            pool1 = tf.nn.max_pool(lrn1, ksize=[1, 3, 3, 1],
                           strides=[1, 2, 2, 1],
                           padding='SAME', name='pool1')
            print("pool1", pool1.shape)
        with tf.name_scope("conv2") as scope:
            kernel = tf.Variable(tf.truncated_normal([5, 5, 96, 256], dtype=tf.float32, stddev=1e-1), name='weights2')
            conv2 = tf.nn.conv2d(pool1, kernel, strides=[1, 1, 1, 1], padding='SAME')
            lrn2 = tf.nn.lrn(conv2, depth_radius=2, bias=1.0, alpha=1e-05, beta=0.75)
            pool2 = tf.nn.max_pool(lrn2, ksize=[1, 3, 3, 1],
                                   strides=[1, 2, 2, 1],
                                   padding='VALID', name='pool2')

            print("pool2",pool2.shape)
        with tf.name_scope("conv3") as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 384], dtype=tf.float32, stddev=1e-1), name='weights3')
            conv3 = tf.nn.conv2d(pool2, kernel, strides=[1, 1, 1, 1], padding='SAME')
            print("conv3",conv3.shape)

        with tf.name_scope("conv4") as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 384, 384], dtype=tf.float32, stddev=1e-1), name='weights4')
            conv4 = tf.nn.conv2d(conv3, kernel, strides=[1, 1, 1, 1], padding='SAME')
            print("conv4",conv4.shape)

        with tf.name_scope("conv5") as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 384, 256], dtype=tf.float32, stddev=1e-1), name='weights5')
            conv5 = tf.nn.conv2d(conv4, kernel, strides=[1, 1, 1, 1], padding='SAME')
            pool5 = tf.nn.max_pool(conv5, ksize=[1, 3, 3, 1],
                                   strides=[1, 2, 2, 1],
                                   padding='VALID', name='pool5')

        with tf.name_scope("fc6") as scope:
            print("pool5", pool5.shape)
            flattened = tf.reshape(pool5, [-1, 6 * 6 * 256])
            weights = tf.Variable(tf.random_normal([6*6*256, 4096]))
            biases = tf.Variable(tf.random_normal([4096]))

            # Matrix multiply weights and inputs and add bias
            act = tf.nn.xw_plus_b(flattened, weights, biases, name="fc6")
            fc6 = tf.nn.relu(act)
            dp6 = tf.nn.dropout(fc6,keep_prob=self.KEEP_PROB)

        with tf.name_scope("fc7") as scope:
            weights = tf.Variable(tf.random_normal([4096, 4096]))
            biases = tf.Variable(tf.random_normal([4096]))

            # Matrix multiply weights and inputs and add bias
            act = tf.nn.xw_plus_b(dp6, weights, biases, name="fc7")
            fc7 = tf.nn.relu(act)
            dp7 = tf.nn.dropout(fc7, keep_prob=self.KEEP_PROB)

        with tf.name_scope("fc8") as scope:
            weights = tf.Variable(tf.random_normal([4096, self.NUM_CLASS]))
            biases = tf.Variable(tf.random_normal([self.NUM_CLASS]))

            # Matrix multiply weights and inputs and add bias
            act = tf.nn.xw_plus_b(dp7, weights, biases, name="fc8")
        return act

运行之后结构显示:

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

本文分享自微信公众号 - OpenCV学堂(CVSCHOOL),作者:gloomyfish

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 升级到tensorflow2.0,我整个人都不好了

    Tensorflow 2.0发布已经有一段时间了,各种基于新API的教程看上去的确简单易用,一个简单的mnist手写识别只需要下面不到20行代码就OK了,

    OpenCV学堂
  • tensorflow中实现神经网络训练手写数字数据集mnist

    基于tensorflow实现一个简单的三层神经网络,并使用它训练mnist数据集,神经网络三层分别为:

    OpenCV学堂
  • 干货 | Tensorflow设计简单分类网络实现猫狗图像分类训练与测试

    第一层:32个feature map 5x5卷积、步长为2、最大值池化 局部相应归一化处理(LRN) 第二层:64个feature map 3x3卷积、步长为...

    OpenCV学堂
  • 【TensorFlow】理解 Estimators 和 Datasets

    Google 在 2017 年 9 月 12 号的博文 Introduction to TensorFlow Datasets and Estimators 中...

    Alan Lee
  • tensorflow入门:Logistic Regression

    g(z)=11+e−zg(z) = \frac{1}{1+e^{-z}}g(z)=1+e−z1​

    Steve Wang
  • 用 Tensorflow 建立 CNN

    稍稍乱入的CNN,本文依然是学习周莫烦视频的笔记。 还有 google 在 udacity 上的 CNN 教程。 CNN(Convolutional Neura...

    杨熹
  • 实例介绍TensorFlow的输入流水线

    在训练模型时,我们首先要处理的就是训练数据的加载与预处理的问题,这里称这个过程为输入流水线(input pipelines,或输入管道,[参考:https://...

    机器学习算法工程师
  • Task 3 使用TensorFlow

    对于一个被研究的物体,它有多个属性(x1, x2, ... xn)和一个值y。线性回归假设y与(x1, x2, ... xn)有线性关系,也就是我们可以把y表示...

    平凡的学生族
  • 基于tensorflow的手写数字分类预测kaggle实战

    kaggle网站手写数字分类的比赛链接:https://www.kaggle.com/c/digit-recognizer 注册账号后才能参加kaggle比赛...

    潇洒坤
  • tf12: 判断男声女声

    本帖训练一个简单的神经网络模型,用来判断声音是男是女。 本帖数据集取自voice-gender项目,这个项目使用了n种分类模型,并比较了准确率,但是它没有使...

    MachineLP

扫码关注云+社区

领取腾讯云代金券