Tensorflow实战:Inception_V3原理及实现(多注释)

       参考《Tensorflow实战》黄文坚,对Inception_V3进行了实现,增加了自己的理解,欢迎提问!!

       Inception_V3中使用了称为Inception model的结构,Inception model本身如同大网络中的小网络,其结构可以反复堆叠一起形成大大网络。

       Inception_V1结构如下图所示:

      人脑神经元的连接是稀疏的,因此研究者认为大型神经网络的合理连接方式应该也是稀疏的。稀疏结构是非常适合神经网络的一种结构,尤其对非常大型,非常深的网络,可以减轻过拟合并减少计算量,例如卷积神经网络就是稀疏的连接,Inception Net的目标就是找到最优的稀疏结构单元(Inception model)。

       Inception model的构建符合Hebbian原理, 简单介绍下Hebbian原理:神经反射活动的持续与重复会导致神经元稳定性的持久提升,当两个神经元A和B离的很近,并且A参与了B重复、持续的兴奋,那么某些代谢变化会导致A将作为能使B兴奋的细胞。总结一下即“一起发射的神经元会连接在一起”。在神经网络角度,即相关性高的节点应该被连接在一起。

       在图片数据中,天然的就是临近区域的数据相关性高,因此相邻的像素点被卷积操作连接在一起。而我们可能有多个卷积核,在同一位置但在不同通道输出的卷积核的输出结果相关性很高。因此一个1×1的卷积就可以很自然的将这些相关性很高的、在同一个空间位置但是不同通道的特征连接在一起,这就是为什么1×1卷积这么频繁的被应用在Inception Net中。

      1×1卷积所连接的的节点的相关性是很高的,而稍微大一些尺寸的卷积如3×3,5×5的相关性也很高,因此可以适当地使用一些以增加多样性。Inception model中一般有4个分支,包含不同尺寸地卷积和一个最大池化,增加了网络对不同尺寸的适应性。

      下图为Inception V3中三种结构的Inception model

本文的Inception_V3组织结构如下图所示:

     

本文使用Inception_V3的结构及参数,进行了前向计算的测评,代码及详细注释如下:

import tensorflow as tf
from datetime import datetime
import time
import math

'''############################################03《TensorFlow实战》实现Inception_V3##################################################'''

slim = tf.contrib.slim
trunc_normal = lambda stddev: tf.truncated_normal_initializer(0.0, stddev)

'''用来生成网络中经常用到的函数的默认参数,
比如卷积网络的激活函数、权重初始化方式、标准化器等,
因此后面定义一个卷积层将变得十分方便,可以用一行代码定义一个卷积层'''
def inception_v3_arg_scope(weight_decay=0.00004, stddev=0.1, batch_norm_var_collection='moving_vars'):

    batch_norm_params = {   #定义batch normalization的参数字典,见书P122的BN
        '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],
        }
    }

    '''slim.arg_scope工具,可以给函数的参数自动赋予某些默认的值
    使用了slim.arg_scope后就不需要每次都重复设置参数了,只需要在有修改时设置'''
    # 这句对slim.conv2d和slim.fully_connected的参数自动赋值,将参数weights_regularizer的值默认设为slim.l2_regularizer(weight_decay)
    with slim.arg_scope([slim.conv2d, slim.fully_connected],
                        weights_regularizer = slim.l2_regularizer(weight_decay)):
        #嵌套一个slim.arg_scope,对卷积层生成函数slim.conv2d的几个参数赋予默认值
        with slim.arg_scope(
            [slim.conv2d],
            weights_initializer = tf.truncated_normal_initializer(stddev=stddev),    #权重初始化器
            activation_fn = tf.nn.relu,     #激活函数
            normalizer_fn = slim.batch_norm,    #标准化器
            normalizer_params = batch_norm_params   #标准化器的参数
        ) as sc:
            return sc


'''生成Inception V3网络的卷积部分'''
def inception_v3_base(inputs, scope=None):  #inputs表示输入的图片数据的张量,scope为包含了函数默认参数的环境

    end_points = {} #字典表,用来保存某些关键节点供之后使用

    with tf.variable_scope(scope, 'InceptionV3', [inputs]):

        '''定义前几层的卷积池化层'''
        #使用slim.arg_scope对slim.conv2d, slim.max_pool2d, slim.avg_pool2d的参数设置默认值
        with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],    #卷积,最大池化,平均池化
                            stride=1, padding='VALID'): #步长默认设为1,padding默认为VALID

            #定义卷积层:slim.conv2d(inputs, 输出的通道数, 卷积核尺寸, 步长, padding模式)
            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')

        '''定义三个Inception模块组'''
        with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
                            stride=1, padding='SAME'):
            '''定义第一个Inception模块组,包含三个结构类似的Inception Module'''
            #第一个Inception模块组的第一个Inception Module,有4个分支,从Branch_0到Branch_3
            with tf.variable_scope('Mixed_5b'):
                #第一个分支
                with tf.variable_scope('Branch_0'):
                    branch_0 = slim.conv2d(net, 64, [1,1], scope='Conv2d_0a_1x1')
                #第二个分支
                with tf.variable_scope('Branch_1'):
                    branch_1 = slim.conv2d(net, 48, [1, 1], scope='Conv2d_0a_1x1')
                    branch_1 = slim.
  • 8
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值