?譯者 | 朱先忠
審校 | 孫淑娟
遷移學(xué)習(xí)是機(jī)器學(xué)習(xí)的一種類型,它是一種應(yīng)用于已經(jīng)訓(xùn)練或預(yù)訓(xùn)練的神經(jīng)網(wǎng)絡(luò)的方法,而且這些預(yù)訓(xùn)練的神經(jīng)元網(wǎng)絡(luò)是使用數(shù)百萬(wàn)個(gè)數(shù)據(jù)點(diǎn)訓(xùn)練出來(lái)的。
該技術(shù)目前最著名的用法是用來(lái)訓(xùn)練深度神經(jīng)網(wǎng)絡(luò),因?yàn)檫@種方法在使用較少的數(shù)據(jù)訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)時(shí)表現(xiàn)出良好的性能。實(shí)際上,這種技術(shù)在數(shù)據(jù)科學(xué)領(lǐng)域也是很有用的,因?yàn)榇蠖鄶?shù)真實(shí)世界的數(shù)據(jù)通常沒(méi)有數(shù)百萬(wàn)個(gè)數(shù)據(jù)點(diǎn)來(lái)訓(xùn)練出穩(wěn)固的深度學(xué)習(xí)模型。
目前,已經(jīng)存在許多使用數(shù)百萬(wàn)個(gè)數(shù)據(jù)點(diǎn)訓(xùn)練出來(lái)的模型,并且這些模型可以用于以最大精度來(lái)訓(xùn)練復(fù)雜的深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)。
在本教程中,您將學(xué)習(xí)到如何使用遷移學(xué)習(xí)技術(shù)來(lái)訓(xùn)練一個(gè)深度神經(jīng)網(wǎng)絡(luò)的完整過(guò)程。
使用Keras程序?qū)崿F(xiàn)遷移學(xué)習(xí)
在構(gòu)建或訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)之前,您必須搞清楚有哪些選擇方案可用于遷移學(xué)習(xí),以及必須使用哪個(gè)方案來(lái)為項(xiàng)目訓(xùn)練復(fù)雜的深度神經(jīng)網(wǎng)絡(luò)。
Keras應(yīng)用程序是一種高級(jí)的深度學(xué)習(xí)模型,它提供了可用于預(yù)測(cè)、特征提取和微調(diào)的預(yù)訓(xùn)練權(quán)重。Keras庫(kù)中內(nèi)置提供了許多現(xiàn)成可用的模型,其中一些流行的模型包括:
- Xception
- VGG16 and VGG19
- ResNet Series
- MobileNet
【補(bǔ)充】Keras應(yīng)用程序提供了一組深度學(xué)習(xí)模型,它們可與預(yù)先訓(xùn)練的權(quán)重一起使用。有關(guān)這些模型的更具體的內(nèi)容,請(qǐng)參考??Keras官網(wǎng)內(nèi)容??。
在本文中,您將學(xué)習(xí)??MobileNet模型??在遷移學(xué)習(xí)中的應(yīng)用。
訓(xùn)練一個(gè)深度學(xué)習(xí)模型
在本節(jié)中,您將學(xué)習(xí)如何在短短的幾個(gè)步驟內(nèi)為圖像識(shí)別構(gòu)建一個(gè)自定義深度學(xué)習(xí)模型,而無(wú)需編寫任何一系列卷積神經(jīng)網(wǎng)絡(luò)(CNN),您只需對(duì)預(yù)訓(xùn)練的模型加以微調(diào),即可使得您的模型在訓(xùn)練數(shù)據(jù)集上進(jìn)行訓(xùn)練。
在本文中,我們構(gòu)建的深度學(xué)習(xí)模型將能夠識(shí)別手勢(shì)語(yǔ)言數(shù)字的圖像。接下來(lái),讓我們開(kāi)始著手構(gòu)建這個(gè)自定義深度學(xué)習(xí)模型。
獲取數(shù)據(jù)集
要開(kāi)始構(gòu)建一個(gè)深度學(xué)習(xí)模型的過(guò)程,您首先需要準(zhǔn)備好數(shù)據(jù),您可以通過(guò)訪問(wèn)一個(gè)名為Kaggle的網(wǎng)站,從數(shù)百萬(wàn)個(gè)數(shù)據(jù)集中輕松選擇合適的數(shù)據(jù)集。當(dāng)然,也存在不少其他網(wǎng)站為構(gòu)建深度學(xué)習(xí)或機(jī)器學(xué)習(xí)模型提供可用的數(shù)據(jù)集。
但本文將使用的數(shù)據(jù)集取自Kaggle網(wǎng)站提供的??美國(guó)手語(yǔ)數(shù)字?jǐn)?shù)據(jù)集??。
數(shù)據(jù)預(yù)處理
在下載數(shù)據(jù)集并將其保存到本地存儲(chǔ)之后,現(xiàn)在是時(shí)候?qū)?shù)據(jù)集執(zhí)行一些預(yù)處理了,比如準(zhǔn)備數(shù)據(jù)、將數(shù)據(jù)拆分為train目錄、valid目錄和test目錄、定義它們的路徑以及為訓(xùn)練目的創(chuàng)建批處理,等等。
準(zhǔn)備數(shù)據(jù)
下載數(shù)據(jù)集時(shí),它包含從0到9數(shù)據(jù)的目錄,其中有三個(gè)子文件夾分別對(duì)應(yīng)輸入圖像、輸出圖像以及一個(gè)名稱為CSV的文件夾。
接著,從每個(gè)目錄中刪除輸出圖像和CSV文件夾,將輸入圖像文件夾下的內(nèi)容移動(dòng)到主目錄下,然后刪除輸入圖像文件夾。
數(shù)據(jù)集的每個(gè)主目錄現(xiàn)在都擁有500幅圖像,您可以選擇保留所有圖像。但出于演示目的,本文中每個(gè)目錄中只使用其中的200幅圖像。
最終,數(shù)據(jù)集的結(jié)構(gòu)將如下圖所示:
數(shù)據(jù)集的文件夾結(jié)構(gòu)
分割數(shù)據(jù)集
現(xiàn)在,讓我們從將數(shù)據(jù)集拆分為train、valid和test三個(gè)子目錄開(kāi)始。
- train目錄將包含訓(xùn)練數(shù)據(jù),這些數(shù)據(jù)將作為我們輸入模型的輸入數(shù)據(jù),用于學(xué)習(xí)模式和不規(guī)則性。
- valid目錄將包含將被輸入到模型中的驗(yàn)證數(shù)據(jù),并且將是模型所看到的第一個(gè)未看到的數(shù)據(jù),這將有助于獲得最大的準(zhǔn)確性。
- test目錄將包含用于測(cè)試模型的測(cè)試數(shù)據(jù)。
首先,我們來(lái)導(dǎo)入將在代碼中進(jìn)一步使用的庫(kù)。
下面是生成所需目錄并將數(shù)據(jù)移動(dòng)到特定目錄的代碼。
在上面的代碼中,我們首先更改了數(shù)據(jù)集在本地存儲(chǔ)中對(duì)應(yīng)的目錄,然后檢查是否已經(jīng)存在train/0目錄;如果沒(méi)有,我們將分別創(chuàng)建train、valid和test子目錄。
然后,我們創(chuàng)建子目錄0到9,并將所有數(shù)據(jù)移動(dòng)到train目錄中,同時(shí)創(chuàng)建了valid和test這兩個(gè)子目錄下各自的子目錄0至9。
然后,我們?cè)趖rain目錄內(nèi)的子目錄0到9上進(jìn)行迭代,并從每個(gè)子目錄中隨機(jī)獲取90個(gè)圖像數(shù)據(jù),并將它們移動(dòng)到valid目錄內(nèi)的相應(yīng)子目錄。
對(duì)于測(cè)試目錄test也是如此。
【補(bǔ)充】在Python中執(zhí)行高級(jí)文件操作的shutil模塊(手動(dòng)將文件或文件夾從一個(gè)目錄復(fù)制或移動(dòng)到另一個(gè)目錄可能是一件非常痛苦的事情。有關(guān)詳細(xì)技巧,請(qǐng)參考文章https://medium.com/@geekpython/perform-high-level-file-operations-in-python-shutil-module-dfd71b149d32)。
定義到各目錄的路徑
創(chuàng)建所需的目錄后,現(xiàn)在需要定義train、valid和test這三個(gè)子目錄的路徑。
進(jìn)行預(yù)處理
預(yù)訓(xùn)練的深度學(xué)習(xí)模型需要一些預(yù)處理的數(shù)據(jù),這些數(shù)據(jù)非常適合訓(xùn)練。因此,數(shù)據(jù)需要采用預(yù)訓(xùn)練模型所需的格式。
在應(yīng)用任何預(yù)處理之前,讓我們導(dǎo)入TensorFlow及其實(shí)用程序,這些實(shí)用程序?qū)⒃诖a中進(jìn)一步使用。
我們使用了ImageDatagenerator,它采用了一個(gè)參數(shù)preprocessing_function,在該函數(shù)參數(shù)中,我們對(duì)MobileNet模型提供的圖像進(jìn)行了預(yù)處理。
接下來(lái),調(diào)用flow_from_directory函數(shù),其中我們提供了要訓(xùn)練圖像的目錄和維度的路徑,因?yàn)镸obileNet模型是為具有224x224維度的圖像訓(xùn)練使用的。
再接下來(lái),定義了批量大小——定義一次迭代中可以處理多少圖像,然后我們對(duì)圖像處理順序進(jìn)行隨機(jī)打亂。在此,我們沒(méi)有針對(duì)測(cè)試數(shù)據(jù)的圖像進(jìn)行隨機(jī)亂序,因?yàn)闇y(cè)試數(shù)據(jù)不會(huì)用于訓(xùn)練。
在Jupyter筆記本或Google Colab中運(yùn)行上述代碼片斷后,您將看到如下結(jié)果。
上述代碼的輸出結(jié)果
ImageDataGenerator的一般應(yīng)用場(chǎng)景是用于增廣數(shù)據(jù),以下是使用Keras框架中ImageDataGenerator執(zhí)行數(shù)據(jù)增廣的??指南??。
創(chuàng)建模型
在將訓(xùn)練和驗(yàn)證數(shù)據(jù)擬合到模型中之前,深度學(xué)習(xí)模型MobileNet需要通過(guò)添加輸出層、刪除不必要的層以及使某些層不可訓(xùn)練,從而獲得更好的準(zhǔn)確性來(lái)進(jìn)行微調(diào)。
以下代碼將從Keras下載MobileNet模型并將其存儲(chǔ)在mobile變量中。您需要在第一次運(yùn)行以下代碼片斷時(shí)連接到因特網(wǎng)。
如果您運(yùn)行以下代碼,那么您將看到模型的摘要信息,在其中你可以看到一系列神經(jīng)網(wǎng)絡(luò)層的輸出信息。
現(xiàn)在,我們將在模型中添加以10為單位的全連接輸出層(也稱“稠密層”)——因?yàn)閺?到9將有10個(gè)輸出。此外,我們從MobileNet模型中刪除了最后六個(gè)層。
然后,我們將所有輸入和輸出層添加到模型中。
現(xiàn)在,我們將最后23層設(shè)置成不可訓(xùn)練的——其實(shí)這是一個(gè)相對(duì)隨意的數(shù)字。一般來(lái)說(shuō),這一具體數(shù)字是通過(guò)多次試驗(yàn)和錯(cuò)誤獲得的。該代碼的唯一目的是通過(guò)使某些層不可訓(xùn)練來(lái)提高精度。
如果您看到了微調(diào)模型的摘要輸出,那么您將注意到與前面看到的原始摘要相比,不可訓(xùn)練參數(shù)和層的數(shù)量存在一些差異。
接下來(lái),我們要編譯名為Adam的優(yōu)化器,選擇學(xué)習(xí)率為0.0001,以及損失函數(shù),還有衡量模型的準(zhǔn)確性的度量參數(shù)。
現(xiàn)在是準(zhǔn)備好模型并根據(jù)訓(xùn)練和驗(yàn)證數(shù)據(jù)來(lái)開(kāi)始訓(xùn)練的時(shí)候了。在下面的代碼中,我們提供了訓(xùn)練和驗(yàn)證數(shù)據(jù)以及訓(xùn)練的總體輪回?cái)?shù)。詳細(xì)信息只是為了顯示準(zhǔn)確性進(jìn)度,在這里您可以指定一個(gè)數(shù)字參數(shù)值為0、1或者2。
如果您運(yùn)行上面的代碼片斷,那么您將看到訓(xùn)練數(shù)據(jù)丟失和準(zhǔn)確性的輪回的每一步的輸出內(nèi)容。對(duì)于驗(yàn)證數(shù)據(jù),您也能夠看到這樣的輸出結(jié)果。
顯示有精度值的訓(xùn)練輪回步數(shù)
存儲(chǔ)模型
該模型現(xiàn)在已準(zhǔn)備就緒,準(zhǔn)確度得分為99%?,F(xiàn)在請(qǐng)記住一件事:這個(gè)模型可能存在過(guò)度擬合,因此有可能對(duì)于給定數(shù)據(jù)集圖像以外的圖像表現(xiàn)不佳。
上面的代碼將檢查是否已經(jīng)有模型的副本。如果沒(méi)有,則通過(guò)調(diào)用save函數(shù)在指定的路徑中保存模型。
測(cè)試模型
至此,模型已經(jīng)經(jīng)過(guò)訓(xùn)練,可以用于識(shí)別圖像了。本節(jié)將介紹加載模型和編寫準(zhǔn)備圖像、預(yù)測(cè)結(jié)果以及顯示和打印預(yù)測(cè)結(jié)果的函數(shù)。
在編寫任何代碼之前,需要導(dǎo)入一些將在代碼中進(jìn)一步使用的必要的庫(kù)。
加載定制的模型
對(duì)圖像的預(yù)測(cè)將使用上面使用遷移學(xué)習(xí)技術(shù)創(chuàng)建的模型進(jìn)行。因此,我們首先需要加載該模型,以供后面使用。
在此,我們通過(guò)使用load_model函數(shù),實(shí)現(xiàn)從指定路徑加載模型,并將其存儲(chǔ)在my_model變量中,以便在后面代碼中進(jìn)一步使用。
準(zhǔn)備輸入圖像
在向模型提供任何用于預(yù)測(cè)或識(shí)別的圖像之前,我們需要提供模型所需的格式。
首先,我們要定義一個(gè)獲取圖像路徑的函數(shù)preprocess_img,然后使用image實(shí)用程序中的load_img函數(shù)加載該圖像,并將目標(biāo)大小設(shè)置為224x224。然后將該圖像轉(zhuǎn)換成一個(gè)數(shù)組,并將該數(shù)組除以255.0,這樣就將圖像的像素值轉(zhuǎn)換為0和1,然后將圖像數(shù)組重新調(diào)整為形狀(224,224,3),最后返回轉(zhuǎn)換形狀后的圖像。
編寫預(yù)測(cè)函數(shù)
這里,我們定義了一個(gè)函數(shù)predict_result,它接受predict參數(shù),此參數(shù)基本上是一個(gè)預(yù)處理的圖像。然后,我們調(diào)用模型的predict函數(shù)來(lái)預(yù)測(cè)結(jié)果。最后,從預(yù)測(cè)結(jié)果中返回最大值。
顯示與預(yù)測(cè)圖像
首先,我們將創(chuàng)建一個(gè)函數(shù),它負(fù)責(zé)獲取圖像的路徑,然后顯示圖像和預(yù)測(cè)結(jié)果。
上面這個(gè)函數(shù)display_and_predict首先獲取圖像的路徑并使用PIL庫(kù)中的Image.open函數(shù)打開(kāi)該圖像,然后使用matplotlib庫(kù)來(lái)顯示圖像,然后將圖像傳遞給preprep_img函數(shù)以便輸出預(yù)測(cè)結(jié)果,最后使用predict_result函數(shù)獲得結(jié)果并最終打印。
如果您運(yùn)行上面的程序片斷并輸入數(shù)據(jù)集中圖像的路徑,那么您將得到所期望的輸出。
預(yù)測(cè)結(jié)果示意圖
請(qǐng)注意,到目前為止該模型是使用遷移學(xué)習(xí)技術(shù)成功創(chuàng)建的,而無(wú)需編寫任何一系列神經(jīng)網(wǎng)絡(luò)層相關(guān)代碼。
現(xiàn)在,這個(gè)模型可以用于開(kāi)發(fā)能夠進(jìn)行圖像識(shí)別的Web應(yīng)用程序了。文章的最后所附鏈接處提供了如何將該模型應(yīng)用到Flask應(yīng)用程序中的完整實(shí)現(xiàn)源碼。
結(jié)論
本文中我們介紹了使用預(yù)先訓(xùn)練的模型或遷移學(xué)習(xí)技術(shù)來(lái)制作一個(gè)定制的深度學(xué)習(xí)模型的過(guò)程。
到目前為止,您已經(jīng)了解了創(chuàng)建一個(gè)完整的深度學(xué)習(xí)模型所涉及的每一步。歸納起來(lái)看,所使用的總體步驟包括:
- 準(zhǔn)備數(shù)據(jù)集
- 預(yù)處理數(shù)據(jù)
- 創(chuàng)建模型
- 保存自定義模型
- 測(cè)試自定義模型
最后,您可以從??GitHub??上獲取本文示例項(xiàng)目完整的源代碼。
譯者介紹
朱先忠,51CTO社區(qū)編輯,51CTO專家博客、講師,濰坊一所高校計(jì)算機(jī)教師,自由編程界老兵一枚。
原文標(biāo)題:??Trained A Custom Deep Learning Model Using A Transfer Learning Technique???,作者:Sachin Pal?