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

OReillyData發表於2017-02-07

編者注:想要學習如何從頭開始構建和訓練你的第一個TensorFlow計算圖,請閱讀Aaron Schumacher在O’Reilly線上教程裡的《你好,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

我的目錄結構如下圖所示:

640?wx_fmt=png

圖1. 截圖由Justin Francis友情提供

然後我將鳥類的影象集移動到相應的資料夾中。該指令碼接受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機器上進行這個訓練,它可能需要花費一整天的時間。以下是訓練結果:

640?wx_fmt=png

圖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

首先我嘗試分類一張我立即就能識別出為獵隼的圖片:

640?wx_fmt=jpeg

圖3 成熟的獵隼,來自維基百科的DickDaniels作品

TensorFlow也識別出來是獵隼!

640?wx_fmt=png

圖4 截圖由Justin Francis友情提供

接下來我嘗試了一張更復雜的且沒有在我的訓練資料集中出現的幼年遊隼圖片(下面左圖)。幼年遊隼的前面羽毛跟獵隼類似,但當它成年後會變成條紋狀的腹部、黃色的喙和灰白色的下頸部。

640?wx_fmt=jpeg 640?wx_fmt=jpeg

圖5 左圖:幼年遊隼,來自維基百科的Spinus自然攝影影象。右圖:成年遊隼,來自維基百科的Norbert Fischer作品

令我驚訝的是分類器能夠以相當高的精確度識別出幼年遊隼:

640?wx_fmt=png

圖6 截圖由Justin Francis友情提供

我的最後一個例子使用了一張人類經常會錯誤分類的鳥類圖片:幼年禿頭鷹。人類經常會錯誤地認為它是一隻金鷹,因為它的頭部和尾部沒有堅實的白色羽毛。我的訓練分類器使用的訓練圖片約包含10%的幼鷹圖片。

640?wx_fmt=jpeg

圖7 剛剛會飛的幼年禿鷹,來自維基百科的KetaDesign作品

似乎我的分類器還不能超過鳥類學家的智力:

640?wx_fmt=png

圖8 截圖由Justin Francis友情提供

我特別驚訝分類器的第二個猜測是“禿鷲”而不是“禿鷹”。這可能是因為我的很多禿鷲圖片的拍攝角度跟禿鷹類似。

那Merlin系統怎麼樣?它的第一選擇是正確的而第二選擇也是非常合理的。

640?wx_fmt=png

圖9 截圖由Justin Francis友情提供

Merlin系統只有在這張圖片的分類上打敗了我的分類器。但是如果有足夠的訓練資料,我完全相信我的分類器可以學會區別成年禿鷹、幼年禿鷹和金鷹。當然我需要一個單獨的包含更多圖片的幼年禿鷹資料夾。

我用這個分類器做了很多有趣的訓練和實驗。我希望這篇博文也能夠幫你構建你自己的分類器。研究人員和愛好者的創造能力是無限的,請在Twitter上通過@wagonhelm或#TensorFlow標記我。

640?wx_fmt=jpeg

Justin Francis

Justin居住在加拿大西海岸的一個小農場。這個農場專注於樸門道德和設計的農藝。在此之前,他是一個非營利性社群合作社自行車商店的創始人和教育者。在過去的兩年中,他住在一艘帆船上,全職探索和體驗加拿大的喬治亞海峽。但現在他的主要精力都放在了學習機器學習上。

640?wx_fmt=png


相關文章