TensorFlow学习--GoogLeNet实现

来源:互联网 发布:麦壳少儿编程 编辑:程序博客网 时间:2024/06/04 21:34

GoogLeNet结构

Google Inception Net通常被称为Google Inception V1,在ILSVRC-2014比赛中由论文<Going deeper with convolutions>提出.
Inception V1有22层,比AlexNet的8层和VGGNet的19层还要深.参数量(500万)仅有AlexNet参数量(6000万)的1/12,但准确率远胜于AlexNet的准确率.
Inception V1降低参数量的目的:
1. 参数越多模型越庞大,需要模型学习的数据量就越大,且高质量的数据非常昂贵.
2. 参数越多,消耗的计算资源越多.

Inception V1网络的特点:
1. 模型层数更深(22层),表达能力更强.
2. 去除最后的全连接层,用全局平均池化层(即将图片尺寸变为1x1)来代替它.(借鉴了NIN)
3. 使用Inception Module提高了参数利用效率.

Inception V3中的种类:

这里写图片描述

这里写图片描述

这里写图片描述

Inception Module结构图:

这里写图片描述

1x1卷积可以跨通道组织信息,提高网络的表达能力,同时可以对输出通道升维和降维.Inception Module的4个分支都用到了1x1卷积来进行降维.第一个分支对输入进行了1x1卷积;第二个分支先使用1x1卷积然后连接3x3卷积,相当于进行了两次特征变换;第三个分支先使用了1x1卷积,然后使用5x5卷积;第四个分支是3x3最大池化后用1x1卷积.1x1卷积用很小的计算量就能增加一层特征变换和非线性化.Filter concatenation层将1×1/3×3/5×5的卷积结果连接起来(在输出通道数这个维度上聚合).这样防止了层数增多带来的计算资源的需求,使网络的宽度和深度均可扩大.

将高度相关的节点连接在一起,形成稀疏网络:

这里写图片描述

网络模型如图:

网络模型

GoogLeNet性能测试

