《Android開發高手課》學習筆記1

最近在學習張紹文老師的《Android開發高手課》課程,學習到了很多的乾貨,特別是在處理問題的策略和知識的廣度方面給了我很多的啓發,對未來的學習也提供了方向。

目前,技術的發展有兩個趨勢。一個趨勢是,隨着5G網絡的發展,物聯網使“萬物互聯”成爲可能。物聯網時代,也是雲計算和邊緣計算並存的世界,且邊緣計算將扮演重要的角色。邊緣計算是與雲計算相反的計算範式,指的是在網絡邊緣節點(終端設備)進行數據處理和分析。邊緣計算之所以重要,原因在於:首先,在物聯網時代,將有數十億的終端設備持續採集數據,帶來的計算量將是雲計算所不能承受的;其次,終端設備的計算能力不斷提高,並不是所有的計算都需要在雲端完成;再有,將數據傳回雲端計算再將結果返回終端的模式,不可避免存在時延,不僅影響用戶體驗,有些場景也是不可接受的;最後,隨着用戶對數據安全和隱私的重視,也會要求在終端進行數據加工和計算。

另一個趨勢是,人工智能技術的迅速發展。最近幾年,以深度學習爲代表的人工智能技術取得了突破性的進展,不僅在社會上引起了人們的興趣和關注,同時也正在重塑商業的格局。人工智能技術的重大價值在於,藉助智能算法和技術,將之前必須人工才能完成的工作進行機器化,用機器的規模化解放人工,突破人力生產要素的瓶頸,從而大幅提高生產效率。在商業社會,“規模化”技術將釋放巨大的能量、創造巨大的價值,甚至重塑商業的競爭,拓展整個商業的外部邊界。

邊緣計算既然有計算能力,在很多應用場景中就會產生智能計算的需求,兩者結合在一起,就形成了邊緣智能計算。

移動端機器學習的開發技術

目前,移動端機器學習的應用技術主要集中在圖像處理、自然語言處理和語音處理。在具體的應用上,包括但不限於視頻圖像的物體檢測、語言翻譯、語音助手、美顏等,在自動駕駛、教育、醫療、智能家居和物聯網等方面有巨大的應用需求。目前已經商用的深度學習技術主要有如下一些:

框架 研發公司 支持平臺
TF_lite Google ARM
Caffe2 Facebook ARM
TF_lite Xiaomi ARM、DSP、GPU
paddle-mobile Baidu ARM、GPU
FeatherCNN Tencent ARM
NCNN Tencent ARM

1.計算框架

因爲深度學習算法具有很多特定的算法算子,爲了提高移動端開發和模型部署的效率,各大廠都開發了移動端深度學習的計算框架,例如谷歌的TensorFlow Lite、Facebook的Caffe2等,Android開發的同學還是挺有必要去了解這些計算框架的。爲了培養興趣這方面的興趣並獲得感性的認識,你可以挑選一個比較成熟的大廠框架,例如 TensorFlow Lite,在手機開發一個物體檢測的Demo練練手。

在實際項目中,TensorFlow Lite和Caffe2等通常運行比較慢。在網上可以很容易找到各個計算框架的對比圖。如果要真正入門的話,在這裏我推薦大家使用NCNN框架。NCNN是騰訊開源的計算框架,優點比較明顯,代碼結構清晰、文件不大,而且運行效率高。強烈推薦有興趣的Android開發同學把源碼閱讀幾遍,不僅有助於理解深度學習常用的算法,也有助於理解移動端機器學習的計算框架。

閱讀NCNN源碼抓住三個最基礎的數據結構,Mat、Layer和Net。其中,Mat用於存儲矩陣的值,神經網絡中的每個輸入、輸出以及權重,都是用Mat來存儲的。Layer實際上表示操作,所以每個Layer都必須有前向操作函數(forward函數),所有算子,例如,卷積操作(convolution)、LSTM操作等都是從Layer派生出來的。Net用來表示整個網絡,將所有數據節點和操作結合起來。

在閱讀NCNN源碼的同時,建議大家也可以看些關於卷積神經網絡算法的入門資料,會有助於理解。

2.計算性能優化

