Linux上TensorFlow的深入研究:構建一個低成本、快速、精準的圖像分類器

在過去的八個月裏,我花了大量時間學習了盡可能多的機器學習知識。我經常對在這個小但快速成長的社區中的在線慕課(MOOCs)上遇到的各種各樣的人感到驚訝。他們中既有費米實驗室(Fermilab)的量子研究員,也有矽穀的CEO們。最近我一直關注開源軟件TensorFlow,這篇教程就是我的研究成果。
我覺得很多機器學習教程都是麵向Mac係統的。使用Linux係統的一個主要優勢是它是免費的,並支持基於GPU的TensorFlow。GPU的並行加速計算能力是機器學習重大進步的原因之一。因此你不需要為了構建一個快速分類器而使用最前沿的計算設備,像我用的計算機和顯卡總共花費了不到400美元。
在本教程中我會告訴你如何在Ubuntu上使用GPU來訓練自己的圖像分類器。本教程跟Pete Warden的《“詩人”也能用TensorFlow》非常類似,但是稍有不同。我會假定你已經安裝了TensorFlow和Bazel,並在你的主目錄下git克隆了最新版本的TensorFlow。如果你還沒有完成上述工作,你可以按照我博客上的教程進行操作。如果你的計算機沒有與TensorFlow兼容GPU,你仍然可以使用這個教程,隻不過它需要更長的時間。
整個訓練過程非常簡單,可以分為四個主要步驟:
1. 收集訓練用的圖像。
2. 使用TensorFlow和Inception模型來訓練一個計算圖/模型。
3. 編寫腳本來用你的計算圖來進行圖像分類。
4. 通過對新圖像進行分類來測試腳本。
我決定使用五種不同的鷙鳥來訓練我的圖像分類器。使用鷙鳥並不是一個偶然的決定,我曾在不列顛哥倫比亞省鄧肯市的“勐龍”機構工作了兩年,這是一個教育中心及野生動物管理機構。長期以來我對這些凶勐的神話生物有著深厚的熱情。作為終極挑戰,我把我的分類器跟康奈爾大學鳥類實驗室的Merlin ID工具係統進行對比。在本文的撰寫過程中該實驗室升級了它的網站並發布公告:“Merlin Photo ID 暫停使用以進行維護和升級。…康奈爾鳥類實驗室和Visipedia團隊正在合作研發可以識別照片中鳥類的計算機視覺技術”。毫無疑問,他們正在將他們的Merlin係統(現在不可用)升級為一個現代機器學習分類器。
收集訓練用的圖像
我從“勐龍”的臉書頁麵並結合網絡搜索為每類鷙鳥收集了約100張圖片。我找到了鷙鳥在許多不同的環境及地點的圖片以建立圖像集。為了使圖像分類器有很好的泛化能力,至少用100張在不同的場景和背景中的圖像用來訓練它是比較理想的。還有一些方法可以扭曲現有的圖像以得到更多的訓練樣本,但這可能會降低你的訓練過程的速度。注意我們不需要用成千上萬的樣本來訓練模型,這是因為TensorFlow會用Inception模型之前訓練特征檢測器來重新訓練一個新模型。
我多做了一個實驗,即讓每種鷙鳥類圖像樣本的大約10%是幼鳥圖像。我很好奇分類器是否可以找到一個幼鳥和成年鳥之間的相似之處。
一旦有了合適的圖像數量和類型,我在我的TensorFlow目錄下創一個文件夾:
$ cd ~/tensorflow
$ mkdir tf_files && cd tf_files && mkdir bird_photos && cd bird_photos
$ mkdir baldeagle goldeneagle peregrine saker vulture
我的目錄結構如下圖所示:
然後我將鳥類的圖像集移動到相應的文件夾中。該腳本接受PNG、JPG、GIF和TIF類型圖像,但我發現為了避免一個錯誤,我不得不重命名一個有很多符號的文件名。
訓練模型
然後我使用克隆的TensorFlow源碼中的內置python腳本訓練了一個新模型和相關標簽。我們用來重新訓練的原始計算圖是穀歌研究人員花費了兩個星期在一台包含八個NVidia Tesla K40 GPU的計算機上訓練得到的。
$ cd ~/tensorflow
$ python tensorflow/examples/image_retraining/retrain.py \
–bottleneck_dir=tf_files/bottlenecks \
–model_dir=tf_files/inception \
–output_graph=tf_files/retrained_graph.pb \
–output_labels=tf_files/retrained_labels.txt \
–image_dir tf_files/bird_photos
因為我安裝的TensorFlow有GPU支持,所以訓練模型用了不到10分鍾。如果在我的舊Xeon CPU機器上進行這個訓練,它可能需要花費一整天的時間。以下是訓練結果:
圖2 截圖由Justin Francis友情提供
我的TensorFlow模型的最終測試精度為91.2%。考慮到我用了各種各樣不同的圖像,我覺得這個結果是非常令人驚喜的。
構建分類器
到目前為止我采用了原始計算圖並用我自己的圖片集重新訓練。接下來我用Bazel構建了我自己的圖像分類器,它是從TensorFlow git上克隆下來的。(不要關閉終端,否則你將需要重新構建)
$ bazel build tensorflow/examples/label_image:label_image
測試分類器
有趣的部分來了——對新的一組圖像進行分類器測試。為了簡便起見,我把我的測試圖像放在我的tf_files文件夾中。
$ bazel-bin/tensorflow/examples/label_image/label_image \
–graph=tf_files/retrained_graph.pb \
–labels=tf_files/retrained_labels.txt \
–output_layer=final_result \
–image=tf_files/bird.jpg #This is the test image
首先我嚐試分類一張我立即就能識別出為獵隼的圖片:
圖3 成熟的獵隼,來自維基百科的DickDaniels作品
TensorFlow也識別出來是獵隼!
圖4 截圖由Justin Francis友情提供
接下來我嚐試了一張更複雜的且沒有在我的訓練數據集中出現的幼年遊隼圖片(下麵左圖)。幼年遊隼的前麵羽毛跟獵隼類似,但當它成年後會變成條紋狀的腹部、黃色的喙和灰白色的下頸部。
圖5 左圖:幼年遊隼,來自維基百科的Spinus自然攝影圖像。右圖:成年遊隼,來自維基百科的Norbert Fischer作品
令我驚訝的是分類器能夠以相當高的精確度識別出幼年遊隼:
圖6 截圖由Justin Francis友情提供
我的最後一個例子使用了一張人類經常會錯誤分類的鳥類圖片:幼年禿頭鷹。人類經常會錯誤地認為它是一隻金鷹,因為它的頭部和尾部沒有堅實的白色羽毛。我的訓練分類器使用的訓練圖片約包含10%的幼鷹圖片。
圖7 剛剛會飛的幼年禿鷹,來自維基百科的KetaDesign作品
似乎我的分類器還不能超過鳥類學家的智力:
圖8 截圖由Justin Francis友情提供
我特別驚訝分類器的第二個猜測是“禿鷲”而不是“禿鷹”。這可能是因為我的很多禿鷲圖片的拍攝角度跟禿鷹類似。
那Merlin係統怎麼樣?它的第一選擇是正確的而第二選擇也是非常合理的。
圖9 截圖由Justin Francis友情提供
Merlin係統隻有在這張圖片的分類上打敗了我的分類器。但是如果有足夠的訓練數據,我完全相信我的分類器可以學會區別成年禿鷹、幼年禿鷹和金鷹。當然我需要一個單獨的包含更多圖片的幼年禿鷹文件夾。
原文發布時間為:2017-02-08
本文來自雲棲社區合作夥伴“大數據文摘”,了解相關信息可以關注“BigDataDigest”微信公眾號
最後更新:2017-05-25 18:31:58