現代圖像識別模型具有數百萬個參數。從頭開始訓練需要大量標記的訓練數據和大量計算能力(數百小時 GPU 或更多)。遷移學習是一項通過采用在相關任務上經過訓練并在新模型中重復使用的一部分模型來快速實現這一目標的技術。在本教程中,我們將重用 ImageNet 上訓練的強大圖像分類器的特征提取功能,并簡單地在頂部訓練新的分類層。有關該方法的更多信息,您可以到 Decaf 上閱讀這篇論文(https://arxiv.org/abs/1310.1531)。
盡管這種方法無法與訓練整個模型相提并論,但對于許多應用來說已經有著出奇制勝的效果,特別對適量的訓練數據有效(數千,而非數百萬標記的圖像),且無需 GPU, 就可以在筆記本電腦上運行 30 分鐘。本教程將向您展示如何在您自己的圖像上運行示例腳本,并對您有助于控制訓練過程的一些選項作進一步解釋。
注意:本教程的一個版本也可作為 codelab 使用。
本教程使用 TensorFlow Hub 來調用預先訓練過的模型或模塊。對于初學者,我們將使用具有在 ImageNet 上訓練的 Inception V3 架構的圖像特征提取模塊,并稍后返回其他選項,包括 NASNet / PNASNet,以及MobileNet V1 和 V2。
在開始之前,您需要安裝 PIP 包 tensorflow-hub 以及最新版本的 TensorFlow。有關詳細信息,請參閱 TensorFlow Hub 的安裝說明(https://tensorflow.google.cn/hub/installation?hl=zh-CN)。
花卉訓練
圖片來自 Kelly Sikkema
任何訓練在開始之前,需要一組圖像來向網絡傳授您想要識別的新類別。本文后半部分會介紹該如何準備自己的圖像,但為了方便起見,我們創建了一個關于經許可的花卉照片的知識共享檔案,以便初始使用。要獲取花卉照片集,請運行以下命令:
cd ~curl -LO http://download.tensorflow.org/example_images/flower_photos.tgztar x*** flower_photos.tgz
獲得圖像后,可以從 GitHub 下載示例代碼(它不是庫安裝的一部分):
mkdir ~/example_codecd ~/example_codecurl -LO https://github.com/tensorflow/hub/raw/master/examples/image_retraining/retrain.py
在最簡單的情況下,可以這樣運行(大約需要半小時):
python retrain.py --image_dir ~/flower_photos
該腳本還有許多其他選項。 您可以通過以下方式獲得完整列表:
python retrain.py -h
此腳本加載預先訓練的模塊,并在您下載的花卉照片的頂部訓練一個新的分類器。在完整的網絡訓練過程中,原始的 ImageNet 類別中并無任何花卉種類。遷移學習的神奇之處在于,經過訓練用來區分某些對象的較低層無需任何改動,就可以重復用于多種識別任務。
瓶頸
根據機器速度,腳本可能需要 30 分鐘或更久才能完成。第一階段分析磁盤上的所有映像,并計算和緩存每個映像的瓶頸值。“瓶頸” 是一個非正式術語,我們經常在實際進行分類的最終輸出層之前使用該層。(TensorFlow Hub 將其稱為 “圖像特征向量”)倒數第二層已經過訓練,可以輸出一組足夠好的值,分類器可以用它來區分要求識別的所有類。這就意味著它必須是一個有意義的,并且緊湊的圖像摘要,畢竟它必須包含足夠的信息,以便分類器在一組非常小的值中做出正確的選擇。我們在最后一層的再訓練可以在新類上運行的原因是因為結果表明,區分 ImageNet 中所有 1,000 個類所需的信息通常也可用于區分新類型的對象。
因為每個圖像在訓練期間多次重復使用,并且計算每個瓶頸需要花費大量時間,所以它會加速將這些瓶頸值緩存到磁盤上,因此不必反復重新計算它們。默認情況下,它們存儲在 / tmp / bottleneck 目錄中,如果重新運行腳本,它們將被重用,因此您無需在此部分上流連。
訓練
一旦瓶頸完成,就開始對網絡頂層進行實際訓練。您將看到一系列步驟輸出,每一個步驟輸出均顯示訓練的準確性,并驗證準確度和交叉熵。訓練準確性顯示當前訓練批次中使用的圖像百分比標記為正確的類別。驗證準確度是來自不同組的隨機選擇的圖像組的精度。關鍵的區別在于訓練精度是基于網絡能夠學習的圖像,因此網絡可以過度擬合訓練數據中的噪音。衡量網絡性能的真正標準是測量其在訓練數據中未包含的數據集上的性能 - 這是通過驗證準確度來衡量的。如果訓練精度高但驗證精度仍然很低,則意味著網絡過度擬合并記住訓練圖像中的特定特征,這些特征對于普遍情況來說可能并無用處。交叉熵是一種損失函數,可以讓我們一瞥學習過程的進展情況。訓練的目標是盡可能減少損失,因此您可以通過關注損失是否保持向下趨勢來判斷學習是否有效,忽略短暫的噪音。
默認情況下,此腳本將運行 4,000 個訓練步驟。每個步驟從訓練集中隨機選擇十個圖像,從緩存中找到它們的瓶頸,并將它們輸入到最后一層從而獲得預測。然后將這些預測與實際標簽進行比較,通過反向傳播過程更新最終層的權重。隨著過程的繼續,您應該看到報告的準確度得到改善,并且在完成所有步驟之后,對與訓練和驗證圖片分開的一組圖像運行最終測試準確度評估。該測試評估是訓練模型將如何在分類任務上執行的最佳估計。您看到的準確度值應介于 90% 和 95% 之間,但是由于訓練過程中的隨機性,準確值會因批次不同而不同。此數字是基于完全訓練模型后給定正確標簽的測試集中圖像的百分比。
使用 TensorBoard 可視化再訓練
該腳本包含 TensorBoard 摘要,使之更容易理解、調試和優化再訓練。例如,您可以將圖形和統計數據進行可視化,諸如在訓練期間權重或準確度變化。
要啟動 TensorBoard,請在重新訓練期間或之后運行此命令:
tensorboard --logdir /tmp/retrain_logs
TensorBoard 運行后,將 Web 瀏覽器導航到 localhost:6006 以查看 TensorBoard。
rewin.py 腳本默認情況下會將 TensorBoard 摘要記錄到 / tmp / retrain_logs。您可以使用 --summaries_dir 標志更改目錄。
TensorBoard 的 GitHub 存儲庫提供了有關 TensorBoard 使用的更多信息,包括提示和技巧以及調試信息(https://github.com/tensorflow/tensorboard)。
使用再訓練模型
該腳本能夠將在您的類別上訓練的新模型寫入 /tmp/output_graph.pb,并將包含標簽的文本文件寫入 /tmp/output_labels.txt。新模型包含內嵌的 TensorFlow Hub 模塊和新的分類層。這兩個文件都采用 C ++ 和 Python 圖像分類示例可以讀入的格式,因此您可以立即開始使用新模型。由于您已經替換了頂層,因此您需要在腳本中指定新名稱,例如,如果您使用 label_image,則使用標志 --output_layer = final_result。
這里有一個示例,向我們展示了如何使用重新訓練的圖形運行 label_image 示例。按照慣例,所有 TensorFlow Hub 模塊都接受具有固定范圍 [0,1] 中顏色值的圖像輸入,因此您無需設置 --input_mean 或 --input_std 標志。
curl -LO https://github.com/tensorflow/tensorflow/raw/master/tensorflow/examples/label_image/label_image.pypython label_image.py --graph=/tmp/output_graph.pb --labels=/tmp/output_labels.txt --input_layer=Placeholder --output_layer=final_result --image=$HOME/flower_photos/daisy/21652746_cc379e0eea_m.jpg
您會看到一個花卉標簽列表,大多數情況下頂部會有菊花(雖然每個重新訓練的模型可能會略有不同)。您可以使用自己的圖像替換 --image 參數來嘗試。
如果您想在自己的 Python 程序中使用重新訓練的模型,那么上面的 label_image 腳本是一個合理的起點。label_image 目錄還包含 C ++ 代碼,您可以將其用作模板,將 TensorFlow 與您自己的應用程序集成。
如果您發現默認的 Inception V3 模塊對于您的應用程序來說太大或太慢,請查看下面的 “其他模型架構” 部分,了解加快和縮小網絡的選項。
在您自己的類別上進行訓練
如果您已經設法讓腳本處理花卉示例圖像,您就可以開始考慮教它來識別更喜歡的類別。理論上,您需要做的就是將其指向一組子文件夾,每個子文件夾以您的一個類別命名,并且僅包含該類別的圖像。如果您照做并將子目錄的根文件夾作為參數傳遞給 --image_dir,則腳本就會像對花卉一樣進行訓練。
以下是花卉存檔的文件夾結構,為您提供腳本正在尋找的布局類型示例:
實踐過程中,您想要獲得期待的準確性,可能需要一些工作。我會嘗試引導您解決下面可能遇到的一些常見問題。
創建一套訓練圖像
首先要看的是你收集的圖像,因為我們通過訓練看到的最常見的問題來自于被輸入的數據。
為了使訓練更好地運作,您至少應該收集一百張您想要識別的各種物體的照片。收集的照片越多,訓練的模型的準確性就越高。您還需要確保照片很好地代表了應用程序實際接觸到的內容。比方說,假如您的所有照片都是在室內空白墻背景拍攝,而用戶試圖識別戶外的物體,則您在部署時可能無法看到很好的結果。
另一個需要避免的缺陷是,任何與標記圖像相同的內容會對學習過程產生影響,可能你稍有不慎就會獲得一些沒用的東西。比方說,如果您在藍色房間中拍攝一種物體,而另一種物體在綠色物體中拍攝,則模型最終會根據背景顏色進行預測,而不是您實際關注的物體的特征。為避免這種情況發生,請嘗試盡可能多地在不同時間和不同設備上拍攝照片。
您也許還想再考慮一下使用的類別。那么將大量不同物理形式的大類別劃分為更具視覺沖突力的小類別就非常值得。例如,您可以使用 “汽車”,“摩托車” 和 “卡車” 代替 “車輛”。同樣值得思考的是您是否有 “封閉世界” 或 “開放世界” 問題。在一個封閉的世界中,你唯一要求分類的東西就是你所知道的對象類別。這可能適用于您知道用戶可能正在拍攝花卉照片的植物識別應用程序,因此您所要做的就是決定使用哪個物種。相比之下,漫游機器人在世界各地漫游時可以通過相機看到各式各樣的東西。在這種情況下,您應該會希望分類器報告它無法確定看到的到底是什么,這恐怕很難,如果您經常收集大量典型的 “背景” 照而其中并無相關對象,您可以將它們添加到圖像文件夾中的額外 “未知” 類。
還需要檢查來確保所有圖像都標記正確。用戶生成的標簽通常不能盡如我意。例如:標記為 #daisy 的圖片也可能包含名為 Daisy 的人物和角色。如果您瀏覽圖像并清除所有錯誤,那么整體將會出現奇跡般的準確性。
訓練步驟
如果您對圖像感到滿意,可以通過更改學習過程的詳細信息來了解改善結果的方法。最簡單的嘗試是 --how_many_training_steps。默認值為 4,000,但如果將其增加到 8,000,那么它將執行雙倍的訓練時間。提高準確度會減緩你訓練的時間,而且在某些節點會完全停止(甚至因過度擬合而出現故障),不過你可以嘗試一下,看看到底什么才是最適合你的模型。
扭曲
改善圖像訓練結果的常用方法是以隨機方式使訓練輸入變形,裁剪或增亮。對于相同圖像有著各種可能的變體的情況,這具有擴展訓練數據的有效尺寸的優點,并且傾向于幫助網絡學習應對將在分類器的實際使用過程中產生的所有失真情況。在我們的腳本中啟用這些失真的最大缺點是瓶頸緩存失效,因為輸入圖像永遠不會被完全地重用。這就意味著需要更長的時間(很多小時)的訓練過程,因此建議您在擁有一個相當滿意的模型作品之后,嘗試將此作為一種潤飾模型的方法。
通過將 --random_crop, - random_scale和--random_brightness 傳遞給腳本來啟用這些失真。 這些都是控制每個圖像應用失真的百分比值。該值從 5 或 10 開始是合理的,然后試驗看看哪些值對您的應用有幫助。 --flip_left_right 將水平地隨機鏡像一半的圖像,只要這些反轉有可能在您的應用程序中發生,那么這就是有意義的。不過,如果你試圖識別英文字母,那么這就不是一個好主意,因為翻轉之后這些含義將被破壞殆盡。
超參數
您可以嘗試調整其他幾個參數,看看是否對結果有所幫助。 --learning_rate 控制訓練期間最后一層更新的大小。 直觀地說,如果這比學習小,需要更長的時間,但是它最終可以幫助提高整體精確度。不過也非盡然,因此需要您仔細研究,看看哪種方法更適用于您的情況。 --train_batch_size 控制在每個訓練步驟中檢查的圖像數量,以估算最終圖層的更新。
訓練,驗證和測試集
當您將腳本指向圖像文件夾時,腳本所做的一件事就是將它們分成不同的三組。最大的通常是訓練集,它們是訓練期間饋入網絡的所有圖像,其結果用來更新模型的權重。 您也許想知道為什么我們不使用所有的圖像進行訓練? 當我們進行機器學習時,有一個很大的潛在問題是:我們的模型可能只是記住訓練圖像的不相關細節,從而得出正確的答案。例如,您可以想象一個網絡在其顯示的每張照片的背景中記住一個圖案,并用它來匹配標簽與對象。它可能在訓練過程中對以前看到過的所有圖像能夠產生很好的結果,但是在新的圖像上則以失敗告終,究其原因是因為它沒有學習到對象的普通特征,只是記住了訓練圖像的次要細節。
這個問題被稱為過度擬合,為了避免這個問題,我們將一些數據保留在訓練過程之外,這樣模型就無法記住它們。 然后我們使用這些圖像作為檢查以確保不會發生過度擬合,因為如果我們看到它們具有良好的準確性,則表明網絡沒有過度擬合,這是一個好兆頭。通常的分割是將 80% 的圖像放入主訓練集中,保留 10% 以備在訓練期間能夠經常運行用來驗證,剩下的 10% 則作為測試集用于預測分類器在現實世界的表現。可以使用 --testing_percentage 和 --validation_percentage 標志來控制這些比率。一般情況下,將這些值保留為默認值,因為通常調整它們不會對訓練有任何優勢。
請注意,該腳本使用圖像的文件名(而不是完全隨機的函數)在訓練、驗證和測試集之間劃分圖像。這樣做是為了確保圖像不會在分別運行的訓練集和測試集之間移動,因為如果用于訓練模型的圖像隨后在驗證集中使用,那么這有可能會出現問題。
您可能會注意到驗證準確度在迭代之間波動。大部分這種波動源于這樣的事實:為每個驗證精度測量選擇驗證集的隨機子集。通過選擇 --validation_batch_size = -1,使用整個驗證集進行每次精度計算,可以大大減少波動,但是代價是訓練時間有所增加。
訓練完成后,您會發現它在測試檢查集中錯誤分類的圖像時獨具慧眼。可以通過添加標志 --print_misclassified_test_images 來完成。這可以幫助您了解哪種類型的圖像最容易混淆模型,哪些類別最難以區分。例如,您可能會發現特定類別的某些子類型或某些不尋常的照片角度特別難以識別,這可能會激發您為該子類型添加更多的訓練圖像。通常,檢查錯誤分類的圖像也可能指向輸入數據集中的錯誤,例如錯誤標記,低質量或模糊圖像。然而,通常應該避免在測試集中修正個別錯誤,因為它們不太會反映(更大型的)訓練集中的那些更普遍的問題。
其他模型架構
默認情況下,腳本使用帶有 Inception V3 體系結構預訓練實例的圖像特征提取模塊。這是一個很好的起點,因為它為再訓練腳本提供了高精度的結果和適中的運行時間。但是現在讓我們來看看 TensorFlow Hub 模塊的其他選項
一方面,該列表顯示了更新的,功能更強大的體系結構,例如 NASNet(特別是 nasnet_large 和 pnasnet_large),可以為您提供額外的精確度。
另一方面,如果您打算在移動設備或其他資源受限的環境中部署模型,您可能希望以更小的文件大小或更快的速度(也在訓練中)來交換一點精確度。為此,試試不同的模塊實現 MobileNet V1 或 V2 架構,或者 nasnet_mobile。
使用不同模塊進行訓練很簡單:只需將 --tfhub_module 標志與模塊 URL 一起傳遞,例如:
python retrain.py --image_dir ~/flower_photos --tfhub_module https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/2
這將在 /tmp/output_graph.pb 中創建一個 9 MB 的模型文件,其中的模型使用 MobileNet V2 的基線版本。在瀏覽器中打開模塊 URL 將轉到模塊文檔。
如果您只是想讓它快一點,您可以將輸入圖像(第二個數字)的大小從 '224' 減小到 '192','160' 或 '128' 像素的平方,甚至 '96' (僅適用于 V2)。為了獲得更大幅度地節省,您可以選擇百分比(第一個數字)'100','075','050' 或 '035'(V1 的 '025')來控制 “特征深度” 或神經元的每個位置數量。權重的數量(以及文件大小和速度)隨著該分數的平方而縮小。GitHub 上的 MobileNet V1 博文和 MobileNet V2 頁面上報道了 Imagenet 分類的各自權衡。
Mobilenet V2 不會將功能深度百分比應用于瓶頸層。在 Mobilenet V1 會將功能百分比應用于瓶頸層,對小深度來說,分類層的工作就顯得困難重重。Mobilenet V2 是否有助于瞞天過海并使用原始 1001 ImageNet 類得分,而非應用于嚴格的瓶頸? 您可以嘗試將 removenet_v1 ... / feature_vector 替換為模塊名稱中的 mobilenet_v1 ... / classification。
和之前一樣,您可以將所有重新訓練的模型與 label_image.py 一起使用。您需要指定模型所需的圖像大小,例如:
python label_image.py --graph=/tmp/output_graph.pb --labels=/tmp/output_labels.txt --input_layer=Placeholder --output_layer=final_result --input_height=224 --input_width=224 --image=$HOME/flower_photos/daisy/21652746_cc379e0eea_m.jpg
有關將重新訓練的模型部署到移動設備的更多信息,請參閱本教程的 codelab 版本(https://codelabs.developers.google.com/codelabs/tensorflow-for-poets/?hl=zh-CN#0),特別是第 2 部分, 介紹了 TensorFlow Lite 及其提供的其他優化(包括模型權重的量化)。
-
圖像
+關注
關注
2文章
1087瀏覽量
40503 -
分類器
+關注
關注
0文章
152瀏覽量
13202 -
遷移學習
+關注
關注
0文章
74瀏覽量
5572
原文標題:如何為新類別重新訓練一個圖像分類器
文章出處:【微信號:tensorflowers,微信公眾號:Tensorflowers】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論