赞
踩
2012年,Alex...提出了深度学习卷积神经网络模型Alexnet,其中包含了几个当时新颖的技术点。获得了2012年ILSVRC比赛第一名。Alexnet主要使用的技术点如下:
1.成功使用ReLU作为卷积神经网络的激活函数,验证了在深层卷积神经网络的效果超过Sigmoid,成功解决Sigmoid在网络较深层神经网络的梯度消失问题。
2.训练使用dropout,忽略一部分神经元,以避免过拟合。主要是在最后的几个全连接层使用了dropout。
3.LRN层(Local Response Normalization),提升泛化能力。实际上好像没什么用。而且还降低训练速度。效果我个人认为类似于PCA(主成分分析),不同的是PCA降低了特征的维度,保留了较为重要的特征。而LRN是吧重要的特征变得更重要,不重要的特征所占的比重变小。
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实战》黄文坚,唐源,电子工业出版社,第六章。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。