MNSIT是一個很是有名的手寫體數字識別數據集。包含60000張訓練圖片,10000張測試圖片。每張圖片是28X28的數字。git
TonserFlow提供了一個類來處理 MNSIT數據。這個類會自動下載並轉化數據結構。網絡
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist_data = input_data.read_data_sets("mnist_set",one_hot=True) # print training data size print("training_data_size",mnist_data.train.num_examples) # print validation data size print("validating_data_size",mnist_data.validation.num_examples) #print testing data size print("testing data size",mnist_data.test.num_examples) print("example train image :",mnist_data.train.images[0]) print("example train label :",mnist_data.train.labels[0])
爲了方便使用隨機梯度降低,數據結構
input_data.read_data_sets還提供train.next_batch函數
batch_size = 100 train_x ,train_y = mnist_data.train.next_batch(batch_size) print("X_shape",train_x.shape) print("Y_shape",train_y.shape) ## #X_shape (100, 784) #Y_shape (100, 10)
利用上一篇介紹的方法搭建網絡。app
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()
爲了評判不一樣網絡在不一樣參數下的效果,通常從訓練數據中抽取一部分做爲驗證數據,使用驗證數據能夠評判不一樣參數下模型的表現。除了使用驗證數據,還可使用交叉驗證的方式。dom
TensorFlow提供了一個經過變量名稱來建立或者獲取變量的機制。經過這個機制能夠,在不一樣的函數中能夠經過變量的名字來使用變量。經過變量名稱來獲取變量的函數是函數
tf.get_variable和tf.variable_scope.學習
tf.get_variable除了獲取變量,還具備與tf.Variable類似的功能。都可用來建立變量。測試
#下面兩個定義是等價的 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中不一樣的初始化函數spa
tf.get_variable和tf.Variable最大的區別在於指定變量名稱的參數,tf.Variable的變量名稱是可選參數,tf.get_variable的變量名稱是必填參數。rest
若是須要經過tf.get_variable獲取一個已經建立的變量,須要經過tf.variable_scope來建立一個上下文管理器,
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])
TensorFlow中tf.variable_scope函數能夠嵌套。
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.get_variable和tf.variable_scope來改進咱們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提供了模型的持久化,還能夠從持久化的模型文件中還原被保存的模型。
TensorFlow提供了一個簡單的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))
這裏加載模型的代碼和保存模型的代碼基本一致,也須要先定義計算圖模型的運算只是沒有運行變量初始化。若是不但願重複定義圖上的運算,也能夠直接加載已經持久化的圖。TensorFlow提供了這樣的方法tf.train.import_meta_graph
#直接加載持久化計算圖 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})