用tensorflow实现AlexNet网络

AlexNet网络:

2012年,Alex...提出了深度学习卷积神经网络模型Alexnet,其中包含了几个当时新颖的技术点。获得了2012年ILSVRC比赛第一名。Alexnet主要使用的技术点如下:

1.成功使用ReLU作为卷积神经网络的激活函数,验证了在深层卷积神经网络的效果超过Sigmoid,成功解决Sigmoid在网络较深层神经网络的梯度消失问题。

2.训练使用dropout,忽略一部分神经元,以避免过拟合。主要是在最后的几个全连接层使用了dropout。

3.LRN层(Local Response Normalization),提升泛化能力。实际上好像没什么用。而且还降低训练速度。

4.使用最大池化,避免了平均池化的模糊效果,另外提出了让步长比池化核小的最大池化方法。可以保证池化出的特征有重叠,提升特征的丰富性。

5.数据增强,随机从256*256的原始图像中随机截取224*224大小的区域(并进行水平翻转)这个操作相当于把数据量曾加了(256-224)*(256*224)*2倍=2048倍。如果没有数据增强,只靠原始的数据量,众多的参数会陷入过拟合中。使用数据增强同业可以提高泛化能力。

额 

第一个卷积层使用了较大的卷积核尺寸11*11,步长为4,有96个卷积核;然后是有个3*3步长为2的池化层。只有第一层卷积核比较大,后面的几层卷积核都比较小,都是5*5或者3*3的卷积核。

#首先导入几个需要使用的库
from datetime import datetime
import math
import time
import tensorflow as tf
#这里设置一个batch为30,共100个batch的数据
batch_size = 32
num_batch  = 100
#定义了一个可以打印每一层的名称(t.op.name)并以列表的方式打印输入尺寸信息
def print_activation(t):
    print(t.op.name,'\n',t.get_shape().as_list())

