1.代码实现
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 14 17:13:05 2018 @author: zhen
""" from datetime import datetime
import math
import time
import tensorflow as tf batch_size = 32
num_batchs = 100 def print_activations(t):
print(t.op.name, " ", t.get_shape().as_list()) 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, depth_radius=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, 128], 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=[128], 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, 128, 256], 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=[256], 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, 256, 128], 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=[128], 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, 128, 128], 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=[128], 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 # 评估AlexNet每轮计算时间
def fit_date(session, target, info_string):
num_steps_burn_in = 10 # 初始计算轮数
total_duration = 0.0
total_duration_squared = 0.0 for i in range(num_batchs + 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_batchs
vr = total_duration_squared / num_batchs - mn * mn
sd = math.sqrt(vr)
print('%s:%s across %d steps,%.3f +/- %.3f sec / batch'%(datetime.now(), info_string, num_batchs, mn, sd)) def fit_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) fit_date(sess, pool5, "Forward")
objective = tf.nn.l2_loss(pool5)
grad = tf.gradients(objective, parameters)
fit_date(sess, grad, "Forward-backward") fit_benchmark()
2.结果
conv1 [32, 56, 56, 64]
pool1 [32, 27, 27, 64]
conv2 [32, 27, 27, 128]
pool2 [32, 13, 13, 128]
conv3 [32, 13, 13, 256]
conv4 [32, 13, 13, 128]
conv5 [32, 13, 13, 128]
pool5 [32, 6, 6, 128]
2019-01-27 10:51:37.551617:step 0, duration=1.625
2019-01-27 10:51:54.082824:step 10, duration=1.766
2019-01-27 10:52:10.582787:step 20, duration=1.641
2019-01-27 10:52:27.051502:step 30, duration=1.672
2019-01-27 10:52:43.507558:step 40, duration=1.625
2019-01-27 10:52:59.913772:step 50, duration=1.625
2019-01-27 10:53:16.245750:step 60, duration=1.672
2019-01-27 10:53:32.511337:step 70, duration=1.625
2019-01-27 10:53:48.901938:step 80, duration=1.609
2019-01-27 10:54:05.183145:step 90, duration=1.625
2019-01-27 10:54:19.917492:Forward across 100 steps,1.640 +/- 0.031 sec / batch
2019-01-27 10:55:47.146016:step 0, duration=7.719
2019-01-27 10:57:04.602639:step 10, duration=7.766
2019-01-27 10:58:26.594245:step 20, duration=9.842
2019-01-27 11:00:01.957195:step 30, duration=8.391
2019-01-27 11:01:35.103007:step 40, duration=10.073
2019-01-27 11:03:07.656318:step 50, duration=8.988
2019-01-27 11:04:31.844207:step 60, duration=8.590
2019-01-27 11:06:01.173490:step 70, duration=9.422
2019-01-27 11:07:28.737373:step 80, duration=10.635
2019-01-27 11:09:03.830375:step 90, duration=8.653
2019-01-27 11:10:19.836018:Forward-backward across 100 steps,8.804 +/- 0.817 sec / batch
3.分析
1、AlexNet是比赛分类项目的2012年冠军,top5错误率16.4%,8层神经网络。
2、AlexNet中包含了几个比较新的技术点,首次在CNN中成功应用了Relu、Dropout、 Lrn等Trick。
3、运用Relu,解决Sigmoid在网络层次较深时的梯度弥散。
4、训练Dropout,随机忽略一些神经元,避免过拟合。
5、使用重叠的最大池化,此前CNN普遍平均池化,最大池化避免平均池化的模糊化效果。
6、提出了Lrn层,局部神经元活动创建竞争机制,响应比较大的值变得更大,抑制其他反馈小的神经元,增强泛化能力。
7、数据增强,随机地从256*256的原始图像中截取224*224大小的区域,以及水平翻转的镜像,相当于增加了【(256-224)^2】*2=2048倍的数据量。
注意:没有数据增强,仅靠原始的数据量,参数众多的CNN会陷入过拟合中。