2017年6月28日 星期三

tf.slim deploy trained model

用 tf.slim train 好了 model 以後,要拿來做 inference 才發現腦袋不大清楚不知道怎麼弄,查了一下,看到這邊,原來 tensorflow 本身就有提供 freeze 的工具,slim 也有 script 讓使用者可以方便的 export model。

照著註解裡面步驟做就可以了,兩步,橫簡單,連我都會。

昨天浪費了我幾個小時在那邊摸索,真的很笨。不知道昨天為什麼突然忘記「開始動手做之前先看看別人怎麼做」我的天哪...

[0] https://github.com/tensorflow/models/blob/master/slim/export_inference_graph.py

2017年6月22日 星期四

TF.slim 吃自訂格式的 data

Tensorflow.slim 預設是吃他 TFRecord。但我的圖很多,我不想全部轉成 TFRecord,這樣會吃掉很多硬碟,我想要保留 .jpg 的檔案在硬碟裡,然後有一個文字檔,裡面描述了哪些檔案有哪些 label。

0.jpg -1:* 1:0,7  
1.jpg -1:* 1:1,2,4...

表示 0.jpg 這張圖,有第 0 個 label 跟第 7 個 label。這兩個 label 是 1,其他都是 0。然後 1.jpg 這張圖,有第 1 第 2 第 4 個 label,其他都沒有。至於總共有多少 label,在描述 dataset 的 .py 檔會有寫。

slim 有自己的 reader class,有做了 parallel reader,對於需要大量訓練的時候可以加快 read data 的時間,但是 reader 讀進來之後,decoder 卻只有一個人。如果 decoding 需要很多時間,那這邊就會有問題。為了繞過這個問題,我決定把 reader 跟 decoder 合併在一起。

我根據 slim 的 parallel_reader.py 加了一個 parallel_reader_decoder.py,multi-thread 在讀取檔案以後,同時就會去 decode,之後才放進一個 common queue 讓之後的 node 取用。

這邊註記幾點:
  1. 寫 decoder 的時候,真的要注意效能問題,本來我用很 python 的方法在處理 numpy 陣列,後來發現效能慘不忍睹,改用 numpy style 以後 performance 快了幾百倍。
  2. tf.py_func() 就很好用,不一定要用 C++ 去寫 Op,當然如果真的需要就不要偷懶。
  3. tf.losses 會幫忙把 loss 登錄到 GraphKey.LOSSES,之後會有人去取用,所以不要覺得好奇怪為什麼這個 loss 都沒有人用到
  4. 記得把 slim 的 preprocessing thread 的數量也開到對,不然你會發現 reading 夠快,decoding 夠快,GPU 的 forward computation 跟 backward propagation 也夠快,但是 throughput 就是有夠低。最後發現是死在 preprocessing thread 數量太少。這個數值跟你的 model 所需要的 preprocessing 複雜度有關。mnist 的 preprocessing 很簡單,一個說不定就夠了,inception 可能要 4(或 8?)。
  5. slim 裡面有幾個 queue,queue capacity 記得要改到夠大,pop 以後的 min-size 也要調整(小),不然你會發現他一批一批的做,比方說你 queue capacity 是 16,min-size 卻是 8,但是你有 8 個 clone,這樣他一次要吃掉 8 個,吃完以後這個 queue 的 producer 才會做事,很不方便。這樣這個 queue 等於沒有 buffering 的效果。
    1. Filename Queue (after enumerate files)
    2. Parallel Reading Queue (after read)
    3. Prefetch Queue (after preprocessing)
    4. Batch Queue (after batch packing)
  6. 開太多 preprocessor 的話,tensorboard 秀 graph 會 gg =_=||
  7. sigmoid_cross_entropy 不要亂餵,他的值域就是 0 ~ 1,雖然我自己的 multi-label 標注方法是 1 positive, -1 negative, 0 don't care,但計算的時候,不要去把 logit 轉換到 -1 ~ 1,而是要把 label 從 -1 ~ 1 轉換成 0 ~ 1(但是 label 真的是 0 的時候,要記得 don't care)用tf.abs 跟 tf.maximum 可以做到。不難。
腦子不管用了,剩下的等想到再寫

2017年6月18日 星期日

tensorflow 自訂 operator

考慮開發速度的話,先使用  tf.py_func  [0]
如果遇到限制,或是考慮執行效能的話,再去看 Adding a New Op [1]

雖說 [1] 比 [0] 麻煩,但其實也相當簡單,不用害怕,進去看著照做就可以了,半個小時的事情

[0] https://www.tensorflow.org/api_docs/python/tf/py_func
[1] https://www.tensorflow.org/extend/adding_an_op