重磅實(shí)戰(zhàn):如何用TensorFlow在安卓設(shè)備上實(shí)現(xiàn)深度學(xué)習(xí)健霹,附Demo和源碼

對(duì)于個(gè)人和公司來(lái)說(shuō),存在許多狀況是更希望在本地設(shè)備上做深度學(xué)習(xí)推斷的:想象一下當(dāng)你在旅行途中沒有可靠的互聯(lián)網(wǎng)鏈接時(shí)瓶蚂,或是要處理傳輸數(shù)據(jù)到云服務(wù)的隱私問(wèn)題和延遲問(wèn)題時(shí)撕捍。

邊緣計(jì)算(Edge computing)是一種在物理上靠近數(shù)據(jù)生成的位置從而對(duì)數(shù)據(jù)進(jìn)行處理和分析的方法涯呻,為解決這些問(wèn)題提供了方案。

以「Ok Google」這個(gè)功能為例:用一名用戶的聲音來(lái)訓(xùn)練「Ok Google」,他的手機(jī)在接收到這個(gè)關(guān)鍵詞的時(shí)候就會(huì)被喚醒典鸡。這種小型關(guān)鍵詞檢測(cè)(small-footprint keyword-spotting,KWS)推斷通常在本地設(shè)備上運(yùn)行家夺,所以你不必?fù)?dān)心服務(wù)提供商隨時(shí)監(jiān)聽你的聲音猫态。而云服務(wù)只在你發(fā)出指令后才啟動(dòng)。類似的概念可以擴(kuò)展到智能家用電器或其他物聯(lián)網(wǎng)設(shè)備上的應(yīng)用兆解,在這些應(yīng)用中我們需要不依靠互聯(lián)網(wǎng)進(jìn)行免提語(yǔ)音控制馆铁。

更重要的是,邊緣計(jì)算不僅為物聯(lián)網(wǎng)世界帶來(lái)了人工智能锅睛,還提供了許多其他的可能性和好處埠巨。例如,我們可以在本地設(shè)備上將圖像或語(yǔ)音數(shù)據(jù)預(yù)處理為壓縮表示现拒,然后將其發(fā)送到云辣垒。這種方法解決了隱私和延遲問(wèn)題。

在 Insight 任職期間印蔬,我用 TensorFlow 在安卓上部署了一個(gè)預(yù)訓(xùn)練的 WaveNet 模型勋桶。我的目標(biāo)是探索將深度學(xué)習(xí)模型部署到設(shè)備上并使之工作的工程挑戰(zhàn)!這篇文章簡(jiǎn)要介紹了如何用 TensorFlow 在安卓上構(gòu)建一個(gè)通用的語(yǔ)音到文本識(shí)別應(yīng)用程序。

圖 1. 流程概述侥猬。將 WaveNet 安裝到安卓的三個(gè)步驟例驹。

開發(fā)環(huán)境信息:

  • Pixel, cpu type: ARM64
  • Android 7.1.1
  • Android NDK 15.2
  • Android gradle plugin 2.3.0
  • TensorFlow 1.3.0
  • bazel 0.5.4-homebrew

詳細(xì)教程和實(shí)現(xiàn):https://github.com/chiachunfu/speech

第一步:模型壓縮

為了將深度學(xué)習(xí)模型部署到移動(dòng)/嵌入式設(shè)備上,我們應(yīng)該致力于減少模型的內(nèi)存占用陵究,縮短推斷時(shí)間眠饮,減少耗電。有幾種方法可以實(shí)現(xiàn)這些要求铜邮,如量化仪召、權(quán)重剪枝或?qū)⒋竽P吞釤挸尚∧P汀?/p>

