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

評論