10分鐘帶你打開深度學(xué)習(xí)大門,代碼已開源
本文經(jīng)AI新媒體量子位(公眾號(hào)ID:QbitAI)授權(quán)轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)聯(lián)系出處。
深度學(xué)習(xí)技術(shù)的不斷普及,越來(lái)越多的語(yǔ)言可以用來(lái)進(jìn)行深度學(xué)習(xí)項(xiàng)目的開發(fā),即使是JavaScript這樣曾經(jīng)只是在瀏覽器中運(yùn)行的用于處理輕型任務(wù)的腳本語(yǔ)言。
TensorFlow.js是谷歌推出的基于JavaScript的深度學(xué)習(xí)框架,它提供的高級(jí)API使得開發(fā)可以直接在瀏覽器中運(yùn)行的深度學(xué)習(xí)算法變得輕而易舉。
這不,美國(guó)的一位老哥Gant Laborde使用TensorFlow.js開發(fā)了一款是用深度學(xué)習(xí)技術(shù)在瀏覽器中識(shí)別“石頭剪刀布”游戲手勢(shì)的網(wǎng)頁(yè)應(yīng)用,放出了demo并將代碼開源在了Github上。
對(duì)于JavaScript開發(fā)者來(lái)說(shuō),這是打開深度學(xué)習(xí)大門的極佳入門教材。只需10分鐘,你就可以訓(xùn)練一個(gè)準(zhǔn)確率可觀的手勢(shì)識(shí)別模型,并且調(diào)用攝像頭對(duì)實(shí)時(shí)視頻中的手勢(shì)進(jìn)行識(shí)別。

