我不知道為什么會有這樣的想法,我自己既不失聰,也不失語,而且周圍也沒有這樣的人,我甚至連語音助手也沒有。究其原因,或許是因為有很多文章都在介紹層出不窮的語音助手,也可能是因為各大公司都在爭相成為您青睞的智能家居語音助手,又或許只是因為我越來越多地在朋友家中的桌臺上看到這些設(shè)備。這個問題在我的腦海中一直縈繞不去,我知道這件事勢在必行。
于是,最后有了這個項目。這是一個概念驗證項目,我買了一個Amazon Echo,讓它對手語作出反應(yīng),更準(zhǔn)確地說是美國手語 (ASL),因為和口語一樣,手語的種類也有很多。
原本我可以只發(fā)布代碼,不過,我覺得很多機(jī)器學(xué)習(xí)項目都缺少視覺元素,讓人們很難將它們聯(lián)系起來理解,所以后來還是決定發(fā)布一段關(guān)于系統(tǒng)演示的視頻。同時,我也希望這個方法能夠?qū)⑷藗冴P(guān)注的焦點(diǎn)從項目的科技元素轉(zhuǎn)向人類元素,即這里介紹的并非底層技術(shù),而是此類技術(shù)賦予我們?nèi)祟惖哪芰Α?/p>
既然視頻已經(jīng)公開,下面就通過這篇博文介紹一下底層技術(shù),以及如何使用TensorFlow.js構(gòu)建這一系統(tǒng)。您也可以播放實(shí)時演示。我將其整合在了一起,以便您可以使用自己的詞集和符號/手勢組合來訓(xùn)練。是否要在身邊準(zhǔn)備一個可以響應(yīng)您要求的 Echo,完全由您自選。
早期研究
在早期,我就非常明確我想要為此實(shí)驗整合哪些更廣泛的系統(tǒng)組成部分。我需要的組件如下:
一個神經(jīng)網(wǎng)絡(luò),用以解釋手勢(即將手勢視頻轉(zhuǎn)換為文本)。
一個文字轉(zhuǎn)語音系統(tǒng),用于將解釋過的手勢講給 Alexa
一個語音轉(zhuǎn)文字系統(tǒng),用于將 Alexa 的回應(yīng)轉(zhuǎn)錄給用戶使用
一臺運(yùn)行該系統(tǒng)的設(shè)備(筆記本電腦/平板電腦)和用于互動的 Echo
可以將這些組件整合在一起的界面
早期,我的大部分時間可能都用在了確定哪個神經(jīng)網(wǎng)絡(luò)架構(gòu)最適合此實(shí)驗上面。我想到下面幾個選擇:
1) 由于手勢兼具可視性和時效性,因此我的直覺是將 CNN 與 RNN 結(jié)合在一起,其中最后一個卷積層的輸出(分類前)作為序列饋送到 RNN 中。后來,我為此找到一個技術(shù)術(shù)語,即長期遞歸卷積網(wǎng)絡(luò) (LRCN)。
2) 使用 3D 卷積網(wǎng)絡(luò),以三維方式應(yīng)用卷積,其中前兩個維度是圖像,第三個維度是時間。但是,這些網(wǎng)絡(luò)需要大量存儲設(shè)備,而我希望可以在我用了 7 年的老 Macbook Pro 上進(jìn)行訓(xùn)練。
3) 訓(xùn)練 CNN 時,我沒有使用視頻流中的單個幀,而是只用了可以表示兩個連續(xù)幀之間視運(yùn)動模式的光流表征。我的想法是它會對這種動作進(jìn)行編碼,產(chǎn)生更通用的手語模型。
4) 使用雙流 CNN,其中空間流為單個幀 (RGB),時間流會使用光流表征。
在做進(jìn)一步研究時,我發(fā)現(xiàn)了一些論文,其中至少使用了上述部分視頻行為識別方法(在UFC101 數(shù)據(jù)集上最常見)。但我很快發(fā)現(xiàn),不僅我的計算能力有限,我從頭開始解密和實(shí)施這些論文的能力也很有限,之后幾個月,我的研究時斷時續(xù),經(jīng)常因為其他項目纏身而不得不丟下該項目,我的輸出結(jié)果一直乏善可陳。
最終,我采用了迥異的方法。
TensorFlow.js團(tuán)隊一直在推出基于瀏覽器的有趣小實(shí)驗,幫助人們熟悉機(jī)器學(xué)習(xí)的概念,同時也鼓勵人們用它來構(gòu)建自己的項目。對于那些不熟悉機(jī)器學(xué)習(xí)的人,TensorFlow.js 是一個開放源代碼庫,讓您可以直接在使用 Javascript 的瀏覽器中定義、訓(xùn)練和運(yùn)行機(jī)器學(xué)習(xí)模型。特別值得一提的是,Pacman 網(wǎng)絡(luò)攝像頭控制器和Teachable Machine這兩個演示似乎是很有趣的起點(diǎn)。
雖然這兩個演示都是從網(wǎng)絡(luò)攝像頭選取輸入圖像,并輸出基于訓(xùn)練數(shù)據(jù)的預(yù)測,但其內(nèi)部運(yùn)作卻各不相同:
1) Pacman 網(wǎng)絡(luò)攝像頭 — 使用卷積神經(jīng)網(wǎng)絡(luò)選取輸入圖像(來自網(wǎng)絡(luò)攝像頭)并通過一系列卷積和最大池化層來傳遞圖像。通過這種方式,它能提取圖像的主要特征,并根據(jù)其訓(xùn)練時用過的示例預(yù)測其標(biāo)簽。由于訓(xùn)練過程費(fèi)時費(fèi)力,它使用了名為 MobileNet 的預(yù)訓(xùn)練模型進(jìn)行遷移學(xué)習(xí)。該模型經(jīng)受過基于 ImageNet 數(shù)據(jù)集的訓(xùn)練,可以區(qū)分 1000 種圖像,而且經(jīng)過優(yōu)化,可以在瀏覽器和移動應(yīng)用中運(yùn)行。
2) Teachable Machine — 使用 kNN(最鄰近規(guī)則分類),該分類非常簡單,以至于從技術(shù)上說其完全不執(zhí)行任何“學(xué)習(xí)”。它會接收輸入圖像(來自網(wǎng)絡(luò)攝像頭),并使用相似度函數(shù)或距離度量來尋找最接近該輸入圖像的訓(xùn)練示例的標(biāo)簽,從而對圖像進(jìn)行分類。然而,在饋送 kNN 之前,首先要通過名為 SqueezeNet 的小型神經(jīng)網(wǎng)絡(luò)傳送該圖像。然后,將該網(wǎng)絡(luò)倒數(shù)第二個層的輸出饋送到 kNN 中,該 kNN 允許您訓(xùn)練自己的分類。相較將來自網(wǎng)絡(luò)攝像頭的原始像素值直接饋送到 kNN 中,這樣做的好處在于我們可以使用 SqueezeNet 已經(jīng)學(xué)過的高層抽象,由此訓(xùn)練更好的分類器。
現(xiàn)在您可能想知道,手勢的時效性怎么辦?這兩個系統(tǒng)都是每幀選取一個輸入圖像,并且在預(yù)測時完全不考慮面前的這些幀。這不是考查 RNN 時關(guān)注的整個要點(diǎn)嗎?這對真正理解手勢并非必要?利用在線資源學(xué)習(xí)本項目的 ASL 時,我發(fā)現(xiàn),當(dāng)做出手勢時,不同手勢之間手的始末姿勢以及位置差別很大。與人交流時,其間發(fā)生的一切或許都很必要,但對機(jī)器而言,只使用始末姿勢就足夠了。因此,我決定棄常規(guī)作法而不用,無視過程,直奔目的。
事實(shí)證明,使用 TensorFlow.js 非常有用,其間原因包括:
我可以利用這些演示進(jìn)行原型設(shè)計,而無需編寫任何代碼。最初開始原型設(shè)計時,我只是在瀏覽器中運(yùn)行這些原始示例,用我計劃使用的手勢進(jìn)行訓(xùn)練,然后觀察系統(tǒng)的運(yùn)行方式,即便其輸出結(jié)果意味著是 Pacman 在屏幕上移動。
我可以使用 TensorFlow.js 在瀏覽器中直接運(yùn)行模型。從可移植性、開發(fā)速度和與網(wǎng)頁界面輕松交互的能力來看,這是巨大的。這些模型也可以完全在瀏覽器中運(yùn)行,而無需向服務(wù)器發(fā)送數(shù)據(jù)。
因為模型在瀏覽器中運(yùn)行,我可以將其與現(xiàn)代瀏覽器支持且我需要使用的語音轉(zhuǎn)文字和文字轉(zhuǎn)語音 API 連接起來。
它可以加速測試、訓(xùn)練和微調(diào)操作,而這往往是機(jī)器學(xué)習(xí)中的一大難題。
由于我沒有手語數(shù)據(jù)集,并且訓(xùn)練示例基本是我在重復(fù)做出手語動作,因此使用網(wǎng)絡(luò)攝像頭來收集訓(xùn)練數(shù)據(jù)非常方便。
在全面測試這兩種方法后,我發(fā)現(xiàn)這兩個系統(tǒng)在測試中表現(xiàn)相當(dāng),于是決定使用 Teachable Machine 作為訓(xùn)練基礎(chǔ),這是因為:
如果使用較小的數(shù)據(jù)集,kNN 實(shí)際要比 CNN 運(yùn)行地更快/更好。在用很多示例訓(xùn)練時,它們需要存儲大量數(shù)據(jù),性能也會下降,但我知道我的數(shù)據(jù)集不大,所以這不是問題。
由于 kNN 實(shí)際并非從示例中學(xué)習(xí),所以它們不擅長泛化。因此,使用完全由一個人構(gòu)成的示例訓(xùn)練模型,其預(yù)測結(jié)果并不能很好地遷移至另一個人。但對我而言,這也不是問題,因為我會通過自己反復(fù)做出手勢來訓(xùn)練并測試模型。
該團(tuán)隊曾經(jīng)開放過一個很好的項目剝離樣板文件的源代碼,可以作為一個非常有用的起點(diǎn)。
下面我們從較高層面了解一下系統(tǒng)由始至終的運(yùn)作方式:
在瀏覽器中打開網(wǎng)站后,第一步是提供訓(xùn)練示例。也就是,使用網(wǎng)絡(luò)攝像頭反復(fù)捕捉您自己做出每個手勢時的動作。這樣操作相對較快,因為只要按下特定的拍照按鈕就可以持續(xù)捕獲幀,直到您松開按鈕并使用合適的標(biāo)簽標(biāo)記捕獲的圖像。我訓(xùn)練的這個系統(tǒng)包含 14 個詞匯,我可以將這些詞匯進(jìn)行多種組合,用來向 Alexa 發(fā)出不同請求。
訓(xùn)練完成后,輸入預(yù)測模式。現(xiàn)在,系統(tǒng)會使用來自網(wǎng)絡(luò)攝像頭的輸入圖像并通過分類器運(yùn)行,根據(jù)上一步中提供的訓(xùn)練示例和標(biāo)簽找到與其最鄰近的類別。
如果超過了某個預(yù)測閾值,它會在屏幕的左側(cè)附上標(biāo)簽。
然后我使用語音合成的 Web Speech API 來讀出檢測到的標(biāo)簽。
如果說出的單詞是“Alexa”,則會喚醒附近的 Echo,并且 Echo 會開始聆聽查詢。另外值得注意的是,我創(chuàng)建了一個任意手勢(在空中舉起右拳)來表示單詞 Alexa,因為 ASL 中不存在與這個詞對應(yīng)的手勢,并且反復(fù)拼寫 A-L-E-X-A 也會讓人厭煩。
在完成整個手勢短語后,我再次使用 Web Speech API 來轉(zhuǎn)錄Echo 的反應(yīng),Echo 在回應(yīng)這個查詢時完全不知道該查詢來自另一臺機(jī)器。轉(zhuǎn)錄的反應(yīng)顯示在屏幕的右側(cè),以供用戶閱讀。
再次用手勢表示喚醒詞,清除屏幕并重啟反復(fù)查詢的流程。我已將全部代碼上傳至 Github,包括實(shí)時演示。您可以按照您的想法隨意使用并修改代碼。
雖然系統(tǒng)運(yùn)行較好,但的確需要一些簡單改動來幫助獲取所需結(jié)果并提高準(zhǔn)確度,例如:
確保在說出喚醒詞 Alexa 之前不會檢測到任何手勢。
在訓(xùn)練示例中添加一個完整的泛類,我將其歸為適用于空閑狀態(tài)的“其他”類(空白背景、我站在一旁不做任何動作,手放在身體兩邊等)。這可以防止錯誤檢測詞匯。
在接收輸出前設(shè)定高閾值,以減少預(yù)測錯誤。
降低預(yù)測率。不要按最大幀率進(jìn)行預(yù)測,控制每秒的預(yù)測數(shù)量有助于減少預(yù)測錯誤。
確保預(yù)測時不會重復(fù)考慮短語中已經(jīng)檢測過的詞匯。
在手語中,冠詞通常不用手勢表達(dá),而是依靠上下文來表達(dá)意思,因此,我在訓(xùn)練模型時用了某些包含相應(yīng)冠詞或介詞的詞匯,例如這天氣、這清單等。
另一個難題是,準(zhǔn)確預(yù)測用戶已在何時完成手勢查詢。這對于準(zhǔn)確轉(zhuǎn)錄非常必要。如果太早觸發(fā)轉(zhuǎn)錄(在用戶完成手勢之前),則系統(tǒng)會開始轉(zhuǎn)錄其自己的語音。但如果觸發(fā)太晚,又可能會錯過轉(zhuǎn)錄 Alexa 的部分反應(yīng)。為了解決這一難題,我采用了兩項獨(dú)立的方法,兩者各有利弊:
第一個選擇是在添加詞匯用于訓(xùn)練時,將這些詞匯標(biāo)記為終點(diǎn)詞匯。我說的終點(diǎn)詞匯是指用戶只會在短語結(jié)束時使用的手勢。例如,如果查詢語句是 “Alexa, what’sthe weather?”,則將 “the weather” 作為終點(diǎn)詞匯,當(dāng)檢測到該詞匯時,便可以正確觸發(fā)轉(zhuǎn)錄。這個方法雖然很好用,但這意味著用戶在訓(xùn)練期間必須要記得去標(biāo)記終點(diǎn)詞匯,并且需要依賴該詞僅會出現(xiàn)在查詢結(jié)尾的假設(shè)。這樣,如果將查詢語句調(diào)整為 “Alexa, what’sthe weatherin New York?”,則會面臨問題。我們在演示中就使用了這個方法。
第二個選擇是讓用戶故意做出一個停用詞,讓系統(tǒng)知道他們的查詢語句結(jié)束了。識別到這個停用詞后,系統(tǒng)就可以觸發(fā)轉(zhuǎn)錄。所以用戶需要用手勢比出喚醒詞 > 查詢 > 停用詞。這個方法的風(fēng)險在于,如果用戶忘記用手勢比出這個停用詞,就會導(dǎo)致完全不會觸發(fā)轉(zhuǎn)錄。我在另一個Github 分支中運(yùn)用了這個方法,您可以使用喚醒詞 Alexa 作為查詢 “書夾”,即 “Alexa, what’s the weather in New York”(Alexa)?”。
當(dāng)然,如果有一種方法可以準(zhǔn)確區(qū)分來自內(nèi)部信源(筆記本電腦)和外部信源(附近的 Echo)的語音,就可以解決整個問題,但那又是另一個難題。
日后,我想會有許多其他方法可以解決這個問題,這或許可以作為您自己項目的良好起點(diǎn),用于創(chuàng)建更穩(wěn)健而通用的模型:
Tensorflow.js 還發(fā)布了PoseNet,使用 PoseNet 也可能是一個有趣的方法。從機(jī)器的角度來看,只要追蹤幀中手腕、手肘和肩膀的位置應(yīng)該就足以對大多數(shù)詞匯作出預(yù)測。在拼寫詞匯時,手指位置往往非常重要。
使用基于 CNN 的方法(例如 Pacman 示例)或許可以提高準(zhǔn)確度,并使模型更能抵御平移不變性。該方法也有助于在不同人群中更好地實(shí)現(xiàn)泛化。用戶也可以納入保存模型或加載預(yù)訓(xùn)練 Keras 模型的能力,這些都有清晰的文件記錄。這樣,您就不必在每次重啟瀏覽器時都要訓(xùn)練系統(tǒng)。
某些考慮時間特性的 CNN+RNN 或 PoseNet+RNN 組合可能會使準(zhǔn)確性受到影響。
使用 tensorflow.js 中較新的可重用kNN 分類器。
自我首次發(fā)布此項目以來,人們已在社交媒體上廣泛分享,媒體也進(jìn)行了相關(guān)報道,甚至 Amazon 也在 Echo Show 上實(shí)現(xiàn)上無障礙功能(點(diǎn)擊喚醒 Alexa),用于幫助講話困難的人士。雖然我并無證據(jù)可以證明是我的項目令他們得以實(shí)現(xiàn)這項功能(時間高度巧合),但如果確實(shí)如此,那真的非常酷。我希望 Amazon Show 或其他基于攝像頭和屏幕的語音助手將來都可以納入此項功能。對我而言,這可能是此原型展示的最終用例,并且讓數(shù)百萬新用戶都能用上這些設(shè)備。
降低網(wǎng)絡(luò)復(fù)雜度,并且采用簡單地的架構(gòu)來創(chuàng)建我的原型,這絕對有助于這個項目的快速推廣。我的目標(biāo)并不是要解決整個手語轉(zhuǎn)文本問題。恰恰相反,我想要發(fā)起圍繞包容性設(shè)計的對話,以平易親和的方式介紹機(jī)器學(xué)習(xí),并啟發(fā)人們?nèi)ヌ剿鬟@方面的問題,這才是我希望這個項目能達(dá)成的目標(biāo)。
-
語音控制
+關(guān)注
關(guān)注
5文章
476瀏覽量
28199 -
Alexa
+關(guān)注
關(guān)注
2文章
195瀏覽量
23251
原文標(biāo)題:Alexa 可以響應(yīng)手語啦!借助了網(wǎng)絡(luò)攝像頭和 TensorFlow.js
文章出處:【微信號:tensorflowers,微信公眾號:Tensorflowers】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論