在實際項目中,如果某個路徑成爲時間開銷的瓶頸,通常可以將該節點用NDK去實現。但在通常情況下,移動端機器學習的計算框架已經在NDK中進行實現的,這時改進的方向是採用ARM NEON指令彙編進行優化。

NEON是適用於ARMCortex-A系列處理器的一種128Bit SIMD(Single Instruction%2CMultipleData,單指令、多數據)擴展結構。ARMNEON指令之所有能達到性能優化的目的,關鍵就在於單指令多數據。如下圖所示:
在這裏插入圖片描述
NEON的兩個操作數各有128Bit,各包含4個32Bit的同類型的寄存器,通過如下所示的一條指令,就可以實現4個32Bit數據的並行計算,從而達到性能優化的效果。

VADDQ.S32 Q0,Q1,Q2

我們曾經用NDK的方式實現了深度學習算法中的PixelShuffle操作,後來採用ARMNEON%2B彙編優化的方式,計算的效率提升40倍,效果還是很顯著的。

如果還想進一步提高計算的性能,可以採用Int 8量化的方法。在深度學習裏面,大多數運算都是基於Float 32類型進行的,Float 32是32Bit,128Bit的寄存器一次可以存儲4個Float 32類型數據;相比之下,Int 8類型的數據可以存儲16個。結合前面提到的單指令多數據,如果採用Int 8類型的數據,單條指令可以同時執行16個Int 8數據的運算,從而大大提高了並行性。

但是,將Float 32類型的數值量化到Int 8表達,不可避免會影響到數據的精度,而且量化的過程也是需要時間開銷的,這些都是需要注意的地方。關於量化的方法,感興趣的同學可以閱讀這篇論文

如果設備具有GPU,還可以應用OpenCL進行GPU加速,例如小米開源的移動端機器學習框架MACE

移動端機器學習的算法技術

對於剛開始學習算法的同學,我一直主張不要把算法想象得太複雜,也不要想得太數學化,否則容易讓人望而生畏。數學是思維邏輯的表達,我們希望用數學幫助我們理解算法。我們要能夠達到對算法的直觀理解,從直觀上知道和理解爲什麼這個算法會有這樣的效果,只有這樣纔算是真正掌握了算法。相反,對於一個算法,如果你只記住了數學推導,沒形成直觀的理解,是不能夠靈活應用的。

1.算法設計

深度學習的圖像處理具有很廣的應用,而且比較直觀和有趣,建議你可以從深度學習的圖像處理入手。深度學習的圖像處理,最基本的知識是卷積神經網絡,所以你可以先學習卷積神經網絡。網上有很多關於卷積神經網絡的介紹,這裏就不贅述了。

理解卷積神經網絡關鍵是理解卷積神經網絡的學習機制,理解爲什麼能夠學習。想要理解這一點,首先需要明確兩個關鍵點“前向傳播”和“反向傳播”。整個神經網絡在結構和激活函數確定之後,所謂“訓練”或者“學習”的過程,其實就是在不斷地調整神經網絡的每個權重,讓整個網絡的計算結果趨近於期望值(目標值)。前向傳播是從輸入端開始計算,目標是得到網絡的輸出結果,再將輸出結果和目標值相比較,得到結果誤差。之後將結果誤差沿着網絡結構反向傳播拆解到每個節點,得到每個節點的誤差,然後根據每個節點的誤差調整該節點的權重。“前向傳播”的目的是得到輸出結果,“反向傳播”的目的是通過反向傳播誤差來調整權重。通過兩者互相交替迭代,希望達到輸出結果和目標值一致。

理解卷積神經網絡之後,我們可以動手實現手寫字體識別的示例。掌握之後,可以接着學習深度學習裏的物體檢測算法,例如YOLO、FasterR-CNN等,最後可以動手用TensorFlow都寫一遍,跑跑訓練數據、調調參數,邊動手邊理解。在學習過程中,要特別留意算法模型的設計思想和解決思路。

2.效果優化

效果優化指提升算法模型的準確率等指標,通常的方式有以下幾種:

  • 優化訓練數據;
  • 優化算法設計;
  • 優化模型訓練方式

優化訓練數據

因爲算法模型是從訓練數據中學習的,模型無法學習到訓練數據之外的模式。所以,在選擇訓練數據時要特別小心,必須使得訓練數據包含實際場景中會出現的模式。精心挑選或標註訓練數據,會有效提升模型的效果。訓練數據的標註對效果非常重要,以至於有創業公司專門從事數據標註,還獲得了不少融資。

