我找了好幾天還是找不太到關於DJL的學習資源,所以就想說自己來寫一個,把學習過程打出來讓大家少踩一點雷,而且我覺得不寫筆記我會忘記XD
然後筆記中參雜大量我個人的理解,如果有錯誤的畫歡迎指正,抱歉。
使用教材:https://d2l.djl.ai/
筆記內所有演算法大部分皆採自其中。
Deep Java Library原身是MXNet,由中國的工程師們一起共同進行開發,支援多語系,後來被AWS收購,2019年被正式發布,擁有良好的框架適配性…吧?(待嘗試)
但是速度比tf快很多是真的,希望能夠給我帶來許多驚喜。
ndarray的api呼叫方式:https://reurl.cc/ZQ79np
為什麼需要利用ndarray進行陣列操作?
我覺得這個是最重要的問題,可能是因為這樣可以有效的加速陣列的運算以及非常好的去進行記憶體管理吧。
我覺得這個例子可以滿清楚的說明的。
(初始化)
輸出結果為7.32860 sec
輸出結果為0.10299 sec
我滿震驚的,並想了一下為什麼會有這麼大的速度差異,可能是因為把陣列封裝成NDArray之後,可以直接進行一些加速運算吧,在這裡不贅述,但不可否認的是NDArray對你的計算速度具有非常強大且正面的助益。
記憶體控管是深度學習領域的難題之一。
Java在管理記憶體方面存在一些麻煩的地方。首先,java他的垃圾回收機制無法有效控管深度學習中所使用的記憶體。而手動進行記憶體的釋放會使code變得比較不高效。另外,java系統缺乏對釋放記憶體的支持。所以djl特別創造了NDManager 來釋放(控管)記憶體。
這是djl開發團隊對於記憶體控管方面做的解釋
If the native resources is no longer used, we allow GC(垃圾回收機制) collect it's native memory before NDManager close them. However, there are still some limitations. For example, it may cause OOM(Out of memory記憶體不足) if preprocessing and postprocessing create a large amount of NDArrays in the training loop before GC kicks in.
如果中間NDArray(例如從Trainer-> Model)進入上層NDManager,則會發生記憶體洩漏的事件。
解決方案:
線性模型應該是最簡單也最適用於各種數據的模型,也不會發生資料跟模型過度擬合反而準確率下降的情況,但缺點是…他的模型就是線性,在許多情況之下並非最佳切法。
線性算法不太能算得上是深度學習,他比較像是不斷的進行數據取出,然後根據取得的數據放入模型後的結果,修正權重讓模型更加精準。
基本上所有的機器學習算法都是依照這個虛擬碼來做。
首先,線性回歸是什麼?
線性回歸是利用稱為線性迴歸方程式的最小平方函數對一個或多個自變數和應變數之間關係進行建模的一種迴歸分析。
線性回歸模型:
其中ϵ為偏差值(noice),在建立模型的時候,我們會給他一個平均為0的常態分佈,標準差可以視數據進行調整。
其實就是高中學的統計,就是從計算改成弄出數據集,也不用想的太難啦,嘻嘻。
我用釋例使用djl生成了一個數據集,如下。
class結構
執行後會生成下圖
有了數據集之後,就可以利用數據集來訓練我的模型了。
底下是模型實作的部分
最重要的部分,沒了不管你其他函式寫得多精妙都無法代回Model進行後續運算。
後續藉由他來定義如何對原有權重進行更動,使模型更加貼近數據。
他的理論我覺得滿重要的,但是不適合放這裡,會模糊焦點。
請參閱附錄
優化算法有很多種,是找出最佳權重的具體行動,以下是隨機梯度下降(SGD)在DJL中的程式碼實現。
每次對於權重進行更動的大小取決於學習率 lr。因為我們的損失是通過隨機選取後載入的數據來計算的,所以我們通過批次大小(batchSize)對步長進行歸一化,因此典型步長的大小在很大程度上不取決於我們對批次大小的選擇。
得出的結果是:
Output Data
在訓練中,numEpochs(學習次數)以及lr(學習率)是需要透過不斷的測試和進行調整來讓訓練結果更加符合你的模型的。
在使用較先進的算法的時候,要小心學習次數過高的話,會發生找出來的方程過度擬合數據集的情況。
簡單來講,批次大小將決定我們一次訓練的樣本數目。
batchsize影響模型的優化程度和速度。
適當的增加BatchSize的優點:
1.通過並行化提高記憶體利用率。
2.單次epoch的迭代次數減少,提高執行速度。
(單次epoch=(全部訓練樣本/batchsize)/iteration=1)
3.適當的增加BatchSize,梯度下降方向準確度增加,訓練震動的幅度減小。
相對於正常資料集,如果BatchSize過小,訓練資料就會非常難收斂,從而導致underfitting。
增大BatchSize,相對的會讓處理速度加快,但所需記憶體容量增加。
(epoch的次數需要增加以達到最好的結果)
這裡我們發現上面兩個矛盾的問題,因為當epoch增加以後同樣也會導致耗時增加從而速度下降。因此我們需要尋找最好的Batch_Size,在記憶體效率和記憶體容量之間尋找最佳平衡。
迭代是重複反饋的動作,神經網路中我們希望通過迭代進行多次的訓練以達到所需的目標或結果。
每一次迭代得到的結果都會被作為下一次迭代的初始值,感覺就很像神經元不斷傳遞訊息的過程,不是嗎?
一個迭代=一個正向通過及一個反向通過。
一個時期=所有訓練樣本的一個正向傳遞和一個反向傳遞。
(1)batchsize:批次大小。在深度學習中,一般採用SGD訓練,即每次訓練在訓練集中取batchsize個樣本訓練。
(2)iteration:1個iteration等於使用batchsize個樣本訓練一次。
(3)epoch:1個epoch等於使用訓練集中的全部樣本訓練一次。
酷吧!輕輕鬆鬆解決線性回歸。
DJL內部也有給出不用手刻的方式。
由於這章節我完全看不懂他在說什麼,可能我程度有限,就自己講了。
Softmax 回歸是邏輯回歸 (Logistic Regression) 的推廣,邏輯回歸適用於二元分類的問題,而 Softmax 回歸適用於多分類的問題。
舉例來說,大概就是一個大學生在煩惱他的晚餐要吃什麼的時候,可以預測一下他可能會吃的品項,邏輯回歸只能預估他去吃後門還是宵夜街,而 Softmax 回歸可以分析一下他比較可能吃哪一家店。
當分類數量等於 2 時,Softmax回歸與邏輯回歸的結果是一致的。證明可參閱:https://reurl.cc/L0dX2a
Softmax 回歸是使用 Softmax 運算使得最後一層輸出的機率分佈總和為 1,Softmax 函數通常會放在類神經網路的最後一層,將最後一層所有節點的輸出都通過指數函數 (exponential function),並將結果相加作為分母,個別的輸出作為分子。
跟邏輯回歸差不多,基本上就是單層的類神經網路,想要弄更多層也沒數據了。
另外要注意的是,對於數據,拿梯度下降算法來算的話,切出來的數據會有點像是等高線立體地形圖或是梯田的樣子,最上面一塊的最優解是一整塊平坦的台地,這也是我之前邏輯回歸切出來的權重會亂跳的原因,因為結果都是對的。
好啦我根本看不懂這個,所以我換個說法,softmax包含兩個步驟:
程式碼:
沒有特別需要用哪個,不知道的話,梯度下降就可以了
乾,我覺得我寫的好爛,明天一定重寫,感覺還是不太懂他。
好啦,照著範例走一次,之前沒有碰過影像的分析所以卡很久,無法掌握範例不敢寫。
機器學習大部分的算法都有希望最大化/最小化一個函數/指標,這個函數被稱為「目標函數(Object function)」,深度學習用到的目標函數基本上都是「損失函數(loss function)」,而模型的好壞有絕大部分的因素來至損失函數的設計。
我們通常會希望模型預測出來的東西可以跟實際的值一樣。但現實是預測出來的東西基本上跟實際值都會有落差,這個落差在統計上稱為「殘差(residual)」。
損失函數中的損失就是「實際值和預測值的殘差」。
數學上會用y表示實際值,ŷ表示預測值。
error rate=