聖誕節玩的有點嗨,差點忘記更新。祝你們昨天聖誕節快樂,再過幾天元旦節快樂。git
來繼續學習,在/home/your_name/TensorFlow/cifar10/ 下新建文件夾cifar10_train,用來保存訓練時的日誌logs,繼續在/home/your_name/TensorFlow/cifar10/ cifar10.py中輸入以下代碼:github
def train(): # global_step global_step = tf.Variable(0, name = 'global_step', trainable=False) # cifar10 數據文件夾 data_dir = '/home/your_name/TensorFlow/cifar10/data/cifar-10-batches-bin/' # 訓練時的日誌logs文件,沒有這個目錄要先建一個 train_dir = '/home/your_name/TensorFlow/cifar10/cifar10_train/' # 加載 images,labels images, labels = my_cifar10_input.inputs(data_dir, BATCH_SIZE) # 求 loss loss = losses(inference(images), labels) # 設置優化算法,這裏用 SGD 隨機梯度降低法,恆定學習率 optimizer = tf.train.GradientDescentOptimizer(LEARNING_RATE) # global_step 用來設置初始化 train_op = optimizer.minimize(loss, global_step = global_step) # 保存操做 saver = tf.train.Saver(tf.all_variables()) # 彙總操做 summary_op = tf.merge_all_summaries() # 初始化方式是初始化全部變量 init = tf.initialize_all_variables() os.environ['CUDA_VISIBLE_DEVICES'] = str(0) config = tf.ConfigProto() # 佔用 GPU 的 20% 資源 config.gpu_options.per_process_gpu_memory_fraction = 0.2 # 設置會話模式,用 InteractiveSession 可交互的會話,逼格高 sess = tf.InteractiveSession(config=config) # 運行初始化 sess.run(init) # 設置多線程協調器 coord = tf.train.Coordinator() # 開始 Queue Runners (隊列運行器) threads = tf.train.start_queue_runners(sess = sess, coord = coord) # 把彙總寫進 train_dir,注意此處尚未運行 summary_writer = tf.train.SummaryWriter(train_dir, sess.graph) # 開始訓練過程 try: for step in xrange(MAX_STEP): if coord.should_stop(): break start_time = time.time() # 在會話中運行 loss _, loss_value = sess.run([train_op, loss]) duration = time.time() - start_time # 確認收斂 assert not np.isnan(loss_value), 'Model diverged with loss = NaN' if step % 30 == 0: # 本小節代碼設置一些花哨的打印格式,能夠不用管 num_examples_per_step = BATCH_SIZE examples_per_sec = num_examples_per_step / duration sec_per_batch = float(duration) format_str = ('%s: step %d, loss = %.2f (%.1f examples/sec; %.3f ' 'sec/batch)') print (format_str % (datetime.now(), step, loss_value, examples_per_sec, sec_per_batch)) if step % 100 == 0: # 運行彙總操做, 寫入彙總 summary_str = sess.run(summary_op) summary_writer.add_summary(summary_str, step) if step % 1000 == 0 or (step + 1) == MAX_STEP: # 保存當前的模型和權重到 train_dir,global_step 爲當前的迭代次數 checkpoint_path = os.path.join(train_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step) except Exception, e: coord.request_stop(e) finally: coord.request_stop() coord.join(threads) sess.close() def evaluate(): data_dir = '/home/your_name/TensorFlow/cifar10/data/cifar-10-batches-bin/' train_dir = '/home/your_name/TensorFlow/cifar10/cifar10_train/' images, labels = my_cifar10_input.inputs(data_dir, BATCH_SIZE, train = False) logits = inference(images) saver = tf.train.Saver(tf.all_variables()) os.environ['CUDA_VISIBLE_DEVICES'] = str(0) config = tf.ConfigProto() config.gpu_options.per_process_gpu_memory_fraction = 0.2 sess = tf.InteractiveSession(config=config) coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess = sess, coord = coord) # 加載模型參數 print("Reading checkpoints...") ckpt = tf.train.get_checkpoint_state(train_dir) if ckpt and ckpt.model_checkpoint_path: ckpt_name = os.path.basename(ckpt.model_checkpoint_path) global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1] saver.restore(sess, os.path.join(train_dir, ckpt_name)) print('Loading success, global_step is %s' % global_step) try: # 對比分類結果,至於爲何用這個函數,後面詳談 top_k_op = tf.nn.in_top_k(logits, labels, 1) true_count = 0 step = 0 while step < 157: if coord.should_stop(): break predictions = sess.run(top_k_op) true_count += np.sum(predictions) step += 1 precision = true_count / 10000 print('%s: precision @ 1 = %.3f' % (datetime.now(), precision)) except tf.errors.OutOfRangeError: coord.request_stop() finally: coord.request_stop() coord.join(threads) sess.close() if __name__ == '__main__': if TRAIN: train () else: evaluate()
如今說明一下 in_top_k 這個函數的做用,官方文檔介紹中: tf.nn.in_top_k(predictions, targets, k, name=None)
這個函數返回一個 batch_size 大小的布爾矩陣 array,predictions 是一個 batch_size*classes 大小的矩陣,targets 是一個 batch_size 大小的類別 index 矩陣,這個函數的做用是,若是 targets[i] 是 predictions[i][:] 的前 k 個最大值,則返回的 array[i] = True, 不然,返回的 array[i] = False。能夠看到,在上述評估程序 evaluate 中,這個函數沒有用 softmax 的結果進行計算,而是用 inference 最後的輸出結果(一個全鏈接層)進行計算。算法
寫完以後,點擊運行,能夠看到,訓練的 loss 值,從剛開始的 2.31 左右,降低到最終的 0.00 左右,在訓練的過程當中,/home/your_name/TensorFlow/cifar10/cifar10_train/ 文件夾下會出現12個文件,其中有 5 個 model.ckpt-0000 文件,這個是訓練過程當中保存的模型,後面的數字表示迭代次數,5 個 model.ckpt-0000.meta 文件,這個是訓練過程當中保存的元數據(暫時不清楚功能),TensorFlow 默認只保存近期的幾個模型和幾個元數據,刪除前面沒用的模型和元數據。還有個 checkpoint 的文本文檔,和一個 out.tfevents 形式的文件,是summary 的日誌文件。若是不想用 tensorboard 看網絡結構和訓練過程當中的權重分佈,損失狀況等等,在程序中能夠不寫 summary 語句。瀏覽器
訓練完成以後,咱們用 tensorboard 進行可視化(事實上在訓練的過程當中,隨時能夠可視化)。在任意位置打開命令行終端,輸入:網絡
tensorboard --logdir=/home/your_name/TensorFlow/cifar10/cifar10_train/
會出現以下指示:多線程
根據指示,打開瀏覽器,輸入 http://127.0.1.1:6006(有的瀏覽器可能不支持,建議多換幾個瀏覽器試試)會看到可視化的界面,有六個選項卡:函數
EVENTS 對話框裏面有兩個圖,一個是訓練過程當中的 loss 圖,一個是隊列 queue 的圖;因爲沒有 image_summary() 和 audio_summary() 語句,因此,IMAGES 和 AUDIO 選項卡都沒有內容;GRAPHS 選項卡包含了整個模型的流程圖,以下圖,能夠展開和移動選定的 namespace;DISTRBUTIONS 和 HISTOGRAMS 包含了訓練時的各類彙總的分佈和柱狀圖。學習
訓練完以後,設置 TRAIN = False,進行測試,獲得以下結果:測試
能夠看到,測試的精度只有 76%,測試結果不夠高的緣由多是,測試的時候沒有通過 softmax 層,直接用全鏈接層的權重(存疑?),另外官方的代碼也給出了官方的運行結果,以下:優化
能夠看到,通過 10 萬次迭代,官方給出的正確率達到 83%,咱們只進行了 5 萬次,達到 76% 的正確率,相對來講,還算能夠,效果沒有官方好的緣由多是:
1. 官方使用了非固定的學習率;
2. 官方迭代比本代碼迭代次數多一倍;
參考文獻:
1. https://github.com/tensorflow/models/tree/master/tutorials/image/cifar10