在這個(gè)項(xiàng)目中,我使用了 TensorFlow 中的量化工具來(lái)進(jìn)行模型壓縮松蒜。目前我只使用權(quán)重量化來(lái)減小模型大小扔茅,因?yàn)楦鶕?jù) Mac 上的測(cè)試結(jié)果,完整 8 位轉(zhuǎn)換沒有提供額外的好處秸苗,比如縮短推斷時(shí)間召娜。(由于 requant_range 中的錯(cuò)誤,無(wú)法在 Pixel 上運(yùn)行完整的 8 位模型)惊楼。由于 8 位量化工具不適合 CPU玖瘸,時(shí)間甚至翻了一倍秸讹。如果你有興趣了解更多關(guān)于量化的實(shí)用建議,可以閱讀 Pete Warden 這篇很棒的文章(https://petewarden.com/2017/06/22/what-ive-learned-about-neural-network-quantization/)雅倒。

對(duì)模型進(jìn)行權(quán)重量化:

  1. 將模型寫入?yún)f(xié)議緩沖區(qū)文件璃诀。
  2. 從源安裝和配置 TensorFlow(https://www.tensorflow.org/install/install_sources)。
  3. 在 TensorFlow 目錄下運(yùn)行下列命令行:

bazel build tensorflow/tools/graph_transforms:transform_graph
bazel-bin/tensorflow/tools/graph_transforms/transform_graph \

--in_graph=/your/.pb/file
--outputs="output_node_name"
--out_graph=/the/quantized/.pb/file
--transforms='quantize_weights'

以我的項(xiàng)目為例蔑匣,在量化權(quán)重后劣欢,預(yù)訓(xùn)練的 WaveNet 模型的大小從 15.5Mb 下降到了 4.0Mb。現(xiàn)在可以將這個(gè)模型文件移動(dòng)到安卓項(xiàng)目中的「assets」文件夾裁良。

第二步:適用于安卓的 TensorFlow 庫(kù)

要用 TensorFlow 構(gòu)建安卓應(yīng)用程序凿将,我推薦從 TensorFlow Android Demo開始。在我的項(xiàng)目中价脾,我把 TF speech example 作為模板牧抵。這個(gè)示例中的 gradle 文件幫助我們構(gòu)建和編譯安卓的 TF 庫(kù)。但是彼棍,這個(gè)預(yù)構(gòu)建的 TF 庫(kù)可能不包括模型所有必要的 ops灭忠。我們需要想清楚 WaveNet 中需要的全部 ops膳算,并將它們編譯成適合安卓 apk 的.so 文件座硕。為了找到 ops 的完整列表,我首先使用 tf.train.write_graph 輸出圖的詳細(xì)信息涕蜂。然后在終端中運(yùn)行下列命令:

grep "op: " PATH/TO/mygraph.txt | sort | uniq | sed -E 's/^.+"(.+)".?$/\1/g'

接著华匾,編輯/tensorflow/tensorflow/core/kernels/里的 BUILD 文件,在 Android libraries section 中的「android_extended_ops_group1」或「android_extended_ops_group2」里添加缺失的 ops机隙。我們也可以刪除不必要的 ops蜘拉,使 .so 文件變得更小。現(xiàn)在有鹿,運(yùn)行下列命令:

bazel build -c opt //tensorflow/contrib/android:libtensorflow_inference.so
--crosstool_top=//external:android/crosstool
--host_crosstool_top=@bazel_tools//tools/cpp:toolchain
--cpu=armeabi-v7a

你將在這里找到 libtensorflow_inference.so 文件:

bazel-bin/tensorflow/contrib/android/libtensorflow_inference.so

除了 .so 文件之外旭旭,我們還需要一個(gè) JAR 文件。運(yùn)行:

bazel build
//tensorflow/contrib/android:android_tensorflow_inference_java

你將在這里找到該文件:

bazel-bin/tensorflow/contrib/android/libandroid_tensorflow_inference_java.jar

現(xiàn)在葱跋,可以將 .so 和 .jar 文件一起移到你的安卓項(xiàng)目中的「libs」文件夾持寄。

第三步:在安卓上的數(shù)據(jù)預(yù)處理

最后,讓我們將輸入數(shù)據(jù)處理成模型訓(xùn)練所需格式娱俺。對(duì)于音頻系統(tǒng)來(lái)說(shuō)稍味,原始的語(yǔ)音波被轉(zhuǎn)換成梅爾頻率倒譜系數(shù)(MFCC)來(lái)模擬人耳感知聲音的方式。TensorFlow 有一個(gè)音頻 op荠卷,可以執(zhí)行該特征提取模庐。然而,事實(shí)證明油宜,實(shí)現(xiàn)這種轉(zhuǎn)換存在一些變體掂碱。如圖 2 所示怜姿,來(lái)自 TensorFlow audio op 的 MFCC 不同于 librosa 提供的 MFCC。librosa 是一個(gè)被預(yù)訓(xùn)練的 WaveNet 作者們用來(lái)轉(zhuǎn)換訓(xùn)練數(shù)據(jù)的 Python 庫(kù)疼燥。

圖 2. 來(lái)自 librosa 和 TensorFlow audio ops 的 MFCC 處在不同的刻度范圍社牲。

如果您正在訓(xùn)練自己的模型或重訓(xùn)練一個(gè)預(yù)先訓(xùn)練好的模型,那么在處理訓(xùn)練數(shù)據(jù)時(shí)悴了,一定要考慮設(shè)備上的數(shù)據(jù)通道搏恤。最終,我在 Java 中重寫了 librosa MFCC 來(lái)處理轉(zhuǎn)換問(wèn)題湃交。

結(jié)果

圖 3 展示了 app 的截圖和示例熟空。由于模型中沒有語(yǔ)言模型,而且識(shí)別僅在字符級(jí)搞莺,因此句子中出現(xiàn)了一些拼寫錯(cuò)誤息罗。雖然沒有經(jīng)過(guò)嚴(yán)格的測(cè)試,但在量化之后才沧,我確實(shí)發(fā)現(xiàn)準(zhǔn)確率略有下降迈喉,以及整個(gè)系統(tǒng)對(duì)周圍的噪聲很敏感。


圖 3. App 中兩個(gè)示例的截圖温圆。

下表所示推斷時(shí)間是對(duì) 5 秒音頻的 10 次測(cè)試的平均值挨摸。推斷時(shí)間在兩個(gè)平臺(tái)上都略有增加,而不是減少岁歉,因?yàn)闄?quán)重量化有助于縮小文件大小得运,但不太能優(yōu)化推斷時(shí)間或耗電情況。

