CIFAR

"""CIFAR-10,60000张32*32的彩色图像,训练集5,0000张,测试集1,0000张,标注为10类
每一类图片6000张,airplane.automobile.bird.cat.deer.dog.frog.horse.ship.truck
trick1: 对weights L2正则化
trick2: 对图片进行了翻转。随机剪切等数据增强,制造了更多样本
trick3: 在每个卷积-最大池化层后面使用了LRN层,增加了模型的泛化能力
"""
import cifar10,cifar10_input
import tensorflow as tf
import numpy as np 
import time

max_steps=3000  #跑一遍测试集需要78个step;跑一遍训练集需要391个step
batch_size=128
data_dir='/tmp/cifar10_data/cifar-10-batches-bin'#下载CIFAR-10数据的默认路径

#L2是用来惩罚特征权重的,防止过拟合。即特征的权重也会成为损失函数的一部分从而筛选出最有效的特征
def variable_with_weight_loss(shape,stddev,wl):       #定义初始化weight的函数
    var= tf.Variable(tf.truncated_normal(shape,stddev=stddev))
    if wl is not None:
        weight_loss= tf.multiply(tf.nn.l2_loss(var),wl,name='weight_loss')
        tf.add_to_collection('losses',weight_loss)    #把'weight_loss'统一存到losses里面
    return var


#下载解压数据
cifar10.maybe_download_and_extract()
#tf.image.per_image_whitening对数据减去均值,除以方差,保证数据零均值,方差为1
image_train,labels_train= cifar10_input.distorted_inputs(
                                            data_dir= data_dir,batch_size= batch_size)
image_test,labels_test= cifar10_input.inputs(eval_data=True,
                                              data_dir= data_dir,
                                              batch_size=batch_size)  #得到batch,再传给holder
image_holder =tf.placeholder(tf.float32,[batch_size,24,24,3])
label_holder =tf.placeholder(tf.int32,[batch_size])


#创建第一个卷积层
#LRN只对RELU有用,对Sigmoid这种有固定边界并且能抑制过大值的激活函数没多大用,活跃的神经元对相邻神经元的抑制现象(侧抑制)
weight1= variable_with_weight_loss(shape=[5,5,3,64],stddev=5e-2,
                                   wl=0.0)     #weight loss=0,即不对第一个卷积层的weight进行L2的正则
