天天看點

從零建構現代深度學習架構(TinyDL-0.01)

作者:閃念基因
從零建構現代深度學習架構(TinyDL-0.01)

導讀

本文主要以一個Java工程師視角,闡述如何從零(無任何二三方依賴)建構一個極簡(麻雀雖小五髒俱全)現代深度學習架構(類比AI的作業系統)。

本文主要以一個Java工程師視角,闡述如何從零(無任何二三方依賴)建構一個極簡(麻雀雖小五髒俱全)現代深度學習架構(類比AI的作業系統)。這裡的背景部分主要回答兩個經常會碰到的靈魂之問:一、為什麼要做;二、你做和别人做有什麼差別?

為什麼要寫一個深度學習架構?

1.1. 學習擁抱AI

AI是大趨勢,是長賽道,這次不一樣。在雙拐點下Javaer的困境需要轉型适應這個變化。在之前的文章《關于AIGC在互動上的若幹實踐》的最後我講了下感受:

近年來市場與技術環境出現了雙拐點:一方面消費網際網路的發展已經完全進入存量博弈時代增量紅利不再,降本增效成為主旋律;另一方面AI技術的最新發展取得重大突破,在很多方面的效率和成本已經明顯超越人類。 新時代新形勢下也迫使像我這樣的Javaer不得不去轉型擁抱新技術。

對于技術上有兩條新方向:一條以3D為代表的元宇宙相關技術,例如區塊鍊,XR等技術的轉型;另外一條是以大模型為代表的AI方向的轉型。最近開始學習深度學習相關的東西,于是作為Java碼農為了能看懂CNN,DNN,RNN等網絡模型,現在還在惡補線性代數和微積分以及PyTorch。雖都說“人生苦短,我用python”,可是想通過看源代碼,來學習深度學習架構的實作來了解原理的Javaer,Python天馬行空的風格,确實讓我覺得人生苦短(這裡沒有任何語言論戰之意)。

大實體學家費曼說,“凡我不能創造的,我就不能了解 ”。我想他大概是對的吧,于是我也想試一試。

1.2. just for fun,向linux-0.01 緻敬

1991年9月17日,21歲的芬蘭學生林納斯在網上釋出了開源作業系統Linux-0.01[1],代碼整潔,目錄清晰。本着東施效颦的做法,我也特意将版本号成0.01, TinyDL-0.01(Tiny Deep Learning)[2], 也算向linux-0.01 緻敬了。分享給對AI有興趣Javaer,可以從底層工程角度了解深度學習的原理以及簡單的實作,有興趣的小夥伴可以一起互相學習。

2. 與别人的有什麼不同?

深度學習架構有很多,比較多用python編寫的(底層是C/C++) 例如 TensorFlow,PyTorch以及MXNet等。Java實作的深度學習架構比較知名的有兩個:一個是DeepLearning4J[3]由于Eclipse開源社群維護, 還有一個DJL[4]是AWS的開源的深度學習 Java 架構。

DeepLearning4J是一個全棧的實作,過于複雜龐大的技術棧(65%Java 69.7w行,24%C++ ,3.4%Cuda等)且依賴過多複雜科學計算的三方庫,顯然很難通過代碼來學習。

DJL隻是一套面向深度學習的Java高層次的接口,并沒有任何真正的實作,最終是運作在TensorFlow或PyTorch深度學習引擎上的。

TinyDL-0.01[5]如它的名字一樣,是一個最小化實作的輕量級深度學習架構(Java實作)。相比與其他實作:1)極簡,基本上零二三方依賴(為了不想引入Junit,我有了不寫單測的理由了);2)全棧,從最底層的張量運算到最上層的應用案例,3)分層易擴充,每一層的實作都包括了核心概念和原理且層邊界清晰。當然不足之處更明顯:功能簡陋性能較差。

TinyDL-0.01雖然隻是一個tony級别的架構,但它嘗試具有現代深度學習架構的基本特性(動态計算圖,自動微分,多優化器,多類型網絡層實作等),主打一個簡單明了,主要用于入門學習使用。如果想通過看PyTorch等架構的代碼來深度了解深度學習,那基本直接勸退。

一、整體架構