import tensorflow as tfslim = tf.contrib.slimtrunc_normal = lambda stddev: tf.truncated_normal_initializer(0.0, stddev)# 生成默认参数def inception_v3_arg_scope(weight_decay=0.00004,                      # L2正则weight_decay                           stddev=0.1,                                # 标准差                           batch_norm_var_collection='moving_vars'):    batch_norm_params = {        'decay': 0.9997,        'epsilon':0.001,        'updates_collections': tf.GraphKeys.UPDATE_OPS,        'variables_collections':{            'beta': None,            'gamma': None,            'moving_mean': [batch_norm_var_collection],            'moving_variance': [batch_norm_var_collection],        }    }    # 提供了新的范围名称scope name    # 对slim.conv2d和slim.fully_connected两个函数的参数自动赋值    with slim.arg_scope([slim.conv2d, slim.fully_connected],                        weights_regularizer=slim.l2_regularizer(weight_decay)):        with slim.arg_scope(            [slim.conv2d], # 对卷积层的参数赋默认值            weights_initializer=tf.truncated_normal_initializer(stddev=stddev), # 权重初始化器            activation_fn=tf.nn.relu,  # 激活函数用ReLU            normalizer_params=batch_norm_params) as sc: # 标准化器参数用batch_norm_params            return sc# inputs为输入图片数据的tensor(299x299x3),scope为包含了函数默认参数的环境def inception_v3_base(inputs, scope=None):    # 保存某些关键节点    end_points = {}    # 定义InceptionV3的网络结构    with tf.variable_scope(scope, 'InceptionV3', [inputs]):        # 设置卷积/最大池化/平均池化的默认步长为1,padding模式为VALID        # 设置Inception模块组的默认参数        with slim.arg_scope([slim.conv2d,       # 创建卷积层                             slim.max_pool2d,   # 输出的通道数                             slim.avg_pool2d],  # 卷积核尺寸                            stride=1,           # 步长                            padding='VALID'):   # padding模式            # 经3个3x3的卷积层后,输入数据(299x299x3)变为(35x35x192),空间尺寸降低,输出通道增加            net = slim.conv2d(inputs, 32, [3,3], stride=2, scope='Conv2d_1a_3x3')            net = slim.conv2d(net, 32, [3, 3], scope='Conv2d_2a_3x3')            net = slim.conv2d(net, 64, [3, 3], padding='SAME', scope='Conv2d_2b_3x3')            net = slim.max_pool2d(net, [3, 3], stride=2, scope='MaxPool_3a_3x3')            net = slim.conv2d(net, 80, [1, 1], scope='Conv2d_3b_1x1')            net = slim.conv2d(net, 192, [3, 3], scope='Conv2d_4a_3x3')            net = slim.max_pool2d(net, [3, 3], stride=2, scope='MaxPool_5a_3x3')        # 设置卷积/最大池化/平均池化的默认步长为1,padding模式为SAME        # 步长为1,padding模式为SAME,所以图像尺寸不会变,仍为35x35        with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d], stride=1, padding='SAME'):            # 设置Inception Moduel名称为Mixed_5b            with tf.variable_scope('Mixed_5b'):                # 第1个分支:64输出通道的1x1卷积                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')                # 第2个分支:48输出通道的1x1卷积,连接64输出通道的5x5卷积                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 48, [1, 1], scope='Con2d_0a_1x1')                    branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope='Conv2d_0b_5x5')                # 第3个分支:64输出通道的1x1卷积,连接两个96输出通道的3x3卷积                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0b_3x3')                    branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0c_3x3')                # 第4个分支:3x3的平均池化,连接32输出通道的1x1卷积                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 32, [1, 1], scope='Conv2d_0b_1x1')                # 4个分支输出通道数之和=64+64+96+32=256,输出tensor为35x35x256                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            # 第1个Inception模块组的第2个Inception Module            with tf.variable_scope('Mixed_5c'):                # 第1个分支:64输出通道的1x1卷积                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')                # 第2个分支:48输出通道的1x1卷积,连接64输出通道的5x5卷积                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 48, [1, 1], scope='Conv2d_0b_1x1')                    branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope='Conv2d_0c_5x5')                # 第3个分支:64输出通道的1x1卷积,连接两个96输出通道的3x3卷积                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0b_3x3')                    branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0c_3x3')                # 第4个分支:3x3的平均池化,连接64输出通道的1x1卷积                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 64, [1, 1], scope='Conv2d_0b_1x1')                # 输出tensor尺寸为35x35x288                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            # 第1个Inception模块组的第3个Inception Module            with tf.variable_scope('Mixed_5d'):                # 第1个分支:64输出通道的1x1卷积                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')                # 第2个分支:48输出通道的1x1卷积,连接64输出通道的5x5卷积                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 48, [1, 1], scope='Conv2d_0a_1x1')                    branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope='Conv2d_0b_5x5')                # 第3个分支:64输出通道的1x1卷积,连接两个96输出通道的3x3卷积                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0b_3x3')                    branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0c_3x3')                # 第4个分支:3x3的平均池化,连接64输出通道的1x1卷积                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 64, [1, 1], scope='Conv2d_0b_1x1')                # 输出tensor尺寸为35x35x288                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            # 第2个Inception模块组            with tf.variable_scope('Mixed_6a'):                # 第1个分支:3x3卷积,步长为2,padding模式为VALID,因此图像被压缩为17x17                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 384, [3, 3], stride=2 , padding='VALID', scope='Conv2d_1a_1x1')                # 第2个分支:64输出通道的1x1卷积,连接2个96输出通道的3x3卷积                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')                    branch_1 = slim.conv2d(branch_1, 96, [3, 3], scope='Conv2d_0b_3x3')                    # 步长为2,padding模式为VALID,因此图像被压缩为17x17                    branch_1 = slim.conv2d(branch_1, 96, [3, 3], stride=2, padding='VALID', scope='Conv2d_1a_1x1')                # 第3个分支:3x3的最大池化层,步长为2,padding模式为VALID,因此图像被压缩为17x17x256                with tf.variable_scope('Branch_2'):                    branch_2 = slim.max_pool2d(net, [3, 3], stride=2, padding='VALID', scope='MaxPool_1a_3x3')                net = tf.concat([branch_0, branch_1, branch_2], 3)            # 第2个Inception模块组,包含5个Inception Module            with tf.variable_scope('Mixed_6b'):                # 第1个分支:192输出通道的1x1卷积                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')                # 第2个分支:128输出通道的1x1卷积,接128输出通道的1x7卷积,接192输出通道的7x1卷积                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 128, [1, 1], scope='Conv2d_0a_1x1')                    branch_1 = slim.conv2d(branch_1, 128, [1, 7], scope='Conv2d_0b_1x7')                    branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 128, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 128, [7, 1], scope='Conv2d_0b_7x1')                    branch_2 = slim.conv2d(branch_2, 128, [1, 7], scope='Conv2d_0c_1x7')                    branch_2 = slim.conv2d(branch_2, 128, [7, 1], scope='Conv2d_0d_7x1')                    branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0e_1x7')                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')                # 输出tensor尺寸=17x17x(192+192+192+192)=17x17x768                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            # 经过一个Inception Module输出tensor尺寸不变,但特征相当于被精炼类一遍            # 第3个Inception模块组            with tf.variable_scope('Mixed_6c'):                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')                    branch_1 = slim.conv2d(branch_1, 160, [1, 7], scope='Conv2d_0b_1x7')                    branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0b_7x1')                    branch_2 = slim.conv2d(branch_2, 160, [1, 7], scope='Conv2d_0c_1x7')                    branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0d_7x1')                    branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0e_1x7')                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')                # 输出tensor尺寸为17x17x768                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            # 第4个Inception模块组            with tf.variable_scope('Mixed_6d'):                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')                    branch_1 = slim.conv2d(branch_1, 160, [1, 7], scope='Conv2d_0b_1x7')                    branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0b_7x1')                    branch_2 = slim.conv2d(branch_2, 160, [1, 7], scope='Conv2d_0c_1x7')                    branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0d_7x1')                    branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0e_1x7')                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')                # 输出tensor尺寸为17x17x768                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            # 第5个Inception模块组            with tf.variable_scope('Mixed_6e'):                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')                    branch_1 = slim.conv2d(branch_1, 192, [1, 7], scope='Conv2d_0b_1x7')                    branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 192, [7, 1], scope='Conv2d_0b_7x1')                    branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0c_1x7')                    branch_2 = slim.conv2d(branch_2, 192, [7, 1], scope='Conv2d_0d_7x1')                    branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0e_1x7')                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')                # 输出tensor尺寸为17x17x768                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            # 将Mixed_6e存储于end_points中            end_points['Mixed_6e'] = net            # 第3个Inception模块            # 第1个Inception模块组            with tf.variable_scope('Mixed_7a'):                # 第1个分支:192输出通道的1x1卷积,接320输出通道的3x3卷积 步长为2                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')                    branch_0 = slim.conv2d(branch_0, 320, [3, 3], stride=2, padding='VALID', scope='Conv2d_0a_3x3')                # 第2个分支:4个卷积层                with tf.variable_scope('Branch_1'):                    # 192输出通道的1x1卷积                    branch_1 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')                    # 192输出通道的1x7卷积                    branch_1 = slim.conv2d(branch_1, 192, [1, 7], scope='Conv2d_0b_1x7')                    # 192输出通道的7x1卷积                    branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')                    # 192输出通道的3x3卷积 步长为2,输出8x8x192                    branch_1 = slim.conv2d(branch_1, 192, [3, 3], stride=2, padding='VALID', scope='Conv2d_1a_3x3')                # 第3个分支:3x3的最大池化层,输出8x8x768                with tf.variable_scope('Branch_2'):                    branch_2 = slim.max_pool2d(net, [3, 3], stride=2, padding='VALID', scope='MaxPool_1a_3x3')                # 输出tensor尺寸:8x8x(320+192+768)=8x8x1280,尺寸缩小,通道数增加                net = tf.concat([branch_0, branch_1, branch_2], 3)            # 第2个Inception模块组            with tf.variable_scope('Mixed_7b'):                # 第1个分支:320输出通道的1x1卷积                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 320, [1, 1], scope='Conv2d_0a_1x1')                # 第2个分支:384输出通道的1x1卷积                # 分支内拆分为两个分支:384输出通道的1x3卷积+384输出通道的3x1卷积                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 384, [1, 1], scope='Conv2d_0a_1x1')                    branch_1 = tf.concat([                               slim.conv2d(branch_1, 384, [1, 3], scope='Conv2d_0b_1x3'),                               slim.conv2d(branch_1, 384, [3, 1], scope='Conv2d_0b_3x1')], 3)                # 第3个分支:448输出通道的1x1卷积,接384输出通道的3x3卷积,分支内拆分为两个分支                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 448, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 384, [3, 3], scope='Conv2d_0b_3x3')                    # 分支内拆分为两个分支:384输出通道的1x3卷积+384输出通道的3x1卷积                    branch_2 = tf.concat([                               slim.conv2d(branch_2, 384, [1, 3], scope='Conv2d_0c_1x3'),                               slim.conv2d(branch_2, 384, [3, 1], scope='Conv2d_0d_3x1')], 3)                # 第4个分支:3x3的平均池化层,接192输出通道的1x1卷积,输出8x8x768                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')                # 输出tensor尺寸:8x8x(320+768+768+192)=8x8x2048                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            # 第3个Inception模块组            with tf.variable_scope('Mixed_7c'):                # 第1个分支:320输出通道的1x1卷积                with tf.variable_scope('Branch_0'):                    branch_0 = slim.conv2d(net, 320, [1, 1], scope='Conv2d_0a_1x1')                # 第2个分支:384输出通道的1x1卷积                # 分支内拆分为两个分支:384输出通道的1x3卷积+384输出通道的3x1卷积                with tf.variable_scope('Branch_1'):                    branch_1 = slim.conv2d(net, 384, [1, 1], scope='Conv2d_0a_1x1')                    branch_1 = tf.concat([                               slim.conv2d(branch_1, 384, [1, 3], scope='Conv2d_0b_1x3'),                               slim.conv2d(branch_1, 384, [3, 1], scope='Conv2d_0c_3x1')], 3)                # 第3个分支:448输出通道的1x1卷积,接384输出通道的3x3卷积,分支内拆分为两个分支                with tf.variable_scope('Branch_2'):                    branch_2 = slim.conv2d(net, 448, [1, 1], scope='Conv2d_0a_1x1')                    branch_2 = slim.conv2d(branch_2, 384, [3, 3], scope='Conv2d_0b_3x3')                    # 分支内拆分为两个分支:384输出通道的1x3卷积+384输出通道的3x1卷积                    branch_2 = tf.concat([                               slim.conv2d(branch_2, 384, [1, 3], scope='Conv2d_0c_1x3'),                               slim.conv2d(branch_2, 384, [3, 1], scope='Conv2d_0d_3x1')], 3)                # 第4个分支:3x3的平均池化层,接192输出通道的1x1卷积,输出8x8x768                with tf.variable_scope('Branch_3'):                    branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')                    branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')                # 输出tensor尺寸:8x8x(320+768+768+192)=8x8x2048                net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)            return net, end_points# 全局平均池化def inception_v3(inputs,                 num_classes=1000,          # 最后分类数量                 is_training=True,          # 是否是训练过程的标志                 dropout_keep_prob=0.8,     # Dropout保留节点的比例                 prediction_fn=slim.softmax,# 进行分类的函数                 spatial_squeeze=True,      # 是否对输出进行squeeze操作,即去除维数为1的维度                 reuse=None,                # tf.variable_scope的reuse默认值                 scope='InceptionV3'):      # tf.variable_scope的scope默认值    with tf.variable_scope(scope, 'InceptionV3', [inputs, num_classes], reuse=reuse) as scope:        with slim.arg_scope([slim.batch_norm, slim.dropout], is_training=is_training):            net, end_points = inception_v3_base(inputs, scope=scope)            # 设置卷积/最大池化/平均池化的默认步长为1,padding模式为SAME            with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d], stride=1, padding='SAME'):                aux_logits = end_points['Mixed_6e']                # 辅助分类节点                with tf.variable_scope('AuxLogits'):                    # 5x5的平均池化,步长设为3,padding模式设为VALID                    aux_logits = slim.avg_pool2d(aux_logits, [5, 5], stride=3, padding='VALID', scope='AvgPool_1a_5x5')                    aux_logits = slim.conv2d(aux_logits, 128, [1, 1], scope='Conv2d_1b_1x1')                    aux_logits = slim.conv2d(aux_logits,768, [5, 5], weights_initializer=trunc_normal(0.01), padding='VALID', scope='Conv2d_2a_5x5')                    aux_logits = slim.conv2d(aux_logits, num_classes, [1, 1], activation_fn=None,                                             normalizer_fn=None, weights_initializer=trunc_normal(0.001), scope='Conv2d_2b_1x1')                    if spatial_squeeze:                        # 进行squeeze操作,去除维数为1的维度                        aux_logits = tf.squeeze(aux_logits, [1, 2], name='SpatialSqueeze')                    end_points['AuxLogits'] = aux_logits            # 处理正常的分类预测            with tf.variable_scope('Logits'):                # 8x8的平均池化层                net = slim.avg_pool2d(net, [8, 8], padding='VALID', scope='AvgPool_1a_8x8')                # Dropout层                net = slim.dropout(net, keep_prob=dropout_keep_prob, scope='Dropout_1b')                end_points['PreLogits'] = net                logits = slim.conv2d(net, num_classes, [1, 1], activation_fn= None, normalizer_fn=None,scope='Conv2d_1c_1x1')                if spatial_squeeze:                    # 进行squeeze操作,去除维数为1的维度                    logits = tf.squeeze(logits, [1, 2], name='SpatialSqueeze')            # 辅助节点            end_points['Logits'] = logits            # 利用Softmax对结果进行分类预测            end_points['Predictions'] = prediction_fn(logits, scope='Predictions')    return logits, end_pointsimport mathfrom datetime import datetimeimport time# 评估每轮计算占用的时间# 输入TensorFlow的Session,需要测评的算子target,测试的名称info_stringdef time_tensorflow_run(session, target, info_string):    # 定义预热轮数(忽略前10轮,不考虑显存加载等因素的影响)    num_steps_burn_in = 10    total_duration = 0.0    total_duration_squared = 0.0    for i in range(num_batches + num_steps_burn_in):        start_time = time.time()        _ = session.run(target)        # 持续时间        duration = time.time()- start_time        if i >= num_steps_burn_in:            # 只考量10轮迭代之后的计算时间            if not i % 10:                print '%s: step %d, duration = %.3f' % (datetime.now().strftime('%X'), i - num_steps_burn_in, duration)            # 记录总时间            total_duration += duration            total_duration_squared += duration * duration    # 计算每轮迭代的平均耗时mn,和标准差sd    mn = total_duration / num_batches    vr = total_duration_squared / num_batches - mn * mn    sd = math.sqrt(vr)    # 打印出每轮迭代耗时    print '%s: %s across %d steps, %.3f +/- %.3f sec / batch' % (datetime.now().strftime('%X'), info_string, num_batches, mn, sd)# Inception V3运行性能测试if __name__ == '__main__':    batch_size = 32    height, width = 299, 299    inputs = tf.random_uniform((batch_size, height, width, 3))    with slim.arg_scope(inception_v3_arg_scope()):        # 传入inputs获取logits,end_points        logits, end_points = inception_v3(inputs, is_training=False)    # 初始化    init = tf.global_variables_initializer()    sess = tf.Session()    sess.run(init)    num_batches = 100    # 测试Inception V3的forward性能    time_tensorflow_run(sess, logits, 'Forward')

输出:

08:44:25: step 0, duration = 12.33508:46:28: step 10, duration = 12.28608:48:37: step 20, duration = 12.26008:50:40: step 30, duration = 12.25908:52:42: step 40, duration = 12.27508:54:47: step 50, duration = 12.41508:56:53: step 60, duration = 12.82408:59:38: step 70, duration = 17.70809:03:55: step 80, duration = 29.92109:08:59: step 90, duration = 37.04209:14:36: Forward across 100 steps, 18.237 +/- 8.856 sec / batch

GoogLeNet相关连接

论文连接:Going deeper with convolutions

Large Scale Visual Recognition Challenge 2014 (ILSVRC2014)

原创粉丝点击