優化算法設計

根據問題採用更好的算法模型,採用深度學習模型而不是傳統的機器學習模型,採用具有更高特徵表達能力的模型等,例如使用殘差網絡或DenseNet提高網絡的特徵表達能力。

優化模型訓練方式

優化模型訓練方式包括採用哪種損失函數、是否使用正則項、是否使用Dropout結構、使用哪種梯度下降算法等。

3.計算量優化

雖然我們在框架側做了大量的工作來提高計算性能,但是如果在算法側能夠減少計算量,那麼整體的計算實時性也會提高。從模型角度,減少計算量的思路有兩種,一種是設計輕量型網絡模型,一種是對模型進行壓縮。輕量型網絡設計學術界和工業界都設計了輕量型卷積神經網絡,在保證模型精度的前提下,大幅減少模型的計算量,從而減少模型的計算開銷。這種思路的典型代表是谷歌提出的MobileNet,從名字上也可以看出設計的目標是移動端使用的網絡結構。MobileNet是將標準的卷積神經網絡運算拆分成Depthwise卷積運算和Pointwise卷積運算,先用Depthwise卷積對輸入各個通道分別進行卷積運算,然後用Pointwise卷積實現各個通道間信息的融合。

模型壓縮

模型壓縮包括結構稀疏化和蒸餾兩種方式。

在邏輯迴歸算法中,我們通過引入正則化,使得某些特徵的係數近似爲0。在卷積神經網絡中,我們也希望通過引入正則化,使得卷積核的係數近似爲0。與普通的正則化不同的是,在結構稀疏化中,我們希望正則化實現結構性的稀疏,比如某幾個通道的卷積核的係數全部近似爲0,從而可以將這幾個通道的卷積核剪枝掉,減少不必要的計算開銷。

蒸餾方法有遷移學習的意思,就是設計一個簡單的網絡,通過訓練的方式,使得該簡單的網絡具有目標網絡近似的表示能力,從而達到“蒸餾”的效果。

Android開發同學的機會

移動端機器學習的計算框架和算法,前者負責模型計算的性能,減少時間開銷;後者主要負責模型的精度,還可以通過一些算法設計減少算法的計算量,從而達到減少時間開銷的目的。

需要注意的是,在移動端機器學習中,算法模型的訓練通常是在服務器端進行的。目前,終端設備通常不負責模型的訓練。在使用時,由終端設備加載訓練結果模型,執行前向計算得到模型的計算結果。

但是前面講了那麼多行業趨勢和機器學習的基本技術,那對於移動開發的同學來說,如何進入這個“熱門”的領域呢?移動端機器學習是邊緣智能計算範疇的一個領域,而且移動端開發是Android開發同學特別熟悉的領域,所以這也是Android開發同學的一個發展機會,轉型進入邊緣智能計算領域。Android開發同學可以發揮自己的技術專業優勢,先在邊緣計算的終端設備程序開發中站穩腳跟,在未來的技術分工體系中有個堅固的立足點;同時,逐步學習深度學習算法,以備將來往前邁一步,進入邊緣智能計算領域,創造更高的技術價值。

可能在大部分情況下,Android開發同學在深度學習算法領域,跟專業的算法同學相比,不具有競爭優勢,所以我們千萬不要放棄自己所專長的終端設備的開發經驗。對大多數Android開發同學而言,“專精Android開發並懂深度學習算法”纔是在未來技術分工中,創造最大價值的姿勢。

對於學習路徑,我建議Android開發同學可以先學習卷積神經網絡的基礎知識(結構、訓練和前向計算),然後閱讀學習NCNN開源框架,掌握計算性能的優化方法,把開發技術掌握好。同時,可以逐步學習算法技術,主要學習各種常見的深度學習算法模型,並重點學習近幾年出現輕量型神經網絡算法。總之,Android開發同學要重點掌握提高計算實時性的開發技術和算法技術,兼顧學習深度學習算法模型。

基於前面的描述,我梳理了移動端機器學習的技術大圖供你參考。圖中紅圈的部分,是我建議Android開發同學重點掌握的內容。