深度學習架構主要解決的是深度網絡訓練和推理的工程問題,包括多層神經網絡組成的複雜性問題,大量的矩陣運算和并行計算的計算效率問題,以及支援在多個計算裝置的擴充性問題等等。常用的深度學習架構包括:TensorFlow,由Google開發的開源架構;PyTorch,由Facebook開發的開源架構;MXNet,由Amazon開發的開源架構等等。經過多年的發展,它們的架構和功能都慢慢趨同,先看下一個現代深度學習架構的通用能力有哪些。

1. 深度學習通用架構是什麼樣的?

先來看下chatGPT是如何回答這個問題的:

從零建構現代深度學習架構(TinyDL-0.01)

這裡也具體參考當下最流行的深度學習架構PyTorch,大體分成四層(來自知乎):

從零建構現代深度學習架構(TinyDL-0.01)

2. TinyDL的整體架構是什麼樣的?

TinyDL的秉承簡潔分層清晰的原則,并參考了通用的分層邏輯,整體的結構如下:

從零建構現代深度學習架構(TinyDL-0.01)

從下至上保持嚴格的分層邏輯:

1、ndarr包:核心類 NdArray,底層線性代數的簡單實作,目前隻實作CPU版本,GPU版本需要依賴龐大的三方庫。

2、func包:核心類Function與Variable 分别是抽象的數學函數與變量的抽象,用于在前向傳播時自動建構計算圖,實作自動微分功能,其中Variable對應PyTorch的tensor。

3、nnet包:核心類Layer與Block表示神經網絡的層和塊,任何複雜的深度網絡都是依賴這些Layer與Block的堆疊而層。實作了一些常用的cnn層rnn層norm層以及encode與decode的seq2seq架構等等。

4、mlearning 包:機器學習的通用元件的表示,深度學習是機器學習的一個分支,對應更廣泛的機器學習有一套通用的元件,包括資料集,損失函數,優化算法,訓練器,推導器,效果評估器等。

5、modality 包:屬于應用層的範疇,目前深度學習主要應用任務圖形圖像的視覺,自然語言處理以及強化學習三部分,暫時還沒有相應的領域的實作,希望在0.02版中實作GPT-2等原型。

6、example包:一些簡單的能跑通的例子,主要包括機器學習的分類和回歸兩類問題,有曲線的拟合,螺旋曲線的分類,手寫數字的識别以及序列資料的預測。

接下來就從下至上,全棧式地簡答串一下每層涉及的核心概念和簡單實作。

二、線性代數與張量運算

首先進入深度學習的第一層:張量操作層。張量(多元數組)的操作和計算是深度學習的基礎,所有運算幾乎都是基于張量的運算(單個數字稱為标量,一維數稱為向量,二維數組稱為矩陣,三維以及以上數組稱為N維張量)。這些操作通常使用高效的數值計算庫來實作,通過C/C++語言在特定的計算硬體上實作的,提供了各種張量操作,如矩陣乘法、卷積、池化等。

這一部分主要分三塊,首先關于線性代數的一些基本知識,然後是基于CPU的最小化實作,最後對比為什麼深度學習重依賴一種全新的計算範型GPU。

1. 基礎的線性代數

先上一張圖來直接勸退下大家,雖然當初考研的時候,這些隻算最基本的八股練習題:

從零建構現代深度學習架構(TinyDL-0.01)

然後是一些線性代數的常見概念:

向量:向量是一個有大小和方向的量,線上性代數中,向量通常用一列數表示。

矩陣:矩陣是一個二維數組,由行和列組成,它可以用于表示線性方程組或者線性變換。

向量空間:向量空間是由一組向量構成的集合,滿足一些特定的性質,如封閉性、加法和數量乘法的結合性等。

線性變換:線性變換是一種将一個向量空間映射到另一個向量空間的操作。它保留線性組合和共線關系。

線性方程組:線性方程組是一組線性方程的集合,其中每個方程都滿足變量的次數為1,并且具有線性關系。

特征值和特征向量:在矩陣中,特征值是一個标量,特征向量是一個非零向量,滿足矩陣與該向量的乘積等于特征值乘以該向量。

内積和外積:内積是向量之間的一種運算,用于度量它們之間的夾角和長度,外積是向量之間的一種運算,用于生成一個新的向量,該向量垂直于原始向量。

行列式:行列式是一個标量值,由一個方陣的元素按照特定的規則組合而成,它用于計算矩陣的逆、判斷矩陣的奇偶性等。

