TensorFlow实现Cifar-10数据集训练

from models.tutorials.image.cifar10 import cifar10,cifar10_input
import tensorflow as tf
import time
# -----------定义常量-------------------
max_steps = 3000
batch_size = 128
data_dir = 'cifar-10-batches-bin'

L2范式:对模型进行正则化,增加一个正则化项,正则化项是模型复杂度的单调递增函数,模型越复杂正则化项就越大。可以防止参数过多模型过于复杂导致的过拟合现象。L2范数为1/||w||**2。

tf.nn.l2_loss(t, name=None)

解释:这个函数的作用是利用 L2 范数来计算张量的误差值,但是没有开方并且只取 L2 范数的值的一半,具体如下:

output = sum(t ** 2) / 2

使用tf.multiply()将w1与L2范式相乘来控制正则化的大小。使用collection将loss值存储在loss集合中.

# ---------------定义初始化函数--------------

def variable_with_weight_loss(shape,stddev,w1):
    var = tf.Variable(tf.truncated_normal(shape,stddev=stddev))
    if w1 is not None:
        weight_loss = tf.multiply(tf.nn.l2_loss(var),w1,name='weight_loss')
        tf.add_to_collection('losses',weight_loss)
    return var
# --------------生成训练数据和测试数据-----------------
image_train,label_train = cifar10_input.distorted_inputs(data_dir=data_dir,batch_size=batch_size)
image_test,lable_test = cifar10_input.inputs(eval_data=True,data_dir=data_dir,batch_size=batch_size
# ----------------创建输入数据的placeholder-----------
image_holder = tf.placeholder(tf.float32,[batch_size,24,24,3])
lable_holder = tf.placeholder(tf.int32,[batch_size])

LRN函数类似DROPOUT和数据增强作为relu激励之后防止数据过拟合而提出的一种处理方法,全称是 local response normalization--局部响应标准化。这个函数很少使用,基本上被类似DROPOUT这样的方法取代.

计算卷积后的大小为(n+2p-f/s)+1其中n为上一层的长宽,p为padding的大小,f为过滤器的大小,s为步长。

此项目的神经网络结构为:卷积-》池化-》LRN-》卷积-》LRN-》池化-》全链接-》全链接-》全链接

# ---------------创建第一个卷积层-----------------
weight1 = variable_with_weight_loss(shape=[5,5,3,64],stddev=5e-2,w1=0.0)
kernel1 = tf.nn.conv2d(image_holder,weight1,[1,1,1,1],padding="SAME")
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")
# ####使用LRN处理结果
norm1 = tf.nn.lrn(pool1,4,bias=1.0,alpha=0.001/9.0,beta=0.75)
# --------------创建第二个卷积层-------------------
weight2 = variable_with_weight_loss(shape=[5,5,64,64],stddev=5e-2,w1=0.0)
kernel2 = tf.nn.conv2d(norm1,weight2,strides=[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")
# -----------------创建第一个全链接层-------------------
reshape = tf.reshape(pool2,[batch_size,-1])
dim = reshape.get_shape()[1].value
weight3 = variable_with_weight_loss(shape=[dim,384],stddev=0.04,w1=0.004)
bias3 = tf.Variable(tf.constant(0.1,shape=[384]))
local3 = tf.nn.relu(tf.matmul(reshape,weight3)+bias3)
# -------------------创建第二个全链接层------------------
weight4 = variable_with_weight_loss(shape=[384,192],stddev=0.04,w1=0.004)
bias4 = tf.Variable(tf.constant(0.1,shape=[192]))
local4 = tf.nn.relu(tf.matmul(local3,weight4)+bias4)

在创建第三个全链接层时,并没有使用softmax,把softmax的环节放在了与loss一起的计算过程中。

# -------------------创建第三个全链接层-----------------
weight5 = variable_with_weight_loss(shape=[192,10],stddev=1/192.0,w1=0.0)
bias5 = tf.Variable(tf.constant(0.0,shape=[10]))
logits = tf.add(tf.matmul(local4,weight5),bias5)

tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

除去name参数用以指定该操作的name,与方法有关的一共两个参数

第一个参数logits:就是神经网络最后一层的输出,如果有batch的话,它的大小就是[batchsize,num_classes],单样本的话,大小就是num_classes

第二个参数labels:实际的标签,大小同上

当分类问题只有一个正确答案时,可以使用这个函数来加速交叉熵的计算,这个函数的第一个参数是神经网络不包括softmax层的前向传播结果,第二个是训练数据的正确答案。由于本项目使用了L2正则化,所以损失是由范式损失和计算损失相加的结果。即:

J=1/m L+w1||w||所以定义损失函数将两项损失相加。

# ---------------------定义损失函数--------------------
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)
    return tf.add_n(tf.get_collection('losses'),name='total_loss')

由于SOFTMAX给出的结果是一个10维的向量,我们需要选出的是关联性最大的那个使用top函数:

tf.nn.in_top_k(predictions, targets, k, name=None)

判断target 是否在top k 的预测之中。

与MNIST相同的是在程序执行之前要先确定会话,初始化向量的操作。这里不同的是开启线程,因为图片的增强操作即增加图片的丰富程度,这个操作通过旋转/裁剪增加图像集合,需要开启线程实现此操作。
# -----------------定义训练前数据--------------
loss = loss(logits,lable_holder)
train_op  = tf.train.AdamOptimizer(1e-3).minimize(loss)
top_k_op = tf.nn.in_top_k(logits,lable_holder,1)
sess= tf.InteractiveSession()
tf.global_variables_initializer().run()
tf.train.start_queue_runners()
# ------------------训练数据----------------------
for step in range(max_steps):
    start_time = time.time()
    image_batch,lable_batch = sess.run([image_train,label_train])
    _,loss_value = sess.run([train_op,loss],feed_dict={image_holder:image_batch,lable_holder:lable_batch})
    duration = time.time()-start_time
    if step%10 == 0:
        examples_per_sec = batch_size/duration
        sec_per_batch = float(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)

你可能感兴趣的:(TensorFlow)