在這裏插入圖片描述
最近在學習張紹文老師的《Android開發高手課》課程,學習到了很多的乾貨,特別是在處理問題的策略和知識的廣度方面給了我很多的啓發,對未來的學習也提供了方向。

目前,技術的發展有兩個趨勢。一個趨勢是,隨着5G網絡的發展,物聯網使“萬物互聯”成爲可能。物聯網時代,也是雲計算和邊緣計算並存的世界,且邊緣計算將扮演重要的角色。邊緣計算是與雲計算相反的計算範式,指的是在網絡邊緣節點(終端設備)進行數據處理和分析。邊緣計算之所以重要,原因在於:首先,在物聯網時代,將有數十億的終端設備持續採集數據,帶來的計算量將是雲計算所不能承受的;其次,終端設備的計算能力不斷提高,並不是所有的計算都需要在雲端完成;再有,將數據傳回雲端計算再將結果返回終端的模式,不可避免存在時延,不僅影響用戶體驗,有些場景也是不可接受的;最後,隨着用戶對數據安全和隱私的重視,也會要求在終端進行數據加工和計算。

另一個趨勢是,人工智能技術的迅速發展。最近幾年,以深度學習爲代表的人工智能技術取得了突破性的進展,不僅在社會上引起了人們的興趣和關注,同時也正在重塑商業的格局。人工智能技術的重大價值在於,藉助智能算法和技術,將之前必須人工才能完成的工作進行機器化,用機器的規模化解放人工,突破人力生產要素的瓶頸,從而大幅提高生產效率。在商業社會,“規模化”技術將釋放巨大的能量、創造巨大的價值,甚至重塑商業的競爭,拓展整個商業的外部邊界。

邊緣計算既然有計算能力,在很多應用場景中就會產生智能計算的需求,兩者結合在一起,就形成了邊緣智能計算。

移動端機器學習的開發技術
目前,移動端機器學習的應用技術主要集中在圖像處理、自然語言處理和語音處理。在具體的應用上,包括但不限於視頻圖像的物體檢測、語言翻譯、語音助手、美顏等,在自動駕駛、教育、醫療、智能家居和物聯網等方面有巨大的應用需求。目前已經商用的深度學習技術主要有如下一些:

框架 研發公司 支持平臺
TF_lite Google ARM
Caffe2 Facebook ARM
TF_lite Xiaomi ARM、DSP、GPU
paddle-mobile Baidu ARM、GPU
FeatherCNN Tencent ARM
NCNN Tencent ARM
1.計算框架
因爲深度學習算法具有很多特定的算法算子,爲了提高移動端開發和模型部署的效率,各大廠都開發了移動端深度學習的計算框架,例如谷歌的TensorFlow Lite、Facebook的Caffe2等,Android開發的同學還是挺有必要去了解這些計算框架的。爲了培養興趣這方面的興趣並獲得感性的認識,你可以挑選一個比較成熟的大廠框架,例如 TensorFlow Lite,在手機開發一個物體檢測的Demo練練手。

在實際項目中,TensorFlow Lite和Caffe2等通常運行比較慢。在網上可以很容易找到各個計算框架的對比圖。如果要真正入門的話,在這裏我推薦大家使用NCNN框架。NCNN是騰訊開源的計算框架,優點比較明顯,代碼結構清晰、文件不大,而且運行效率高。強烈推薦有興趣的Android開發同學把源碼閱讀幾遍,不僅有助於理解深度學習常用的算法,也有助於理解移動端機器學習的計算框架。

閱讀NCNN源碼抓住三個最基礎的數據結構,Mat、Layer和Net。其中,Mat用於存儲矩陣的值,神經網絡中的每個輸入、輸出以及權重,都是用Mat來存儲的。Layer實際上表示操作,所以每個Layer都必須有前向操作函數(forward函數),所有算子,例如,卷積操作(convolution)、LSTM操作等都是從Layer派生出來的。Net用來表示整個網絡,將所有數據節點和操作結合起來。

在閱讀NCNN源碼的同時,建議大家也可以看些關於卷積神經網絡算法的入門資料,會有助於理解。

2.計算性能優化
在實際項目中,如果某個路徑成爲時間開銷的瓶頸,通常可以將該節點用NDK去實現。但在通常情況下,移動端機器學習的計算框架已經在NDK中進行實現的,這時改進的方向是採用ARM NEON指令彙編進行優化。