有沒有點頭大?但是如果你看到CPU版本的簡單實作[6],你也會瞬間覺得如此簡單(目前隻支援标量&向量&矩陣,暫不支援更高次元的張量)。

2. CPU版本的簡單實作

/**

 * 支援,1,标量;2.向量;3,矩陣,

 * <p>

 * 暫不支援,更高緯度的張量,更高維的通過Tensor來繼承簡單實作

 */

public class NdArray {

protected Shape shape;

/**

     * 真實存儲資料,使用float32

     */

private float[][] matrix;

}

/**

 * 表示矩陣或向量的形狀

 */

public class Shape {

/**

     * 表示多少行

     */

public int row = 1;

/**

     * 表示多少列

     */

public int column = 1;

public int[] dimension;

}
           

其實都是一些對二維數組的操作:大緻分三類,首先是一些簡單初始化函數;其次是基本的四則運算加減乘除,還有一些運算會對矩陣改變形狀,其中内積是最長的。

3. 為什麼需要GPU

通過上面在CPU上實作的的矩陣操作,特别是一個簡單内積運算需要多層for循環嵌套,大家就知道,在CPU上這種為邏輯控制轉移設計的架構,其實并不能很好地實作并行運算。而矩陣運算的行列其實是可以并行的,是以深度學習依賴的矩陣運算在CPU上是極其低效的。為了更直覺地對比可以參考下圖,相比于CPU,GPU的控制邏輯單元較弱(藍色單元),但是具有大量的ALU(算術邏輯 綠色單元)。

從零建構現代深度學習架構(TinyDL-0.01)

大部分深度學習架構(如TensorFlow、PyTorch等)都提供了對GPU的支援,可以友善地利用GPU進行并行計算。随着今年chatGPT的爆發,GPU已經成為AI的基礎設施,快速成為一種全新的主流計算範式。

三、計算圖與自動微分

現在來到深度學習架構的第二層:func層,主要實作深度學習架構非常重要的特性,計算圖與自動微分。

1)計算圖是一種圖形化表示方式,用于描述計算過程中資料的流動和操作的依賴關系。在深度學習中,神經網絡的前向傳播和反向傳播過程可以通過計算圖來表示。

2)自動微分是一種計算導數的技術,用于計算函數的導數或梯度。在深度學習中,反向傳播算法就是一種自動微分的方法,用于計算神經網絡中每個參數對于損失函數的梯度。

通過計算圖和自動微分的結合,可以有效地計算複雜神經網絡中大量參數的梯度,進而實作模型的訓練和優化。

1. 數值與解析微分

1.1. 數值微分

導數是函數圖像在某一點處的斜率,也就是縱坐标增量(Δy)和橫坐标增量(Δx)在Δx->0時的比值。微分是指函數圖像在某一點處的切線在橫坐标取得增量Δx以後,縱坐标取得的增量,一般表示為dy。

從零建構現代深度學習架構(TinyDL-0.01)

數值微分是一種用數值方法來近似計算函數的導數的方法,其目的是通過計算函數在某個點附近的有限差分來估計函數的導數值。求解使用比較多的是中心差分, 通過近似計算函數在某個點的導數,使用函數在該點前後一個點的函數值來計算,公式如下:f'(x) ≈ (f(x + h) - f(x - h)) / (2h)。其中,h是差分的步長,步長越小,計算結果越精确。數值微分是一種近似計算方法,計算結果與真實的導數值存在一定誤差。

1.2. 解析微分

解析微分是微積分中的另一種方法,用于精确計算函數在某個點的導數值。它通過應用導數的定義和基本的微分規則來求解導數。可以根據函數的定義,确定函數表達式。例如,給定一個函數 f(x),需要确定它的表達式,如 f(x) = x^2 + 2x + 1。例如以下是一些常用函數的解析微分:

從零建構現代深度學習架構(TinyDL-0.01)

2. 計算圖

計算圖被定義為有向圖,其中節點對應于數學運算, 計算圖是表達和評估數學表達式的一種方式。例如, 有以下等式 g=(x+y)∗z,繪制上述等式的計算圖。

從零建構現代深度學習架構(TinyDL-0.01)

計算圖具有加法節點(具有“+”符号的節點)和乘法節點,其具有三個輸入變量xyz以及一個輸出g。

現在看下一個更複雜的函數:

從零建構現代深度學習架構(TinyDL-0.01)

以下函數f(x,y)的計算圖如下:

從零建構現代深度學習架構(TinyDL-0.01)

計算圖的優點是能夠清晰地表示複雜的函數計算過程,并且友善進行反向傳播和參數更新。在深度學習中,計算圖通常用于建構神經網絡模型,其中每個節點表示神經網絡的層或操作,邊表示神經網絡層之間的資料流。通過建構計算圖,可以将複雜的函數計算過程分解為一系列簡單的操作,利用反向傳播算法計算每個節點的梯度,進而實作對模型參數的優化和訓練。

3. 反向傳播

網上找到一個比較形象的例子來說明反向傳播:假設現在要購買水果,在我們日常的思維當中這是一件非常簡單的事情,計算一下價格然後給錢就完事了,但實際上這個過程可以抽象成一張計算圖,當中是包含了若幹步驟的。比如下圖,看到需要先計算蘋果的價格乘上個數,再乘上消費稅,最後得到的才是真正的支付額。

從零建構現代深度學習架構(TinyDL-0.01)

上面的過程叫正向傳播,那反向傳播也很好了解,字面意思是方向相反,但是實際上計算方式也略有不同。假設在上圖買水果的例子當中,我們希望知道蘋果對于最終價格的導數是多少,我們應該怎麼計算?

正向傳播是為了計算模型的最終結果,那麼反向傳播是為了什麼?當然是為了得到模型當中每一個參數對于結果的影響系數,進而可以根據這個系數調整參數,使得模型的結果更好。很顯然需要反向一層一層地往前計算,也就是一層一層地把系數乘起來,其實這裡的系數就是每一層的導數。

從零建構現代深度學習架構(TinyDL-0.01)

反向傳播使用與正方向相反的箭頭(粗線)表示 , 反向傳播傳遞“局部導數”,将導數的值寫在箭頭的下方。在這個例子中,反向傳播從右向左傳遞導數的值(1→1.1→2.2)。從這個結果中可知,“支付金額關于蘋果的價格的導數”的值是 2.2。這意味着,如果蘋果的價格上漲 1 日元, 最終的支付金額會增加 2.2 日元(嚴格地講,如果蘋果的價格增加某個微小值,則最終的支付金額将增加那個微小值的2.2 倍)。

鍊式法則

鍊式法則是微積分中的一個重要定理,用于求複合函數的導數,偏導數是多元函數對其中一個變量的偏微分,鍊式法則同樣适用于多元函數的偏導數。假設有兩個函數:y = f(u) 和 u = g(x),其中 y 是 x 的函數。那麼根據鍊式法則,y 對 x 的導數可以通過求 f 對 u 的導數和 g 對 x 的導數的乘積來計算。具體而言,鍊式法則可以表示為:dy/dx = (dy/du) * (du/dx)。要計算一個複雜函數的導數,采取的就是鍊式求導的方式。神經網絡其實本質上就可以看成是一個複雜函數,就是對一個複雜函數求導。

從零建構現代深度學習架構(TinyDL-0.01)

很難簡單講清楚,畢竟背後是大學通識課裡最難的,大學第一年很多同學都挂在了這棵樹上-高數,感興趣的同學可以參閱《深度學習的數學》[7]。

4. func層的設計與實作

func層最核心的類就是 Function以及Variable,對應于一個抽象的數學函數形式y=f(x) 中,x和y表示Variable 變量,f()表示一個函數Function。每個具體的function的實作需要實作兩個方法:forward與backward。

/**

     * 函數的前向傳播

     *

     * @param inputs

     * @return

     */

    public abstract NdArray forward(NdArray... inputs);




    /**

     * 函數的後向傳播,求導

     *

     * @param yGrad

     * @return

     */

    public abstract List<NdArray> backward(NdArray yGrad);
           

例如一個Sigmoid的函數實作如下:

public class Sigmoid extends Function {

    @Override

    public NdArray forward(NdArray... inputs) {

        return inputs[0].sigmoid();

    }




    @Override

    public List<NdArray> backward(NdArray yGrad) {

        NdArray y = getOutput().getValue();

        return Collections.singletonList(yGrad.mul(y).mul(NdArray.ones(y.getShape()).sub(y)));

    }




    @Override

    public int requireInputNum() {

        return 1;

    }

}
           

Variable 的是實作如下,表示數學中的變量的抽象,其中backward 是反向傳播的入口函數。

**

 * 數學中的變量的抽象

 */