表 1. 權(quán)重量化前后的推斷時(shí)間锅移。測(cè)試環(huán)境是我的 Pixel 手機(jī)和 Macbook air熔掺。

接下來(lái)做些什么?

有兩件重要的事情可以讓這個(gè)項(xiàng)目更進(jìn)一步,也可以為社區(qū)提供額外的教程和演練非剃,以便在邊緣設(shè)備上部署一個(gè)現(xiàn)實(shí)語(yǔ)音識(shí)別系統(tǒng)置逻。

提高語(yǔ)音識(shí)別性能:添加拼寫校正的語(yǔ)言模型和噪聲下采樣模型,以降低周圍噪聲的影響备绽。

改善推斷時(shí)間和耗電情況:用 NEON 或其他架構(gòu)進(jìn)行低層次優(yōu)化券坞,用 gemmlowp 進(jìn)行低精度矩陣計(jì)算。

GitHub 地址:https://github.com/chiachunfu/speech

選自DataScience

作者:Chia-Chun

機(jī)器之心編譯

參與:Edison Ke疯坤、路雪

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末报慕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子压怠,更是在濱河造成了極大的恐慌眠冈,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蜗顽,居然都是意外死亡布卡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門雇盖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)忿等,“玉大人,你說(shuō)我怎么就攤上這事崔挖∶辰郑” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵狸相,是天一觀的道長(zhǎng)薛匪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)脓鹃,這世上最難降的妖魔是什么逸尖? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮瘸右,結(jié)果婚禮上娇跟,老公的妹妹穿的比我還像新娘。我一直安慰自己太颤,他們只是感情好苞俘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著栋齿,像睡著了一般苗胀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瓦堵,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音歌亲,去河邊找鬼菇用。 笑死,一個(gè)胖子當(dāng)著我的面吹牛陷揪,可吹牛的內(nèi)容都是我干的惋鸥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼悍缠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼卦绣!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起飞蚓,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤滤港,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后趴拧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溅漾,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡山叮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了添履。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屁倔。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖暮胧,靈堂內(nèi)的尸體忽然破棺而出锐借,到底是詐尸還是另有隱情,我是刑警寧澤往衷,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布瞎饲,位于F島的核電站,受9級(jí)特大地震影響炼绘,放射性物質(zhì)發(fā)生泄漏嗅战。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一俺亮、第九天 我趴在偏房一處隱蔽的房頂上張望驮捍。 院中可真熱鬧,春花似錦脚曾、人聲如沸东且。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)珊泳。三九已至,卻和暖如春拷沸,著一層夾襖步出監(jiān)牢的瞬間色查,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工撞芍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秧了,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓序无,卻偏偏與公主長(zhǎng)得像验毡,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帝嗡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容