NEON是適用於ARMCortex-A系列處理器的一種128Bit SIMD(Single Instruction%2CMultipleData,單指令、多數據)擴展結構。ARMNEON指令之所有能達到性能優化的目的,關鍵就在於單指令多數據。如下圖所示:
在這裏插入圖片描述
NEON的兩個操作數各有128Bit,各包含4個32Bit的同類型的寄存器,通過如下所示的一條指令,就可以實現4個32Bit數據的並行計算,從而達到性能優化的效果。

VADDQ.S32 Q0,Q1,Q2

我們曾經用NDK的方式實現了深度學習算法中的PixelShuffle操作,後來採用ARMNEON%2B彙編優化的方式,計算的效率提升40倍,效果還是很顯著的。

如果還想進一步提高計算的性能,可以採用Int 8量化的方法。在深度學習裏面,大多數運算都是基於Float 32類型進行的,Float 32是32Bit,128Bit的寄存器一次可以存儲4個Float 32類型數據;相比之下,Int 8類型的數據可以存儲16個。結合前面提到的單指令多數據,如果採用Int 8類型的數據,單條指令可以同時執行16個Int 8數據的運算,從而大大提高了並行性。

但是,將Float 32類型的數值量化到Int 8表達,不可避免會影響到數據的精度,而且量化的過程也是需要時間開銷的,這些都是需要注意的地方。關於量化的方法,感興趣的同學可以閱讀這篇論文。

如果設備具有GPU,還可以應用OpenCL進行GPU加速,例如小米開源的移動端機器學習框架MACE。

移動端機器學習的算法技術
對於剛開始學習算法的同學,我一直主張不要把算法想象得太複雜,也不要想得太數學化,否則容易讓人望而生畏。數學是思維邏輯的表達,我們希望用數學幫助我們理解算法。我們要能夠達到對算法的直觀理解,從直觀上知道和理解爲什麼這個算法會有這樣的效果,只有這樣纔算是真正掌握了算法。相反,對於一個算法,如果你只記住了數學推導,沒形成直觀的理解,是不能夠靈活應用的。

1.算法設計
深度學習的圖像處理具有很廣的應用,而且比較直觀和有趣,建議你可以從深度學習的圖像處理入手。深度學習的圖像處理,最基本的知識是卷積神經網絡,所以你可以先學習卷積神經網絡。網上有很多關於卷積神經網絡的介紹,這裏就不贅述了。

理解卷積神經網絡關鍵是理解卷積神經網絡的學習機制,理解爲什麼能夠學習。想要理解這一點,首先需要明確兩個關鍵點“前向傳播”和“反向傳播”。整個神經網絡在結構和激活函數確定之後,所謂“訓練”或者“學習”的過程,其實就是在不斷地調整神經網絡的每個權重,讓整個網絡的計算結果趨近於期望值(目標值)。前向傳播是從輸入端開始計算,目標是得到網絡的輸出結果,再將輸出結果和目標值相比較,得到結果誤差。之後將結果誤差沿着網絡結構反向傳播拆解到每個節點,得到每個節點的誤差,然後根據每個節點的誤差調整該節點的權重。“前向傳播”的目的是得到輸出結果,“反向傳播”的目的是通過反向傳播誤差來調整權重。通過兩者互相交替迭代,希望達到輸出結果和目標值一致。

理解卷積神經網絡之後,我們可以動手實現手寫字體識別的示例。掌握之後,可以接着學習深度學習裏的物體檢測算法,例如YOLO、FasterR-CNN等,最後可以動手用TensorFlow都寫一遍,跑跑訓練數據、調調參數,邊動手邊理解。在學習過程中,要特別留意算法模型的設計思想和解決思路。

2.效果優化
效果優化指提升算法模型的準確率等指標,通常的方式有以下幾種:

優化訓練數據;
優化算法設計;
優化模型訓練方式
優化訓練數據
因爲算法模型是從訓練數據中學習的,模型無法學習到訓練數據之外的模式。所以,在選擇訓練數據時要特別小心,必須使得訓練數據包含實際場景中會出現的模式。精心挑選或標註訓練數據,會有效提升模型的效果。訓練數據的標註對效果非常重要,以至於有創業公司專門從事數據標註,還獲得了不少融資。

