AlexNet包含6亿3000万个连接,6000万个参数和65万个神经元,拥有5个卷积层,其中3个卷积层后面连接了最大池化层,最后还有3个全连接层。
AlexNet将LeNet的思想发扬光大,主要用到的新技术如下:
(1)成功使用ReLU作为CNN的激活函数,并验证其效果再较深的网络中超过Sigmoid,成功解决了Sigmoid在网络较深时的梯度弥散问题。
(2)训练时使用Dropout随即忽略一部分神经元,以避免模型过拟合。
(3)在CNN只使用重叠的最大池化。
(4)提出LRN层,提出了LRN层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
(5)提出了 AlexNet层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
(6)数据增强,随机地从256*256的原始图像中截取224*224大小的区域(以及水平翻转的镜像),相当于增加了2*(256-224)^2=2048倍的数据量。如果没有数据增强,仅靠原始的数据量,参数众多的CNN会陷入过拟合中,使用了数据增强后可以大大减轻过拟合,提升泛化能力。进行预测时,则是取图片的四个角加中间共5个位置,并进行左右翻转,一共获得10张图片,对他们进行预测并对10次结果求均值。同时,AlexNet论文中提到了会对图像的RGB数据进行PCA处理,并对主成分做一个标准差为0.1的高斯扰动,增加一些噪声,这个Trick可以让错误率再下降1%。
整个 AlexNet有8个需要训练参数的层,前5层为卷积层,后3层为全连层, LRN层出现在第一个及第二个卷积层后,最大池化层出现在两个 LRN层及最后一个卷积层后。ReLU激活函数则应用在这8层每一层的后面。如图所示: AlexNet
AlexNet每层的参数如图:其中输入的图片尺寸为224*224,第一个卷积层使用的卷积核尺寸为11*11,步长为4,有96个卷积核,紧接着一个LRN层,然后一个3*3的最大池化层,步长为2,之后的卷积核尺寸都比较小,都是5*5或者3*3的大小,并且步长都为1。
因为使用ImageNet数据训练一个完整的AlexNet耗时长,所以下面不涉及实际数据的训练。建立一个完整的AlexNet卷积神经网络, 然后对他每个batch的前馈计算forward和反馈计算backward的速度进行测试。
先导入接下来会用到的库:
from datetime import datetime
import math
import tensorflow as tf
import time
总共测试100个batch的数据:
batch_size=32
num_batches=100
定义显示网络每一层结构的函数print_actications, 展示每一个卷积层或池化层输出tensor的尺寸,
def print_activations(t):
print(t.op.name,' ',t.get_shape().as_list())
接下来设计AlexNet的网络结构:
def inference(images):
parameters=[]
with tf.name_scope('conv1') as scope:
kernel=tf.Variable(tf.truncated_normal([11,11,3,64],
dtype=tf.float32,stddev=1e-1),name='weights')
conv=tf.nn.conv2d(images,kernel,[1,4,4,1],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]
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')
print_activations(pool1)
with tf.name_scope('conv2') as scope:
kernel=tf.Variable(tf.truncated_normal([5,5,64,192],
dtype=tf.float32,stddev=1e-1),name='weights')
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')
bias=tf.nn.bias_add(conv,biases)
conv2=tf.nn.relu(bias,name=scope)
parameters +=[kernel,biases]
print_activations(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')
print_activations(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='weights')
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')
bias=tf.nn.bias_add(conv,biases)
conv3=tf.nn.relu(bias,name=scope)
parameters +=[kernel,biases]
print_activations(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='weights')
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')
bias = tf.nn.bias_add(conv, biases)
conv4 = tf.nn.relu(bias, name=scope)
parameters += [kernel, biases]
print_activations(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='weights')
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')
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=[1,3,3,1],strides=[1,2,2,1],
padding='VALID',name='pool5')
print_activations(pool5)
return pool5,parameters
def time_tensorflow_run(session,target,info_string):
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:
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_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(),info_string,num_batches,mn,sd))
接下来是主函数run_benchmark:
def run_benchmark():
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,parameters=inference(images)
init=tf.global_variables_initializer()
sess=tf.Session()
sess.run(init)
time_tensorflow_run(sess,pool5,"Forward")
objective=tf.nn.l2_loss(pool5)
grad=tf.gradients(objective,parameters)
time_tensorflow_run(sess,grad,"Forward-backward")
run_benchmark()
conv1 [32, 56, 56, 64]
pool1 [32, 27, 27, 64]
conv2 [32, 27, 27, 192]
pool2 [32, 13, 13, 192]
conv3 [32, 13, 13, 384]
conv4 [32, 13, 13, 256]
conv5 [32, 13, 13, 256]
pool5 [32, 6, 6, 256]
2018-11-21 20:02:46.049800:step 0,duration=0.270
2018-11-21 20:02:48.779797:step 10,duration=0.260
2018-11-21 20:02:51.489796:step 20,duration=0.270
2018-11-21 20:02:54.199795:step 30,duration=0.280
2018-11-21 20:02:56.904185:step 40,duration=0.270
2018-11-21 20:02:59.624187:step 50,duration=0.270
2018-11-21 20:03:02.344184:step 60,duration=0.270
2018-11-21 20:03:05.064195:step 70,duration=0.270
2018-11-21 20:03:07.784187:step 80,duration=0.270
2018-11-21 20:03:10.584184:step 90,duration=0.290
2018-11-21 20:03:13.264184:Forward across 100 steps,0.027 +/- 0.082 sec /batch
2018-11-21 20:03:26.464180:step 0,duration=1.190
2018-11-21 20:03:38.424179:step 10,duration=1.210
2018-11-21 20:03:50.394177:step 20,duration=1.200
2018-11-21 20:04:02.374176:step 30,duration=1.180
2018-11-21 20:04:14.324174:step 40,duration=1.190
2018-11-21 20:04:26.277548:step 50,duration=1.190
2018-11-21 20:04:38.256889:step 60,duration=1.190
2018-11-21 20:04:50.179339:step 70,duration=1.190
2018-11-21 20:05:02.580086:step 80,duration=1.307
2018-11-21 20:05:14.734489:step 90,duration=1.220
2018-11-21 20:05:25.551670:Forward-backward across 100 steps,0.121 +/- 0.362 sec /batch
参考文献:
Tensorflow实战( 黄文坚)