你好,游客 登录
背景:
阅读新闻

TensorFlow实战之实现AlexNet经典卷积神经网络

[日期:2018-02-27] 来源:网络  作者: [字体: ]

本文已同步本人另外一个博客(http://blog.csdn.net/qq_37608890/article/detAIls/79371347)

本文根据最近学习TensorFlow书籍网络文章的情况,特将一些学习心得做了总结,详情如下.如有不当之处,请各位大拿多多指点,在此谢过。

一、AlexNet模型及其基本原理阐述

1、关于AlexNet

2012年,AlexKrizhevsky提出了深度卷积神经网络模型AlexNet,可以看作LeNet的一种更深更宽的版本。该模型包含了6亿3000万个连接,6000万个参数和65万个神经元,拥有5个卷积层,其中3个卷积层后面连接了最大池化层,最后还有3个全连接层。它将LeNet的思想得到更广泛的传播,把把CNN的基本原理应用到很深很宽的网络中。

2、AlexNet主要使用到的新技术点

(1)成功使用RelU作为CNN的激活函数,并验证其效果在较深的网络超过Sigmoid函数,成功解决了Sigmoid函数在网络较深时梯度弥散问题。

(2)训练时使用Droupout随机忽略一部分神经元,以避免出现模型过拟合。

(3) 在CNN中使用重叠的最大池化。

(4) 提出了LRN层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。

(5) 使用CUDA加速深度卷积网络的训练,利用GPU强大的并行计算能力,处理神经网络训练时大量的矩阵运算。

(6) 数据增强,随机地从256*256的原始图像中截取224*224大小的区域(以及水平翻转的镜像),相当于增加了(256-224)^2=2048倍的数据量。

3、原理阐释

整个AlexNet包括8个需要训练参数的层(不含LRN和池化层),前5层为卷积层,后3层为全连接层,如图1所示。AlexNet最后一层是有1000类输出的Softmax层用作分类。LRN层出现在第1个及第2个卷积层后,而最大池化层出现在两个LRN层及最后一个卷积层后。RelU激活函数则应用在这8层每一层的后面。

 

图1AlexNet的网络结构

AlexNet每层的超参数如图1所示,其中输入的图片尺寸为224*224,第一个卷积层使用了较大的卷积核尺寸11*11,步长为4,有96个卷积核;然后是一个LRN层;再往后是一个3*3的最大池化层,步长为2。再往后的卷积核尺寸都比较小,基本都是5*5或3*3的大小,且步长都是1,即会扫描全图像所有像素;而最大池化层依然保持为3*3,步长为2。

这里不难发现,前几个卷积层里面,虽然计算量很大,但参数量很小,基本都在1M左右甚至更小,只占AlexNet总参数量很小一部分。这也是卷积层的价值所在:通过较小的参数量提取有效的特征。

如果前几层直接使用全连接层,则参数量和计算量将会难以想象。尽管每一个卷积层只占整个网络参数量的1%不到,但如果抛弃任何一个卷积层,都会迫使整个网络的分类能力大幅度下降。

图1中特殊的地方是卷积部分都是画成上下两块,意思是说把这一层计算出来的featuremap分开,但是前一层用到的数据要看连接的虚线,如图中input层之后的第一层第二层之间的虚线是分开的,是说二层上面的128map是由一层上面的48map计算的,下面同理;而第三层前面的虚线是完全交叉的,就是说每一个192map都是由前面的128+128=256map同时计算得到的。

Alexnet有一个特殊的计算层,LRN层,做的事是对当前层的输出结果做平滑处理,图2所示:

图2

前后几层(对应位置的点)对中间这一层做一下平滑约束,计算方法如下:

 

二、经典卷积神经网络AlexNet模型实现过程

1、简要说明

因为使用ImageNet数据集训练一个完整的AlexNet非常耗时,这里AlexNet的实现将不涉及实际数据的训练,但会创建一个完整的AlexNet卷积神经网络,然后对它每个batch的前馈计算(forward)和反馈计算(backward)的速度进行测试。下面使用随机图片数据来计算每轮前馈、反馈的平均耗时。当然,读者也可以自行下载ImageNet数据完成训练并测试。

2、实现过程

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165

==============================================================================fromdatetime importdatetimeimportmathimporttimeimporttensorflow as tf#这里总共测试100个batch的数据。batch_size=32num_batches=100#定义一个用来显示网络每一层结构的函数print_activations,展示每一个卷积层或池化层输出的tensor尺寸。defprint_activations(t):print(t.op.name, ' ', t.get_shape().as_list())#设计AlexNet网络结构。#设定inference函数,用于接受images作为输入,返回最后一层pool5(第5个池化层)及parameters(AlexnNet中所有需要训练的模型参数)#该函数包括多个卷积层和池化层。definference(images):parameters =[]# 第1个卷积层with tf.name_scope('conv1') as scope:kernel =tf.Variable(tf.truncated_normal([1111364], dtype=tf.float32,stddev=1e-1), name='weights')conv =tf.nn.conv2d(images, kernel, [1441], padding='SAME')biases =tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32),trainable=True, name='biases')bias =tf.nn.bias_add(conv, biases)conv1 =tf.nn.relu(bias, name=scope)print_activations(conv1)parameters +=[kernel, biases]# 添加LRN层和最大池化层lrn1 =tf.nn.lrn(conv1, 4, bias=1.0, alpha=0.001/9.0, beta=0.75, name='lrn1')pool1 =tf.nn.max_pool(lrn1,ksize=[1331],strides=[1221],padding='VALID',name='pool1')print_activations(pool1)# 设计第2个卷积层with tf.name_scope('conv2') as scope:kernel =tf.Variable(tf.truncated_normal([5564192], dtype=tf.float32,stddev=1e-1), name='weights')conv =tf.nn.conv2d(pool1, kernel, [1111], padding='SAME')biases =tf.Variable(tf.constant(0.0, shape=[192], dtype=tf.float32),trainable=True, name='biases')bias =tf.nn.bias_add(conv, biases)conv2 =tf.nn.relu(bias, name=scope)parameters +=[kernel, biases]print_activations(conv2)# 对第2个卷积层的输出进行处理,同样也是先做LRN处理再做最大化池处理。lrn2 =tf.nn.lrn(conv2, 4, bias=1.0, alpha=0.001/9.0, beta=0.75, name='lrn2')pool2 =tf.nn.max_pool(lrn2,ksize=[1331],strides=[1221],padding='VALID',name='pool2')print_activations(pool2)# 设计第3个卷积层with tf.name_scope('conv3') as scope:kernel =tf.Variable(tf.truncated_normal([33192384],dtype=tf.float32,stddev=1e-1), name='weights')conv =tf.nn.conv2d(pool2, kernel, [1111], padding='SAME')biases =tf.Variable(tf.constant(0.0, shape=[384], dtype=tf.float32),trainable=True, name='biases')bias =tf.nn.bias_add(conv, biases)conv3 =tf.nn.relu(bias, name=scope)parameters +=[kernel, biases]print_activations(conv3)# 设计第4个卷积层with tf.name_scope('conv4') as scope:kernel =tf.Variable(tf.truncated_normal([33384256],dtype=tf.float32,stddev=1e-1), name='weights')conv =tf.nn.conv2d(conv3, kernel, [1111], padding='SAME')biases =tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),trainable=True, name='biases')bias =tf.nn.bias_add(conv, biases)conv4 =tf.nn.relu(bias, name=scope)parameters +=[kernel, biases]print_activations(conv4)# 设计第5个卷积层with tf.name_scope('conv5') as scope:kernel =tf.Variable(tf.truncated_normal([33256256],dtype=tf.float32,stddev=1e-1), name='weights')conv =tf.nn.conv2d(conv4, kernel, [1111], padding='SAME')biases =tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),trainable=True, name='biases')bias =tf.nn.bias_add(conv, biases)conv5 =tf.nn.relu(bias, name=scope)parameters +=[kernel, biases]print_activations(conv5)# 最大池化层pool5 =tf.nn.max_pool(conv5,ksize=[1331],strides=[1221],padding='VALID',name='pool5')print_activations(pool5)returnpool5, parameters#构建函数time_tensorflow_run,用来评估AlexNet每轮计算时间。deftime_tensorflow_run(session, target, info_string):num_steps_burn_in =10total_duration =0.0total_duration_squared =0.0forinrange(num_batches +num_steps_burn_in):start_time =time.time()=session.run(target)duration =time.time() -start_timeifi >=num_steps_burn_in:ifnot%10:print('%s: step %d, duration = %.3f'%(datetime.now(), i -num_steps_burn_in, duration))total_duration +=durationtotal_duration_squared +=duration *durationmn =total_duration /num_batchesvr =total_duration_squared /num_batches -mn *mnsd =math.sqrt(vr)print('%s: %s across %d steps, %.3f +/- %.3f sec / batch'%(datetime.now(), info_string, num_batches, mn, sd))#主函数defrun_benchmark():with tf.Graph().as_default():image_size =224images =tf.Variable(tf.random_normal([batch_size,image_size,image_size, 3],dtype=tf.float32,stddev=1e-1))pool5, parameters =inference(images)init =tf.global_variables_initializer()config =tf.ConfigProto()config.gpu_options.allocator_type ='BFC'sess =tf.Session(config=config)sess.run(init)time_tensorflow_run(sess, pool5, "Forward")objective =tf.nn.l2_loss(pool5)grad =tf.gradients(objective, parameters)# Run the backward benchmark.time_tensorflow_run(sess, grad, "Forward-backward")#执行主函数run_benchmark()

3、执行结果分析

这里有三部分如下:

首先是AlexNet的网络结构 

12345678

conv1 [32565664]pool1 [32272764]conv2 [322727192]pool2 [321313192]conv3 [321313384]conv4 [321313256]conv5 [321313256]pool5 [3266256]

其次是Forward运行的时间。

1234567891011

2018-02-2608:08:01.966903: step 0, duration =0.9142018-02-2608:08:11.376824: step 10, duration =0.9392018-02-2608:08:21.075799: step 20, duration =0.9532018-02-2608:08:30.983637: step 30, duration =0.9302018-02-2608:08:40.616086: step 40, duration =0.9382018-02-2608:08:50.259619: step 50, duration =0.9652018-02-2608:09:01.280123: step 60, duration =1.1282018-02-2608:09:11.993487: step 70, duration =0.9982018-02-2608:09:22.223815: step 80, duration =0.9352018-02-2608:09:31.741528: step 90, duration =0.9212018-02-2608:09:40.085934: Forward across 100steps, 0.990+/-0.082sec /batch

最后是backward运行的时间。

1234567891011

2018-02-2608:10:19.714161: step 0, duration =3.3872018-02-2608:10:55.765137: step 10, duration =3.4952018-02-2608:11:32.451839: step 20, duration =4.1892018-02-2608:12:07.982546: step 30, duration =3.3692018-02-2608:12:43.531404: step 40, duration =3.4152018-02-2608:13:18.980045: step 50, duration =3.4702018-02-2608:13:54.535575: step 60, duration =3.3712018-02-2608:14:29.413705: step 70, duration =3.6552018-02-2608:15:06.147061: step 80, duration =3.5832018-02-2608:15:43.403758: step 90, duration =3.9212018-02-2608:16:16.511215: Forward-backward across 100steps, 3.602+/-0.237sec /batch

三、小结

AlexNet为卷积神经网络和深度学习正名,为复兴神经网络做出了很多贡献,当然,超大型的数据集ImageNet也给深度学习带来了很大贡献。训练深度卷积神经网络,必须要有一个类似于ImageNet这样超大型数据集才能避免出现过拟合现象,从而更能体现深度学习的优势所在。因此,传统机器学习模型更适合一个小型数据集,在面对大型数据集时,需要更大学习容量的模型,那就是深度学习模型。

深度学习的参数不一定比传统机器学习模型多,尤其是在卷积层使用的参数量一般都比较少,但其抽取特征的能力非常强悍,这是CNN之所以有效的原因。

收藏 推荐 打印 | 录入:Cstor | 阅读:
相关新闻      
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款