kernel1= tf.nn.conv2d(image_holder,weight1,[1,1,1,1],padding='SAME')  #卷积操作,步长为1
bias1= tf.Variable(tf.constant(0.0,shape=[64]))
conv1= tf.nn.relu(tf.nn.bias_add(kernel1,bias1))
pool1=tf.nn.max_pool(conv1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')  #步长比池化核的尺寸小
norm1=tf.nn.lrn(pool1,4,bias=1.0,alpha=0.001/9.0,beta=0.75)#LOCAL RESPONSE NORMALIZATION


#创建第二个卷积层
weight2= variable_with_weight_loss(shape=[5,5,64,64],stddev=5e-2,
                                    wl=0.0)  #没有给weight加一个L2的loss,即没做正则化处理
kernel2= tf.nn.conv2d(norm1,weight2,[1,1,1,1],padding='SAME')
bias2= tf.Variable(tf.constant(0.1,shape=[64]))
conv2= tf.nn.relu(tf.nn.bias_add(kernel2,bias2))
norm2= tf.nn.lrn(conv2,4,bias=1.0,alpha=0.001/9.0,beta=0.75)
pool2= tf.nn.max_pool(norm2,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')


#全连接层1
# 使用一个get_shape函数,获取数据扁平化之后的长度,接着使用variable_with_weight_loss函数对全连接层的weight进行初始化,这里隐含节点数为384
reshape= tf.reshape(pool2,[batch_size,-1])   #变成一维的
dim = reshape.get_shape()[1].value           #获取reshape后的长度
weight3= variable_with_weight_loss(shape=[dim,384],stddev=0.04,wl=0.004)#shape[输入,输出]
bias3= tf.Variable(tf.constant(0.1,shape=[384]))
local3=tf.nn.relu(tf.matmul(reshape,weight3)+bias3)    


#也是全连接层2
# 隐含节点数192
weight4= variable_with_weight_loss(shape=[384,192],stddev=0.04,wl=0.004)
bias4= tf.Variable(tf.constant(0.1,shape=[192]))
local4= tf.nn.relu(tf.matmul(local3,weight4)+bias4) 


#最后一层
# 将这层的weight的正太分布标准差设为上一个隐含层的节点数的倒数,并且不计入L2的正则.
#计算softmax主要是为了计算loss,直接比较inference的输出的各类的数值大小即可.
weight5= variable_with_weight_loss(shape=[192,10],stddev=1/192.0,wl=0.0) 
bias5= tf.Variable(tf.constant(0.0,shape=[10]))      
logits= tf.add(tf.matmul(local4,weight5),bias5) #logits:模型Inference的输出结果


#计算CNN的loss
#这里依然使用cross entropy, 需要注意的是这里我们把softmax的计算与cross entropy loss的计算合在了一起,即tf.nn.sparse_softmax_cross_entropy_with_logits
#先用tf.reduce_mean对cross entropy 计算均值;再用tf.add_to_collection把cross entropy 的loss 添加至整体的loss.
#最后使用tf.add_n将整体的losses的collection中的全部loss求和,得到最终的loss
#其中包括cross entropy loss,还有后面两个全连接层中weight的L2 loss
def loss(logits,labels):
    labels= tf.cast(labels, tf.int64)
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
        logits=logits,labels=labels,name='cross_entropy_per_example')
    cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
    
    tf.add_to_collection('losses',cross_entropy_mean)  #移进collection

    return tf.add_n(tf.get_collection('losses'), name='total_loss') #进行累加

#接着将logits节点和label_placeholder传入loss函数,获得最终的loss
loss = loss( logits, label_holder)

#优化器选择Adam Optimizer,学习速率设为1e-3
train_op= tf.train.AdamOptimizer(1e-3).minimize(loss)
#使用tf.nn.in_top_k函数求输出结果中top k的准确率,默认使用top 1,也就是输出分数最高的那一类的准确率
top_k_op= tf.nn.in_top_k(logits,label_holder,1)


#然后使用tf.InteravtiveSession创建默认的session,接着初始化全部模型参数
sess= tf.InteractiveSession()
tf.global_variables_initializer().run()

tf.train.start_queue_runners()#启动图片数据增强的线程队列,(16)个线程


#每隔10个step会计算并展示当前的loss,每秒钟能训练的样本数量,以及训练一个batch所花费的时间
for step in range(max_steps):  #如果max_steps比较大,推荐使用学习速率衰减(decay)的SGD进行训练
    start_time=time.time()
    image_batch,label_batch =sess.run([image_train,labels_train])
    _, loss_value= sess.run([train_op, loss],
                            feed_dict={image_holder:image_batch, label_holder:label_batch})
    duration = time.time()-start_time
    if step % 10 ==0:
        examples_per_sec= batch_size / duration
        sec_per_batch= float(duration)   #一个batch对应一个duration

        format_str= ('step %d,loss=%.2f(%.1f examples/sec; %.3f sec/batch)')
        print(format_str % (step,loss_value,examples_per_sec,sec_per_batch))


#接下来评测模型在测试集上的准确率
num_examples=10000
import math
num_iter = int (math.ceil(num_examples/batch_size))
true_count=0 #初始化为0
total_sample_count =num_iter* batch_size
step=0
while step < num_iter:
    image_batch,label_batch =sess.run([image_test,labels_test])
    predictions= sess.run([top_k_op],feed_dict={image_holder:image_batch,
                                                label_holder:label_batch })  #计算模型在这个batch的top 1上预测正确的样本数,最后汇总所有预测正确的结果
    true_count +=np.sum(predictions)
    step +=1

#最后将准确率的测评结果计算并打印出来
precision = true_count / total_sample_count
print('precision @ 1 =%.3f' %precision)


"""
提升模型的泛化性
lrn一般在卷积层之后的conv与pool
l2一般在fc层计算weight loss值
"""

你可能感兴趣的:(CIFAR)