public class Variable {

    private String name;




    private NdArray value;




    /**

     * 梯度

     */

    private NdArray grad;




    /**

     * 保持是函數對象生成了目前Variable

     */

    private Function creator;




    private boolean requireGrad = true;




    /**

     * 變量的反向傳播

     */

    public void backward() {}

}
           

整個func層的實作如下:

從零建構現代深度學習架構(TinyDL-0.01)

四、神經網絡與深度學習

神經網絡由多個神經元組成的網絡,在模拟生物神經系統的基礎上進行資訊處理和學習。神經網絡的設計靈感來源于人類大腦中神經元之間的互相作用。在神經網絡中,每個神經元接收來自其他神經元的輸入,并根據輸入的權重進行權重求和,然後将結果傳遞給激活函數進行處理并産生輸出。神經網絡的學習過程通常通過調整網絡中神經元之間的連接配接權重來實作,使得網絡能夠根據輸入資料進行預測和分類。如下圖是神經元的生物和數學兩種模型的表示。

從零建構現代深度學習架構(TinyDL-0.01)

神經網絡是由多個節點組成的層次結構,每個節點通過權重和非線性激活函數的計算來處理輸入資料,并将結果傳遞給下一層節點。而深度學習是在神經網絡基礎上使用多個隐藏層的深層神經網絡。神經網絡是深度學習的基礎模型,而深度學習在神經網絡的基礎上引入了多層網絡結構,可以自動學習更加抽象和進階的特征表示。

1. 誤差反向傳播算法

2006年,Hinton等人提出了一種基于無監督學習的深度神經網絡模型。模型的訓練通過一種全新的方法來解決梯消失的問題,逐層訓練打破了以往深度網絡難以訓練的困境,為深度學習的發展奠定了基礎開創了深度學習。但是現代深度學習仍然是采用誤差反向傳播(backpropagation)算法進行訓練的,主要原因有:一些新的激活函數的提出,正則化參數初始化等方法的改進,還有全網絡的梯度下降訓練的高效等等。

反向傳播算法是訓練神經網絡的主要方法,基于梯度下降,通過計算損失函數對網絡參數的梯度,然後按照梯度的反方向調整網絡參數,進而使得網絡的輸出更接近于真實值。反向傳播算法利用鍊式法則,将網絡的輸出與真實值之間的誤差逐層傳遞回網絡的輸入層,計算每一層參數的梯度。具體如下:

  1. 正向傳播:将輸入樣本通過神經網絡的前向計算過程,得到網絡的輸出值。
  2. 計算損失函數:将網絡的輸出值與真實值之間的差異,作為損失函數的輸入,計算網絡預測值與真實值之間的誤差。
  3. 反向傳播:根據損失函數的值,逐層計算每個參數對損失函數的梯度。通過鍊式法則,将上一層的梯度乘以目前層的激活函數對輸入的導數,得到目前層的梯度,并傳遞到前一層,逐層計算直到輸入層。
  4. 更新網絡參數:使用梯度下降算法,按照梯度的反方向更新每個參數的值,使得損失函數逐漸減小。
  5. 重複上述步驟,直至達到訓練停止的條件,或者達到最大疊代次數。

反向傳播算法的核心思想,是通過計算每一層參數的梯度,逐層更新網絡參數,進而使網絡能夠逼近真實值。

從零建構現代深度學習架構(TinyDL-0.01)

誤差反向傳播算法在深度神經網絡中面臨的一個常見挑戰是梯度消失問題。為解決梯度消失問題,很多方法被提出:1)激活函數選擇,使用非線性激活函數,如ReLU(Rectified Linear Unit)或Leaky ReLU,可以幫助減輕梯度消失問題。2)權重初始化,合适的權重初始化可以幫助避免梯度消失。

例如,使用較小的方差來初始化權重,可以保持梯度的合理大小。3)批歸一化(Batch Normalization),是一種在每個小批量資料上進行歸一化的技術,有助于穩定梯度并加速網絡訓練。4)殘差連接配接(Residual Connections),是一種跳躍連接配接的技術,允許激活和梯度在網絡中直接傳播。5)梯度裁剪(Gradient Clipping),是一種限制梯度大小的技術,通過設定一個梯度門檻值,可以防止梯度爆炸,并在一定程度上減輕梯度消失問題等等。這些方法可以單獨或結合使用,以幫助解決梯度消失問題,并促使了深度學習的爆發。