#设计网络结构,以图片作为输入,返回pool5和所有需要训练的模型参数
def Alexnet_structure(images):
    #定义一个列表
    parameters = []
    #定义第一层卷积层
    #可以将scope段内所有定义的变量自动命名为conv1/xxx
    with tf.name_scope('conv1') as scope:
        #第一层的卷积核,11*11*3,共64个,tf.truncated_normal一种设置正态分布的方法
        kernel = tf.Variable(tf.truncated_normal([11,11,3,64],dtype=tf.float32,stddev=1e-1),name='weigths')
        #设置第一层卷积层,卷积核是上面初始化后的卷积核,步长为4,4,填充为SAME
        conv   = tf.nn.conv2d(images,kernel,[1,4,4,1],padding='SAME')
        #设置第一层的偏置,初始值为0
        biases = tf.Variable(tf.constant(0.0,shape=[64],dtype=tf.float32),trainable=True,name='biases')
        #设置w*x+b,之后用激活函数处理。作为第一层的输出
        W_x_plus_b   = tf.nn.bias_add(conv,biases)
        conv1  = tf.nn.relu(W_x_plus_b,name=scope)
        #启用最开始定义的打印层信息的函数,把输出尺寸打印出来
        print_activation(conv1)
        parameters += [kernel,biases]
        #LRN层个人感觉与PCA的效果差不多,PCA实现的是降维,把主要的特征保留
        # LRN实现的是将主要特征的贡献放大,将不重要的特征缩小
        #由于效果并不明显,且运行速度回慢三倍,很多神经网络已经放弃了加入LRN层
        #lrn1=tf.nn.lrn(conv1,4,bias=1.0,alpha=0.001/9,beta=0.75,name='lrn1')
        #pool1=tf.nn.max_pool(lrn1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='VALID',name='pool1')
        pool1=tf.nn.max_pool(conv1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='VALID',name='pool1')
        print_activation(pool1)

    #定义第二个网络层
    with tf.name_scope('conv2')as scope:
        #定义卷积核5*5,192个,
        kernel = tf.Variable(tf.truncated_normal([5,5,64,192],dtype=tf.float32,stddev=1e-1),name='weigtths')
        #定义了一个卷积操作,步长为1,经过这次卷积后图像尺寸大小没有改变
        conv   = tf.nn.conv2d(pool1, kernel, [1, 1, 1, 1], padding='SAME')
        biases = tf.Variable(tf.constant(0.0,shape=[192],dtype=tf.float32),trainable=True,name='biases')
        W_x_plus_b   = tf.nn.bias_add(conv, biases)
        #同样用了relu激活函数
        conv2  = tf.nn.relu(W_x_plus_b, name=scope)
        parameters += [kernel, biases]
        print_activation(conv2)
        #lrn2  = tf.nn.lrn(conv2, 4, bias=1.0, alpha=0.001 / 9, beta=0.75, name='lrn2')
        #pool2 = tf.nn.max_pool(lrn2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool2')
        #池化层,3*3,步长为2,2,池化后由 [32, 27, 27, 192]--->[32, 13, 13, 192]
        #这个每一层第一个参数欧式32,这个是batch_size,即每次送入的图片的数目
        pool2 = tf.nn.max_pool(conv2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool2')
        print_activation(pool2)

    #定义第三层卷积层
    with tf.name_scope('conv3')as scope:
        kernel = tf.Variable(tf.truncated_normal([3, 3, 192, 384], dtype=tf.float32, stddev=1e-1), name='weigtths')
        conv   = tf.nn.conv2d(pool2, kernel, [1, 1, 1, 1], padding='SAME')
        biases =tf.Variable(tf.constant(0.0,shape=[384],dtype=tf.float32),trainable=True,name='biases')
        W_x_plus_b   = tf.nn.bias_add(conv, biases)
        conv3  = tf.nn.relu(W_x_plus_b, name=scope)
        parameters += [kernel, biases]
        print_activation(conv3)

    #定义第四层卷积层
    with tf.name_scope('conv4')as scope:
        kernel = tf.Variable(tf.truncated_normal([3, 3, 384, 256], dtype=tf.float32, stddev=1e-1), name='weigtths')
        conv   = tf.nn.conv2d(conv3, kernel, [1, 1, 1, 1], padding='SAME')
        biases = tf.Variable(tf.constant(0.0,shape=[256],dtype=tf.float32),trainable=True,name='biases')
        W_x_plus_b   = tf.nn.bias_add(conv, biases)
        conv4  = tf.nn.relu(W_x_plus_b, name=scope)
        parameters += [kernel, biases]
        print_activation(conv4)

    #定义第五层卷积层
    with tf.name_scope('conv5')as scope:
        kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 256], dtype=tf.float32, stddev=1e-1), name='weigtths')
        conv   = tf.nn.conv2d(conv4, kernel, [1, 1, 1, 1], padding='SAME')
        biases = tf.Variable(tf.constant(0.0,shape=[256],dtype=tf.float32),trainable=True,name='biases')
        W_x_plus_b   = tf.nn.bias_add(conv, biases)
        conv5  = tf.nn.relu(W_x_plus_b, name=scope)
        parameters += [kernel, biases]
        print_activation(conv5)
        #根据原网络设计,第五层卷积层后紧跟一个池化层
        pool5  = tf.nn.max_pool(conv5, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool5')
        print_activation(pool5)
        return pool5,parameters

#评估Alexnet每轮计算时间的函数
def time_Alexnet_run(session,target,info_string):
    num_steps_burn_in = 10
    total_duration    = 0.0
    total_duration_squared = 0.0
    for i in range(num_batch+num_steps_burn_in):
        start_time = time.time()
        tar = session.run(target)
        duration = time.time()-start_time
        if i >= num_steps_burn_in:
            if not i%10:
                print('%s:step %d,duration=%.3f'%(datetime.now(),i-num_steps_burn_in,duration))
            total_duration+=duration
            total_duration_squared+=duration*duration
    mn=total_duration/num_batch
    vr=total_duration_squared/num_batch-mn*mn
    sd=math.sqrt(vr)
    print('%s:s% accoss %d steps,%.3f +/-%.3f sec/batch ' % (datetime.now(), info_string,num_batch,mn,sd))

#主函数
def main():
    with tf.Graph().as_default():
        image_size = 224
        images = tf.Variable(tf.random_normal([batch_size,image_size,image_size,3],dtype=tf.float32,stddev=1e-1))
        pool5 , parmeters = Alexnet_structure(images)
        #初始化所有变量
        init   =  tf.global_variables_initializer()
        sess   =  tf.Session()
        sess.run(init)
        #统计计算时间
        time_Alexnet_run(sess,pool5,"Forward")
        objective = tf.nn.l2_loss(pool5)
        grad      = tf.gradients(objective,parmeters)
        time_Alexnet_run(sess,grad,"Forward-backward")
        print(len(parmeters))

main()

参考书籍:《Tensorflow实战》黄文坚,唐源,电子工业出版社,第六章。

猜你喜欢

转载自blog.csdn.net/Dongjiuqing/article/details/84191313