import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("mnist_set",one_hot=True) #数据集相关常数 INPUT_NODE = 784 OUTPU_NODE = 10 #配置神经网络参数 LAYER1_NODE = 500 BATCH_SIZE = 100 LEARNING_RATE_BASE = 0.8 #基础学习率 LEARNING_RATE_DECAY = 0.99#学习衰减率 REGULARIZATION_RATE = 0.0001#正则的惩罚系数 MOVE_AVG_RATE = 0.99 #滑动平均衰减率 TRAIN_STEPS = 30000 def inference(input_tensor,weights1,biases1,weight2,biases2,avg_class=None): #当没有提供滑动平均类时,直接使用当前值 if avg_class == None: #计算隐藏层的前向传播结果,使用RELU激活函数 layer1 = tf.nn.relu(tf.matmul(input_tensor,weights1)+biases1) #返回输出层的前向传播 return tf.matmul(layer1,weight2)+ biases2 else: #前向传播之前,用avg——class计算出变量的滑动平均值 layer1 = tf.nn.relu(tf.matmul(input_tensor,avg_class.average(weights1))+avg_class.average(biases1)) return tf.matmul(layer1,avg_class.average(weight2))+ avg_class.average(biases2) #模型的训练过程 def train(mnist): x = tf.placeholder(tf.float32,[None,INPUT_NODE],name='x-input') y_ = tf.placeholder(tf.float32,[None,OUTPU_NODE],name="y_input") #隐藏层参数 w1 = tf.Variable(tf.random_normal([INPUT_NODE,LAYER1_NODE],stddev=0.1)) b1 = tf.Variable(tf.constant(0.1,shape=[LAYER1_NODE])) #输出层参数 w2 = tf.Variable(tf.random_normal([LAYER1_NODE,OUTPU_NODE],stddev=0.1)) b2 = tf.Variable(tf.constant(0.1,shape=[OUTPU_NODE])) y = inference(x,w1,b1,w2,b2) #定义存储训练轮数的变量,设为不可训练 global_step = tf.Variable(0,trainable=False) #初始化滑动平均类 variable_averages = tf.train.ExponentialMovingAverage(MOVE_AVG_RATE,global_step) #在神经网络的所有参数变量上使用滑动平均 variable_averages_op = variable_averages.apply(tf.trainable_variables()) averages_y = inference(x,w1,b1,w2,b2,avg_class=variable_averages) #计算交叉熵损失 cross_entropy = tf.nn.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(w1)+ regularizer(w2) #总的损失 loss = cross_entropy_mean + regularization #设置指数衰减的学习率 training_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,mnist.train.num_examples/BATCH_SIZE,LEARNING_RATE_DECAY) train_step = tf.train.GradientDescentOptimizer(training_rate).minimize(loss,global_step) #更新滑动平均值 with tf.control_dependencies([train_step,variable_averages_op]): train_op = tf.no_op(name='train') #验证前向传播结果是否正确 correct_prediction = tf.equal(tf.argmax(averages_y,1),tf.argmax(y_,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) #初始会话,开始训练 with tf.Session() as sess: tf.global_variables_initializer().run() #准备验证数据和测试数据 validate_feed = {x:mnist.validation.images,y_: mnist.validation.labels} test_feed = {x:mnist.test.images,y_: mnist.test.labels} #迭代训练神经网络 for i in range(TRAIN_STEPS): if i % 1000 == 0: validate_acc = sess.run(accuracy,feed_dict=validate_feed) print("After %s training steps ,validation accuracy is %s"%(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,test_feed) print("After %s training steps ,test accuracy is %s"%(TRAIN_STEPS,test_acc)) def main(argv=None): mnist = input_data.read_data_sets("mnist_set",one_hot=True) train(mnist) if __name__ == '__main__': #TF 提供了一个主程序入口,tf.app.run会自动调用上面的main() tf.app.run()
2.使用验证数据集判断模型效果
为了判断不同网络在不同参数下的效果,一般从训练数据中提取一部分作为验证数据,验证数据可以用来判断模型在不同参数下的表现。除了使用验证数据,还可以使用交叉验证。
三、变量管理
提供一种按名称创建或检索变量的机制。通过这种机制,变量可以通过它们的名字在不同的函数中使用。通过名称获取变量的函数是
tf.和 tf..
tf.除了获取变量之外,它还有一个类似tf..的功能,可以用来创建变量。
#下面两个定义是等价的 v = tf.Variable(tf.constant(1.0,shape=[1]),name="v") v = tf.get_variable(name="v",shape=[1],initializer=tf.constant_initializer(1.0))
TF 提供了 7 种不同的初始化函数
tf.和tf的最大区别。是指定变量名称的参数。 tf 的变量名。是可选参数,tf.的变量名。是必需的参数。
如果需要通过tf.获取已经创建好的变量,则需要通过tf.创建上下文管理器,
with tf.variable_scope("foo"): v = tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0)) #如果命名空间foo中已经存在了v,这会报错 #ValueError: Variable foo/v already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? #在声明上下文管理器的时候,直接将reuse设为True,tf。get_variable则会直接获取已经存在的变量,但设为true的时候tf。get_variable不能创建变量 with tf.variable_scope("foo",reuse=True): v1 = tf.get_variable("v",[1])
tf.函数可以嵌套。
with tf.variable_scope("root",reuse=True): print(tf.get_variable_scope().reuse) #True with tf.variable_scope("bar",reuse=False): print(tf.get_variable_scope().reuse) #True 与外层的保持一致 with tf.variable_scope("foo",reuse=False): print(tf.get_variable_scope().reuse) #即使指定了reuse,也会保持与外层一致 print(tf.get_variable_scope().reuse) print(tf.get_variable_scope().reuse)
with tf.variable_scope("root"): print(tf.get_variable_scope().reuse) #false with tf.variable_scope("bar",reuse=True): print(tf.get_variable_scope().reuse) #true with tf.variable_scope("foo"): print(tf.get_variable_scope().reuse) #true print(tf.get_variable_scope().reuse) #true print(tf.get_variable_scope().reuse) #false
使用 tf.和 tf。改进我们的 MNIST 计划
def inference(input_tensor,avg_class=None,reuse = False): #当没有提供滑动平均类时,直接使用当前值 if avg_class == None: #计算隐藏层的前向传播结果,使用RELU激活函数 with tf.variable_scope("layer1",reuse=reuse): weight = tf.get_variable("weight",shape=[INPUT_NODE,LAYER1_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1)) biases = tf.get_variable("biases",shape=[LAYER1_NODE],initializer=tf.constant_initializer(0.0)) layer1 = tf.nn.relu(tf.matmul(input_tensor,weight)+biases) #返回输出层的前向传播 with tf.variable_scope("layer2",reuse=reuse): weight = tf.get_variable("weight",shape=[LAYER1_NODE,OUTPU_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1)) biases = tf.get_variable("biases",shape=[OUTPU_NODE],initializer=tf.constant_initializer(0.0)) layer2 = tf.nn.relu(tf.matmul(layer1,weight)+biases) return layer2 else: #前向传播之前,用avg——class计算出变量的滑动平均值 with tf.variable_scope("layer1",reuse=reuse): weight = tf.get_variable("weight",shape=[INPUT_NODE,LAYER1_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1)) biases = tf.get_variable("biases",shape=[LAYER1_NODE],initializer=tf.constant_initializer(0.0)) layer1 = tf.nn.relu(tf.matmul(input_tensor,avg_class.average(weight))+avg_class.average(biases)) #返回输出层的前向传播 with tf.variable_scope("layer2",reuse=reuse): weight = tf.get_variable("weight",shape=[LAYER1_NODE,OUTPU_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1)) biases = tf.get_variable("biases",shape=[OUTPU_NODE],initializer=tf.constant_initializer(0.0)) layer2 = tf.nn.relu(tf.matmul(layer1,avg_class.average(weight))+avg_class.average(biases)) return layer2
四、模型持久化
之前给出的示例代码训练完成后直接退出,训练好的模型没有保存。 TF提供模型持久化,你可以从持久化的模型文件中恢复保存的模型。
1、模型持久化代码实现
提供简单的 API (tf.train.Saver) 来保存模型。
v1 = tf.Variable(tf.constant(1.0,shape=[1],name="v1")) v2 = tf.Variable(tf.constant(2.0,shape=[1],name="v2")) result = v1 + v2 init_op = tf.global_variables_initializer() #声明tf.train.Saver类用于保存模型 saver = tf.train.Saver() with tf.Session() as sess: sess.run(init_op) #将模型保存到model。ckpt文件中 saver.save(sess,"Model/model.ckpt")
加载保存的模型
v1 = tf.Variable(tf.constant(1.0,shape=[1],name="v1")) v2 = tf.Variable(tf.constant(2.0,shape=[1],name="v2")) result = v1 + v2 # init_op = tf.global_variables_initializer() #声明tf.train.Saver类用于保存模型 saver = tf.train.Saver() with tf.Session() as sess: # sess.run(init_op) #将模型保存到model。ckpt文件中 saver.restore(sess,"Model/model.ckpt") print(sess.run(result))
这里是加载模型和保存模型的代码代码基本相同,需要先定义计算图模型的操作,但是没有运行变量初始化。如果不想在图上重复定义操作,也可以直接加载持久化图。 tf.train 提供了这样的方法。
#直接加载持久化计算图 saver = tf.train.import_meta_graph("Model/model.ckpt.meta") with tf.Session() as sess: saver.restore(sess,"Model/model.ckpt") #通过张量的名称来获取张量 print(sess.run(tf.get_default_graph().get_tensor_by_name("add:0")))
上述程序默认保存或加载TF计算图中的所有变量。但有时只需要保存或加载部分变量。在声明 tf.train.Saver 类时,可以提供需要保存或加载的变量列表。例如
tf.train.Saver([v1]).
除了选择要加载的变量,tf.train.Saver 还支持在保存或加载时重命名变量。
#保存模型 v1 = tf.Variable(tf.constant(1.0,shape=[1],name="outer_v1")) v2 = tf.Variable(tf.constant(2.0,shape=[1],name="outer_v2")) result = v1 + v2 init_op = tf.global_variables_initializer() #声明tf.train.Saver类用于保存模型 saver = tf.train.Saver([v1,v2]) with tf.Session() as sess: sess.run(init_op) saver.save(sess,"Model/model.ckpt") #加载模型 v1 = tf.Variable(tf.constant(1.0,shape=[1],name="outer_v1")) v2 = tf.Variable(tf.constant(2.0,shape=[1],name="outer_v2")) saver = tf.train.Saver({"v1":v1,"v2":v2})
分类:
技术要点:
相关文章:
暂无评论内容