△使用運(yùn)行在瀏覽器中的深度學(xué)習(xí)模型識(shí)別手勢(shì)
在一切開始之前
在打開新世界的大門之前,我們總是需要做一些準(zhǔn)備工作。
在這里,給大家簡(jiǎn)單地介紹一下典型的深度學(xué)習(xí)算法的開發(fā)步驟,目的是希望讀者們?cè)诮酉聛?lái)的操作中明確地知道自己在做什么,而不僅僅是點(diǎn)幾個(gè)按鈕罷了。
這里不會(huì)涉及任何艱澀的數(shù)學(xué)公式,請(qǐng)放心食用。
我們平常所說(shuō)的深度學(xué)習(xí)算法,更確切地說(shuō),應(yīng)該是基于深度神經(jīng)網(wǎng)絡(luò)的算法(或者說(shuō)模型)。
這里并不需要知道深度神經(jīng)網(wǎng)絡(luò)究竟是個(gè)什么東西(你可能需要再花百倍于此的時(shí)間才有可能搞明白其具體原理),只需要知道,它可以視作是一個(gè)函數(shù)f,一個(gè)很難用簡(jiǎn)單公式表達(dá)出來(lái)的函數(shù)。
所謂函數(shù),就要有自變量x和因變量y。
自變量x,我們一般稱之為輸入(input),在這個(gè)問題中就是一張做出“石頭”、“剪刀”或“布”手勢(shì)的手的圖像。
而因變量y,我們一般稱之為輸出(output),在這個(gè)問題中是三個(gè)取值為0-1的數(shù)值,分別對(duì)應(yīng)輸入手勢(shì)是“石頭”、“剪刀”和“布”的概率。
我們依靠這個(gè)函數(shù)f得到我們想要的結(jié)果,但是f并不是天上掉下來(lái)的,它由人為選取的模型和(大量的)模型參數(shù)組成。
其中模型參數(shù)往往由大量數(shù)據(jù)學(xué)習(xí)得到,這個(gè)讓模型學(xué)習(xí)參數(shù)的過程我們稱之為模型訓(xùn)練(train),是深度學(xué)習(xí)算法開發(fā)中最關(guān)鍵的一步。
在這個(gè)問題中,我們需要大量(x,y)數(shù)據(jù)對(duì)來(lái)進(jìn)行訓(xùn)練,也就是大量(圖像,手勢(shì))數(shù)據(jù)對(duì),如(圖像1,剪刀)、(圖像2、石頭)、(圖像3、布)…… 這些數(shù)據(jù)對(duì)往往需要由人為搜集、標(biāo)注得到。
我們可以通過一些評(píng)估指標(biāo)來(lái)衡量模型的好壞程度,比如在這個(gè)問題中,手勢(shì)識(shí)別的準(zhǔn)確度。通過這些評(píng)估指標(biāo)我們可以驗(yàn)證(validate)模型是否經(jīng)過了充分的訓(xùn)練、效果有沒有達(dá)到我們的預(yù)期。如果是,我們可以將其部署投入使用,測(cè)試其在現(xiàn)實(shí)情況中的表現(xiàn)。
總結(jié)來(lái)說(shuō),一個(gè)深度學(xué)習(xí)算法的開發(fā),需要經(jīng)過數(shù)據(jù)準(zhǔn)備、模型選擇與訓(xùn)練、模型效果評(píng)估、模型測(cè)試這四個(gè)階段。
現(xiàn)在,正式開始!
數(shù)據(jù)準(zhǔn)備
我們之前提到,需要大量的(圖像,手勢(shì))數(shù)據(jù)對(duì)來(lái)進(jìn)行模型的訓(xùn)練。搜集這樣的數(shù)據(jù)無(wú)疑是一個(gè)繁瑣的工作,拍照、標(biāo)注……
幸運(yùn)的是,谷歌工程師Laurence Moroney為我們提供了這樣一個(gè)數(shù)據(jù)集,其中包含了白色背景下的三種手勢(shì)共2892張圖像及對(duì)應(yīng)的手勢(shì)標(biāo)簽,一些例子:
△Moroney提供的數(shù)據(jù)集的一些例子
數(shù)據(jù)集網(wǎng)址:
http://www.laurencemoroney.com/rock-paper-scissors-dataset/
一切看似都是這么的順利。等等,我們?cè)趺窗堰@么一坨圖像搞進(jìn)瀏覽器里去?
在瀏覽器里執(zhí)行JavaScript,好像并不能從本地讀取文件。
一個(gè)顯見的想法是,我們把訓(xùn)練數(shù)據(jù)當(dāng)做網(wǎng)頁(yè)中的圖片,讀進(jìn)DOM的img元素中。我們先將訓(xùn)練數(shù)據(jù)中每一張圖像“拉直“成1像素高的圖像,再將所有圖像一行一行堆疊在一起。
比如我們?cè)瓐D大小為64x64,“拉直”之后尺寸為1x4096,訓(xùn)練集的2520張圖像堆疊后形成大小為4096x2520的巨大圖像(雖然它在視覺上已經(jīng)失去了意義),像下面這樣。
這張巨大圖像被稱為精靈表單(sprite-sheet),包含了許多小圖像。
這個(gè)網(wǎng)頁(yè)應(yīng)用的作者提供了生成sprite-sheet的Python代碼,在github倉(cāng)庫(kù)根目錄的spritemaker文件夾下。
△生成的尺寸為4096x2520的sprite-sheet
在demo頁(yè)面中,點(diǎn)擊“Load and Show Examples(讀取數(shù)據(jù)并展示樣例)”按鈕,等待一陣,我們可以看到數(shù)據(jù)被讀入了瀏覽器,并且出現(xiàn)了一個(gè)側(cè)邊欄,其中展示了42張從數(shù)據(jù)集中隨機(jī)選取的圖像。
這個(gè)側(cè)邊欄由TensorFlow Visor提供,可以幫助我們直觀地觀察模型的訓(xùn)練過程,我們可以隨時(shí)按下鍵盤左上方的`鍵切出或隱藏該面板。
△TensorFlow Visor界面中展示的數(shù)據(jù)樣例
模型選擇、訓(xùn)練與效果評(píng)估
接下來(lái)我們將面臨抉擇。
兩個(gè)按鈕擺在我們的面前,“Create Simple Model(創(chuàng)建簡(jiǎn)單模型)”和“Create Advance Model(創(chuàng)建高級(jí)模型)”。

先從簡(jiǎn)單的來(lái)吧,我們點(diǎn)擊“Create Simple Model”。按`鍵切出TensorFlow Visor面板,可以看到上面出現(xiàn)了剛剛創(chuàng)建的簡(jiǎn)單模型的網(wǎng)絡(luò)結(jié)構(gòu),這是一個(gè)5層的卷積神經(jīng)網(wǎng)絡(luò)模型(Flatten層不計(jì)入層數(shù)),你只需要知道它可以看做是一個(gè)一個(gè)相對(duì)簡(jiǎn)單函數(shù)的堆疊,并且這確實(shí)是一個(gè)非常簡(jiǎn)單基礎(chǔ)的卷積神經(jīng)網(wǎng)絡(luò)模型。

