本文是將yolo3目標檢測框架訓練出來的ckpt文件固化成pb文件,主要利用了GitHub上的該項目。
為什么要最終生成pb文件呢?簡單來說就是直接通過tf.saver保存行程的ckpt文件其變量數據和圖是分開的。我們知道TensorFlow是先畫圖,然后通過placeholde往圖里面喂數據。這種解耦形式存在的方法對以后的遷移學習以及對程序進行微小的改動提供了極大的便利性。但是對于訓練好,以后不再改變的話這種存在就不再需要。一方面,ckpt文件儲存的數據都是變量,既然我們不再改動,就應當讓其變成常量,直接‘燒'到圖里面。另一方面,對于線上的模型,我們一般是通過C++或者C語言編寫的程序進行調用。所以一般模型最終形式都是應該寫成pb文件的形式。
由于這次的程序直接從GitHub上下載后改動較小就能夠運行,也就是自己寫了很少一部分程序。因此進行調試的時候還出現了以前根本沒有注意的一些小問題,同時發現自己對TensorFlow還需要更加詳細的去研讀。
首先對程序進行保存的時候,利用 saver = tf.train.Saver(), saver.save(sess,checkpoint_path,global_step=global_step)對訓練的數據進行保存,保存格式為ckpt。但是在恢復的時候一直提示有問題,(其恢復語句為:saver = tf.train.Saver(), saver.restore(sess,ckpt_path),其中,ckpt_path是保存ckpt的文件夾路徑)。出現問題的原因我估計是因為我是按照每50個epoch進行保存,而不是讓其進行固定次數的batch進行保存,這種固定batch次數的保存系統會自動保存最近5次的ckpt文件(該方法的ckpt_path=tf.train,latest_checkpoint('ckpt/')進行回復)。那么如何將利用epoch的次數進行保存呢(這種保存不是近5次的保存,而是每進行一次保存就會留下當時保存的ckpt,而那種按照batch的會在第n次保存,會將n-5次的刪除,n>5)。
我們可以利用:ckpt = tf.train.get_checkpoint_state(ckpt_path),獲取最新的ckptpoint文件,然后利用saver.restore(sess,ckpt.checkpoint_path)進行恢復。當然為了安全起見,應該對ckpt和ckpt.checkpoint_path進行判斷是否存在后,再進行恢復語句的調用,建議打開ckptpoint看一下,里面記錄的最近五次的model的路徑,一目了然。即:
saver = tf.train.Saver() ckpt = tf.train.get_checkpoint_state(model_path) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path)
對于固化網絡,網上有很多的介紹。之所以再介紹,還是由于是用了別人的網絡而不是自己的網絡遇到的坑。在固化時候我們需要知道輸出tensor的名字,而再恢復的時候我們需要知道placeholder的名字。但是,如果網絡復雜或者別人的網絡命名比較復雜,或者name=,根本就沒有自己命名而用的系統自定義的,這樣捋起來還是比較費勁的。當時在網上查找的一些方法,像打印整個網絡變量的方法(先不管輸出的網路名稱,甚至隨便起一個名字,先固化好pb文件,然后對pb文件進行讀取,最后打印操作的名字:
新聞熱點
疑難解答