2. 層和塊的堆積

為了實作這些複雜的網絡,一般引入了神經網絡塊的概念。塊(block)可以描述單個層、由多個層組成的元件或整個模型本身。使用塊進行抽象的一個好處是可以将一些塊組合成更大的元件,這一過程通常是遞歸的。通過定義代碼來按需生成任意複雜度的塊,我們可以通過簡潔的代碼實作複雜的神經網絡。

從零建構現代深度學習架構(TinyDL-0.01)
public interface LayerAble {


    String getName();


    Shape getXInputShape();


    Shape getYOutputShape();


    void init();


    Variable forward(Variable... inputs);


    Map<String, Parameter> getParams();


    void addParam(String paramName, Parameter value);


    Parameter getParamBy(String paramName);


    void clearGrads();


}


/**
 * 表示由層組合起來的更大的神經網絡的塊
 */
public abstract class Block implements LayerAble 


/**
 * 表示神經網絡中具體的層
 */
public abstract class Layer extends Function implements LayerAble           

下圖是nnet層的整體類圖,核心是圍繞着Layer以及Block的實作,其中Block是Layer的容器類時 目錄與檔案的關系,其他都是圍繞着它們的實作,每一種Layer或Block的實作,都是一篇知名的學術論文, 其背後都有很深的數學推導(解釋為什麼網絡中加入了該類型的層是有效的):

從零建構現代深度學習架構(TinyDL-0.01)

五、機器學習與模型

先梳理下機器學習與深度學習的關系,如下深度學習隻是神經網絡向縱深發展的一個分支,深度學習隻是機器學習的一個分支,一種模型的特例。

從零建構現代深度學習架構(TinyDL-0.01)

對應更廣泛的機器學習則有一套通用的元件,包括資料集損失函數,優化算法,訓練器,推導器,效果評估器等。在tinyDL中,講機器學習的通用元件于深度學習沒有強綁定在一起,作為單獨的一層來實作,也便于後續擴充出更多非神經網絡的模型,例如随機森林,支援向量機等。

如下圖所示,是mlearning的整體實作:

從零建構現代深度學習架構(TinyDL-0.01)

1. 資料集

DataSet元件定位為資料的加載和預處理轉化成模型可以學習的資料格式。目前一些簡單資料源實作,都是基于資料可以一次裝載到記憶體的實作(ArrayDataset),例如SpiralDateSet以及MnistDataSet等。

從零建構現代深度學習架構(TinyDL-0.01)

2. 損失函數

Loss函數(損失函數)用于度量模型預測值與實際值之間的差異,或者說模型的預測誤差。它是模型優化的目标函數,通過最小化損失函數來使模型的預測結果更接近實際值。

損失函數的選擇取決于所解決的問題類型,例如分類問題、回歸問題或者其他任務。常見的損失函數有:1)均方誤差(Mean Squared Error, MSE):用于回歸問題,在預測值和真實值之間計算平方差的均值。2)交叉熵(Cross Entropy):用于分類問題,比較預測類别的機率分布與真實類别的分布之間的差異。3)對數損失(Log Loss):也用于分類問題,基于對數似然原理,度量二分類模型的預測機率與真實标簽之間的差異等等。損失函數的選擇應該與模型任務和資料特點相比對,合适的損失函數能夠提供更好的模型性能和訓練效果。

目前tinyDL實作了最常用的MSE和softmaxCrossEntropy,其中SoftmaxCrossEntropy将回歸問題轉化為分類問題的方法是将回歸輸出結果映射為類别的機率分布。通過SoftmaxCrossEntropy,回歸問題可以被轉化為多分類問題,模型可以通過最小化SoftmaxCrossEntropy損失函數來進行訓練和優化。預測階段,可以根據機率分布選擇機率最大的類别作為預測結果。

從零建構現代深度學習架構(TinyDL-0.01)

3. 優化器

機器學習中常用的優化器常用的有:1)随機梯度下降法(SGD),每次隻使用一個樣本來計算梯度和更新參數,相比于梯度下降法,計算速度更快。2)批量梯度下降法,每次使用整個訓練集來計算梯度和更新參數,收斂速度相對較慢,但穩定性較好。3)動量優化器,通過引入動量項來加速梯度下降的更新過程,可以在參數更新時考慮之前的梯度變化情況,進而減少震蕩。4)AdaGrad,根據參數的曆史梯度進行學習率的自适應調整,對于頻繁出現的特征會降低學習率,對于稀疏出現的特征會增加學習率。5)Adam,結合了動量優化器和RMSProp的優點的優化器,Adam優化器通常具有較快的收斂速度和較好的性能等等。目前tinyDL實作了最常用的SGD和Adam:

從零建構現代深度學習架構(TinyDL-0.01)

六、應用任務與小試

深度學習可以在許多領域中應用,特别在計算機視覺,例如深度學習在圖像分類、目标檢測、物體識别、人臉識别、圖像生成等方面有廣泛應用,還有自然語言處理,應用于機器翻譯、文本分類、情感分析、語義了解、問答系統等領域,如智能助理、社交媒體分析等。其中目前的大模型的AIGC的兩個主要的方向分别是 text2Image以及 text2text,主要的模型架構是stblediffusion與 transformer。這些是依賴于強大完善的基礎能力建設的,目前tinyDL-0.01目前還隻能支援一些小模型的訓練和推導。如下:

1. 直線和曲線的拟合

從零建構現代深度學習架構(TinyDL-0.01)

2. 螺旋資料分類問題

從零建構現代深度學習架構(TinyDL-0.01)

其中第三張圖,可以看到模型可以學習出非常清晰的區塊邊界。

3. 手寫數字分類問題

從零建構現代深度學習架構(TinyDL-0.01)

在深度學習中,手寫數字分類問題是一個經典的問題,常用于介紹和學習深度學習算法,該問題的目标是将手寫的數字圖像正确地分類成相應的數字。

簡單地經過50輪的訓練後,loss從1.830 減少到0.034。在測試資料集上,預測的準确達到96%(世界上最好的準确度應該做到了99.8%)。

從零建構現代深度學習架構(TinyDL-0.01)

4. 通過RNN拟合cos曲線

rnn的計算圖如下:

遞歸隐藏層視窗為3的時候計算圖:

從零建構現代深度學習架構(TinyDL-0.01)

遞歸隐藏層視窗為5的時候計算圖:

從零建構現代深度學習架構(TinyDL-0.01)

七、小結

1、TinyDL隻是一個對Javaer入門AI友好的Demo架構

一直堅信整潔的代碼會自己說話,争取做到代碼本身文檔。以上寫了那麼多,其實最好的方式是直接debug一下。同時TinyDL隻是為了對Javaer學習AI的一個Demo級别的深度學習架構,目前其并不适合真實環境的使用,但是希望對Java程式員擁抱AI起到一點點作用。就目前的趨勢看,Python在AI領域的生态優勢已經非常明顯了,且Python最開始就是對數學表達友好的語言,其在運算符上有大量的重載數學可讀性更強。是以要想真的把AI的能力用起來,Python應該是繞不過的坎。

2、TinyDL-0.02 計劃把todo的能力補上,支援一些進階網絡特性

其中最近大火的Transformer網絡架構和attention層,由于時間匆忙都沒來得及實作,TinyDL-0.02希望基于seq2seq的架構實作 tansfromer的原型;還有模型訓練上,目前是最簡單的單線程運作的,後續會實作參數伺服器的分布式網絡訓練的原型。

3、利用chatGPT協助寫代碼真的可以提升效率

TinyDL中大概1/3的代碼是借助chatGPT完成的,用最近比較流行的說法:程式員将成為自己最後的掘墓人,chatGPT之後碼農命運的齒輪開始反轉。

從零建構現代深度學習架構(TinyDL-0.01)

參考連結:

[1]https://github.com/Leavesfly/linux-0.01/blob/master/README

[2]https://github.com/Leavesfly/TinyDL-0.01

[3]https://github.com/deeplearning4j/deeplearning4j

[4]https://github.com/deepjavalibrary/djl

[5]https://github.com/Leavesfly/TinyDL-0.01

[6]https://github.com/Leavesfly/TinyDL-0.01/blob/main/src/main/java/io/leavesfly/tinydl/ndarr/NdArray.java

[7]https://github.com/jash-git/Jash-good-idea-20200304-001/blob/master/CN%20AI%20book/深度學習的數學.pdf

作者:山澤

來源:微信公衆号:阿裡雲開發者

出處:https://mp.weixin.qq.com/s/tFl0RQd3ex98_SAOIIfM_Q

繼續閱讀