關於梯度下降,Pete Moore Molly 幾個人將個人心得做一番討論… mini-batch stochastic gradient descent 在每次更新參數時,從數學公式,就只先看 這一個參數的一次Iteration的調整:
又等於
這方程式意味著 mini-batch stochastic gradient descent它只有從隨機挑選的 Batch (前兩篇的程式裡設定是10筆)裡的數據去計算 應該要往哪個方向調整。
上述的說法亦可套用在另外兩個參數上 與 。
有幾個方向可以討論的:
對於第1.點 Moore 理解計算量隨數據增長,不認為在實務上可能是千億筆的數據可行。Pete 談到他看過一篇論文提到 Large Batch的優缺點,不見得只因硬體限制,記憶體限制而不用全部的數據計算,用較小的Batch 可以帶來一點隨機性的梯度的更新方向,反過來可以幫助找到全局的最佳解。
但是如果太小,只設為1就成了 Stochastic gradient descent,他更新的方向變得很隨機,變得有點團團轉,有時後訓練就無法收斂。
Fields 用統計的觀點來看,更新方向會變得團團轉,是因為數據有噪音,只要抽樣大約30筆當作一個Batch,就可以大幅降低噪點數據的影響力,那又回到昨天對 Batch Size 的金髮姑娘原則 在GPU 計算資源(主要是VRAM)足夠下,儘量設超過30,這樣可以享受平行運算的速度外,也可以加速收斂。關於 Batch Size, Yoshua Bengio 有篇論文Practical recommendations for gradient-based training of deep architectures特別說明實務上的經驗值。
這個話題結束,Fields 趕快依照动手学深度学习以 Gluon 來實現線性迴歸,跟大家講解一下現階段百家爭鳴,對初學者來講,沒必要從無到有寫機器學習的演算法。他是數學出身的,打算從演算法著手,所以他才必須學這個從無到有的實作,對大家而言應該從高階的入門,演示程式如下:
#略去與前面文章一模一樣的代碼,主要就是要創造虛擬的房價與(面積,屋齡)訓練數據集
from mxnet.gluon import data as gdata
batch_size = 10
#資料迭代輸出給訓練器用,大多數的框架都有提供類似的
dataset = gdata.ArrayDataset(features, labels)
data_iter = gdata.DataLoader(dataset, batch_size, shuffle=True)
程式裡面看到 gluon。 這是 Amazon Web Service Mxnet與微軟的Cognitive Toolkit所支持的簡單易懂的開發介面,讓機器學習的設計師們可快速建立神經網路模型並進行訓練的實驗驗證,同時協助底層對應的框架或引擎做優化以加速訓練速度,這對不是計算理論出身的模型設計人員是一大福音。
Moore 聽到這裡又忍不住嗆:"那為何不用 Keras,這個更多人使用,幾乎每一個機器學習入門教材都會談到 Keras。"
Gavin 以 Product Owner 調停,繼續維持在需求還不明朗情況下,專案技術探索多樣化,所以支持對 mxnet 與 gluon 的了解,並鼓勵 Moore 看能否協助了解 Keras 如何處理這個問題。Moore 允諾下一個 Sprint 處理。 Fields 繼續:
from mxnet.gluon import nn
net = nn.Sequential()
#逐層串堆疊深度網路,不過我們只有一層淺層網路,但同樣也是用這網路類型
net.add(nn.Dense(1))
#只一層,而且是全連接層(Dense)
from mxnet import init
net.initialize(init.Normal(sigma=0.01))
#參數隨機取值做為初始值,後續訓練時每個 Iteration 更新
from mxnet.gluon import loss as gloss
loss = gloss.L2Loss()
#我們自己寫的 MSE損失函數其實就是 L2Norm,用現成的函數 L2Loss
from mxnet import gluon
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.03})
#定義用隨機梯度下降SGD(名字誤導了,實際上是 mini-Batch SGD)當訓練器
num_epochs = 3
for epoch in range(1, num_epochs + 1):
for X, y in data_iter:
with autograd.record():
l = loss(net(X), y)
l.backward()
trainer.step(batch_size) #一個 step 就是前文所說的 Iteration
l = loss(net(features), labels)
print('epoch %d, loss: %f' % (epoch, l.mean().asnumpy()))
這個架構已經沒有之前特別用 weight 或者 bias 這樣命名的變量了,我們要從網路 dense 來取值
dense = net[0]
dense.weight.data(), dense.bias.data()
#這樣就把參數 w 與 b 取出了
專案緣起記錄在 【UP, Scrum 與 AI專案】