優化算法設計
根據問題採用更好的算法模型,採用深度學習模型而不是傳統的機器學習模型,採用具有更高特徵表達能力的模型等,例如使用殘差網絡或DenseNet提高網絡的特徵表達能力。

優化模型訓練方式
優化模型訓練方式包括採用哪種損失函數、是否使用正則項、是否使用Dropout結構、使用哪種梯度下降算法等。

3.計算量優化
雖然我們在框架側做了大量的工作來提高計算性能,但是如果在算法側能夠減少計算量,那麼整體的計算實時性也會提高。從模型角度,減少計算量的思路有兩種,一種是設計輕量型網絡模型,一種是對模型進行壓縮。輕量型網絡設計學術界和工業界都設計了輕量型卷積神經網絡,在保證模型精度的前提下,大幅減少模型的計算量,從而減少模型的計算開銷。這種思路的典型代表是谷歌提出的MobileNet,從名字上也可以看出設計的目標是移動端使用的網絡結構。MobileNet是將標準的卷積神經網絡運算拆分成Depthwise卷積運算和Pointwise卷積運算,先用Depthwise卷積對輸入各個通道分別進行卷積運算,然後用Pointwise卷積實現各個通道間信息的融合。

模型壓縮
模型壓縮包括結構稀疏化和蒸餾兩種方式。

在邏輯迴歸算法中,我們通過引入正則化,使得某些特徵的係數近似爲0。在卷積神經網絡中,我們也希望通過引入正則化,使得卷積核的係數近似爲0。與普通的正則化不同的是,在結構稀疏化中,我們希望正則化實現結構性的稀疏,比如某幾個通道的卷積核的係數全部近似爲0,從而可以將這幾個通道的卷積核剪枝掉,減少不必要的計算開銷。

蒸餾方法有遷移學習的意思,就是設計一個簡單的網絡,通過訓練的方式,使得該簡單的網絡具有目標網絡近似的表示能力,從而達到“蒸餾”的效果。

Android開發同學的機會
移動端機器學習的計算框架和算法,前者負責模型計算的性能,減少時間開銷;後者主要負責模型的精度,還可以通過一些算法設計減少算法的計算量,從而達到減少時間開銷的目的。

需要注意的是,在移動端機器學習中,算法模型的訓練通常是在服務器端進行的。目前,終端設備通常不負責模型的訓練。在使用時,由終端設備加載訓練結果模型,執行前向計算得到模型的計算結果。

但是前面講了那麼多行業趨勢和機器學習的基本技術,那對於移動開發的同學來說,如何進入這個“熱門”的領域呢?移動端機器學習是邊緣智能計算範疇的一個領域,而且移動端開發是Android開發同學特別熟悉的領域,所以這也是Android開發同學的一個發展機會,轉型進入邊緣智能計算領域。Android開發同學可以發揮自己的技術專業優勢,先在邊緣計算的終端設備程序開發中站穩腳跟,在未來的技術分工體系中有個堅固的立足點;同時,逐步學習深度學習算法,以備將來往前邁一步,進入邊緣智能計算領域,創造更高的技術價值。

可能在大部分情況下,Android開發同學在深度學習算法領域,跟專業的算法同學相比,不具有競爭優勢,所以我們千萬不要放棄自己所專長的終端設備的開發經驗。對大多數Android開發同學而言,“專精Android開發並懂深度學習算法”纔是在未來技術分工中,創造最大價值的姿勢。

對於學習路徑,我建議Android開發同學可以先學習卷積神經網絡的基礎知識(結構、訓練和前向計算),然後閱讀學習NCNN開源框架,掌握計算性能的優化方法,把開發技術掌握好。同時,可以逐步學習算法技術,主要學習各種常見的深度學習算法模型,並重點學習近幾年出現輕量型神經網絡算法。總之,Android開發同學要重點掌握提高計算實時性的開發技術和算法技術,兼顧學習深度學習算法模型。

基於前面的描述,我梳理了移動端機器學習的技術大圖供你參考。圖中紅圈的部分,是我建議Android開發同學重點掌握的內容。

在這裏插入圖片描述

Markdown 已選中 5169 字數 105 行數 當前行 105, 當前列 63HTML 4783 字數 71 段落

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章