△TensorFlow Visor界面中展示的網(wǎng)絡(luò)結(jié)構(gòu)
點(diǎn)擊“Check Untrained Model Results(查看未訓(xùn)練模型結(jié)果)”,面板中出現(xiàn)了一個(gè)Accuracy(準(zhǔn)確率)表格,和一個(gè)矩陣,它們就是這個(gè)問題中我們對(duì)于模型的評(píng)價(jià)指標(biāo)。
準(zhǔn)確率表格中,每一行是一個(gè)手勢(shì)類別的準(zhǔn)確率值;矩陣中,手勢(shì)X的行和手勢(shì)Y的列確定的單元格代表實(shí)際是手勢(shì)X,被算法認(rèn)為是手勢(shì)Y的圖像數(shù)量,這樣的矩陣我們叫做“混淆矩陣”,因?yàn)樗宫F(xiàn)了算法對(duì)于兩兩手勢(shì)容易搞混的程度。
可以看到,因?yàn)槲覀兊哪P瓦€沒有進(jìn)行訓(xùn)練,所以算法認(rèn)為所有輸入圖像中的手勢(shì)都是“剪刀”,它還很懵懂。
那么就開始訓(xùn)練它吧!點(diǎn)擊“Train Your Simple Model(訓(xùn)練簡(jiǎn)單模型)”!TensorFlow Visor面板中出現(xiàn)了“Model Training(模型訓(xùn)練)”一欄,展示了訓(xùn)練中實(shí)時(shí)的準(zhǔn)確率(Accuracy)和損失(Loss)值,正常情況下,我們應(yīng)該可以看到隨著訓(xùn)練的進(jìn)行,準(zhǔn)確率不斷上升,而損失不斷下降。訓(xùn)練在12個(gè)epoch(60個(gè)batch)后停止。

△TensorFlow Visor界面中展示的訓(xùn)練進(jìn)程
訓(xùn)練結(jié)束后,點(diǎn)擊“Check Model After Training(查看訓(xùn)練后模型結(jié)果)”。在原來(lái)的準(zhǔn)確率表格和混淆矩陣下方出現(xiàn)了訓(xùn)練后模型的準(zhǔn)確率(Trained Accuracy)和混淆矩陣(Trained Confusion Matrix)。
Amazing!訓(xùn)練后,模型在驗(yàn)證數(shù)據(jù)上對(duì)于三種手勢(shì)的識(shí)別準(zhǔn)確率都超過了95%,混淆矩陣也是健康的(對(duì)角線深,其余淺)。

△TensorFlow Visor界面中展示的訓(xùn)練后模型效果
你也許會(huì)想,“高級(jí)的東西總比簡(jiǎn)單的東西好吧?高級(jí)模型效果一定更好。” 其實(shí)這是一個(gè)常見的誤區(qū)。
如果你選擇“Create Advance Model(創(chuàng)建高級(jí)模型)”,重復(fù)上述操作,會(huì)發(fā)現(xiàn)高級(jí)模型不僅訓(xùn)練時(shí)間更長(zhǎng),效果也不如簡(jiǎn)單模型那么好。
更進(jìn)一步,高級(jí)模型如果訓(xùn)練時(shí)間過長(zhǎng),會(huì)出現(xiàn)過擬合(overfitting)的情況。
過擬合是指,模型太注重完美擬合訓(xùn)練數(shù)據(jù),導(dǎo)致其雖然在訓(xùn)練數(shù)據(jù)上的表現(xiàn)極佳,但是對(duì)于訓(xùn)練數(shù)據(jù)之外它沒有見過的數(shù)據(jù)效果較差,或者我們也會(huì)說(shuō)模型此時(shí)的泛化(generalize)能力較差。
模型測(cè)試
既然已經(jīng)有了一個(gè)表現(xiàn)很不錯(cuò)的簡(jiǎn)單模型,那么讓我們立刻將它投入使用吧!
點(diǎn)擊“Launch Webcam(打開攝像頭)”,對(duì)準(zhǔn)一面白墻,對(duì)著攝像頭做出不同的手勢(shì),應(yīng)用會(huì)定時(shí)捕捉視頻圖像,通過訓(xùn)練好的模型算法,告訴你當(dāng)前手勢(shì)屬于三種類別的概率,是不是很酷炫呢?

△使用已訓(xùn)練模型識(shí)別視頻中的手勢(shì)
Done!
至此,你已經(jīng)在完全在瀏覽器中訓(xùn)練了一個(gè)用于手勢(shì)分類的深度學(xué)習(xí)模型,通過一些指標(biāo)驗(yàn)證了它的有效性,并且在現(xiàn)實(shí)情境中對(duì)它進(jìn)行了測(cè)試。
盡管這些步驟很簡(jiǎn)單,但你了解它們?cè)谧鍪裁?mdash;—歡迎來(lái)到深度學(xué)習(xí)的世界!
傳送門
源代碼倉(cāng)庫(kù):
https://github.com/GantMan/rps_tfjs_demo
Demo頁(yè)面:
https://rps-tfjs.netlify.com/