说明:1、损失函数 loss = cross_entropy_mean + regularization
= cross_entropy_mean + regularizer(weights1)+regularizer(weights2)
2、 预测值 y = w2y' + b2
= w2(w1x + b1) +b2
3、在所有代表神经网络参数的变量上使用滑动平均,其他超参数不需要
4、使用梯度下降优化算法优化损失函数,损失函数包括交叉熵损失和L2正则化损失
5、在训练神经网络模型时,每过一遍数据既需要通过反向传播来更新参数,也要更新每个参数的滑动平均值
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./data/MNIST/", one_hot=True)
#输入结点数为像素点数,输出结点数为类别数
INPUT_NODE=784
OUTPUT_NODE=10
#一个隐藏层
LAYER1_NODE=500
#一个批量中的样本量,数据量越小训练过程越接近SGD,数据量越大训练过程越接近梯度下降
BATCH_SIZE=100
#学习率和学习衰减率
LEARNING_RATE_BASE=0.8
LEARNING_RATE_DECAY=0.99
#正则化系数、迭代次数和滑动平均衰减率
REGULARIZATION_RATE=0.0001
TRAINING_STEPS=3000
MOVING_AVERAGE_DECAY=0.99
#定义推断函数,给定所有参数下计算神经网络的前向传播结果。参数avg_class可确定推断中使不使用滑动平均模型
def inference(input_tensor,avg_class,weights1,biases1,weights2,biases2):
#没有提供滑动平均类时,直接使用参数当前的取值
if avg_class == None:
#计算隐藏层前向传播结果,使用ReLU激活函数
layer1=tf.nn.relu(tf.matmul(input_tensor,weights1)+biases1)
#计算输出层的前向传播结果
return tf.matmul(layer1,weights2)+biases2
else:
#首先使用avg_class.average函数计算变量的滑动均值,然后计算相应的前向传播结果
layer1=tf.nn.relu(tf.matmul(input_tensor,avg_class.average(weights1))+avg_class.average(biases1))
return tf.matmul(layer1,avg_class.average(weights2))+avg_class.average(biases2)
#模型训练函数
def train(mnist):
x=tf.placeholder(tf.float32,[None,INPUT_NODE],name='x-input')
y=tf.placeholder(tf.float32,[None,OUTPUT_NODE],name='y-input')
#生成隐藏层参数
weights1=tf.Variable(tf.truncated_normal([INPUT_NODE,LAYER1_NODE],stddev=0.1))
biases1=tf.Variable(tf.constant(0.1,shape=[LAYER1_NODE]))
#生成输出层参数
weights2=tf.Variable(tf.truncated_normal([LAYER1_NODE,OUTPUT_NODE],stddev=0.1))
biases2=tf.Variable(tf.constant(0.1,shape=[OUTPUT_NODE]))
#计算当前参数下前向传播的结果,这里设为‘None’不会计算滑动平均值
y_hat=inference(x,None,weights1,biases1,weights2,biases2)
#定义储存迭代数的变量,这个变量不需要计算滑动平均值,所以这里指定的这个变量为不饿训练变量(trainable=False)
global_step=tf.Variable(0,trainable=False)
#给定滑动平均衰减率和迭代数,初始化滑动平均类。
variable_averages=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
#在所有代表神经网络参数的变量上使用滑动平均,其他超参数不需要。tf.trainable_variables返回的就是图上的集合GraphKeys.TRAINABLE_VARIABLES中的元素。
variables_averages_op=variable_averages.apply(tf.trainable_variables())
#计算使用滑动平均后的前向传播结果,滑动平均不会改变变量本身,而是使用影子变量记录滑动平均值,需要使用滑动平均再明确调用average函数
average_y_hat=inference(x,variable_averages,weights1,biases1,weights2,biases2)
#~使用tf.argmax函数得到正确答案对应的类别编号
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y, 1))
#计算当前批量中所有样本的交叉熵均值
cross_entropy_mean=tf.reduce_mean(cross_entropy)
#计算L2正则化损失函数
regularizer=tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
#计算模型的正则化损失,只计算神经网络权重的正则化损失,不使用偏置项
regularization=regularizer(weights1)+regularizer(weights2)
#总损失函数
loss=cross_entropy_mean+regularization
#设置指数衰减学习率.基础学习率、当前迭代次数、一个epoch所需要的迭代次数、学习衰减率
learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,mnist.train.num_examples/BATCH_SIZE,LEARNING_RATE_DECAY)
#使用梯度下降优化算法优化损失函数,损失函数包括交叉熵损失和L2正则化损失
train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
#在训练神经网络模型时,每过一遍数据既需要通过反向传播来更新参数,也要更新每个参数的滑动平均值。为了一次完成多个操作
#train_op=tf.group(train_step,variables_averages_op)
with tf.control_dependencies([train_step,variables_averages_op]):
train_op=tf.no_op(name='train')
correct_prediction=tf.equal(tf.argmax(average_y_hat,1),tf.argmax(y,1))
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
#初始化会话并开始训练过程
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
validate_feed={x:mnist.validation.images,y:mnist.validation.labels}
test_feed={x:mnist.test.images,y:mnist.test.labels}
# 循环的训练神经网络。
for i in range(TRAINING_STEPS):
if i % 1000 == 0:
validate_acc = sess.run(accuracy, feed_dict=validate_feed)
print("After %d training step(s), validation accuracy using average model is %g " % (i, validate_acc))
xs,ys=mnist.train.next_batch(BATCH_SIZE)
sess.run(train_op,feed_dict={x:xs,y:ys})
test_acc=sess.run(accuracy,feed_dict=test_feed)
print(("After %d training step(s), test accuracy using average model is %g" %(TRAINING_STEPS, test_acc)))
运行结果:
avg_class = None
train(mnist)
运行结果: