展會(huì)信息港展會(huì)大全

神經(jīng)網(wǎng)絡(luò)中的損失函數(shù)正則化和 Dropout 并手寫(xiě)代碼實(shí)現(xiàn)
來(lái)源:互聯(lián)網(wǎng)   發(fā)布日期:2020-11-19 08:40:43   瀏覽:14478次  

導(dǎo)讀:在深度神經(jīng)網(wǎng)絡(luò)中最常用的方法是Regularization和dropout。在本文中,我們將一起理解這兩種方法并在python中實(shí)現(xiàn)它們 Regularization 正則化 正則化通過(guò)在損失函數(shù)的末尾添加額外的懲罰項(xiàng)來(lái)幫助防止模型過(guò)度擬合。 其中m是批次大...

在深度神經(jīng)網(wǎng)絡(luò)中最常用的方法是Regularization和dropout。在本文中,我們將一起理解這兩種方法并在python中實(shí)現(xiàn)它們

Regularization 正則化

正則化通過(guò)在損失函數(shù)的末尾添加額外的懲罰項(xiàng)來(lái)幫助防止模型過(guò)度擬合。

其中m是批次大校所示的正則化稱為L(zhǎng)2正則化,而L2對(duì)權(quán)重應(yīng)用平方,而L1正則化則采用絕對(duì)值,其形式為| W |。

當(dāng)權(quán)重過(guò)多或權(quán)重太大時(shí),附加的額外項(xiàng)會(huì)增加損失,并且可調(diào)整因子λ著重說(shuō)明了我們要對(duì)權(quán)重進(jìn)行多少懲罰。

為什么添加懲罰會(huì)有助于防止過(guò)度擬合?

直觀的理解是,在最小化新?lián)p失函數(shù)的過(guò)程中,某些權(quán)重將減小至接近零,因此相應(yīng)的神經(jīng)元將對(duì)我們的結(jié)果產(chǎn)生非常小的影響,就好像我們正在使用 更少的神經(jīng)元。

前向傳播:在前進(jìn)過(guò)程中,我們只需更改損失函數(shù)。

def compute_loss(A, Y, parameters, reg=True, lambd=.2):

"""

With L2 regularization

parameters: dict with 'W1', 'b1', 'W2', ...

"""

assert A.shape == Y.shape

n_layer = len(parameters)//2

m = A.shape[1]

s = np.dot(Y, np.log(A.T)) + np.dot(1-Y, np.log((1 - A).T))

loss = -s/m

if reg:

p = 0

for i in range(1, n_layer+1):

p += np.sum(np.square(parameters['W'+str(i)]))

loss += (1/m)*(lambd/2)*p

return np.squeeze(loss)

反向傳播:L2正則化的反向傳播實(shí)際上是直接的,我們只需要添加L2項(xiàng)的梯度即可。

def backward(params, cache, X, Y, lambd=0.2):

"""

params: weight [W, b]

cache: result [A, Z]

Y: shape (1, m)

"""

grad = {}

n_layers = int(len(params)/2)

m = Y.shape[1]

cache['A0'] = X

for l in range(n_layers, 0, -1):

A, A_prev, Z = cache['A' + str(l)], cache['A' + str(l-1)], cache['Z' + str(l)]

W = params['W'+str(l)]

if l == n_layers:

dA = -np.divide(Y, A) + np.divide(1 - Y, 1 - A)

if l == n_layers:

dZ = np.multiply(dA, sigmoid_grad(A, Z))

else:

dZ = np.multiply(dA, relu_grad(A, Z))

# with an extra gradient at the end, other terms would remain the same

dW = np.dot(dZ, A_prev.T)/m + (lambd/m)*W

db = np.sum(dZ, axis=1, keepdims=True)/m

dA = np.dot(W.T, dZ)

grad['dW'+str(l)] = dW

grad['db'+str(l)] = db

return grad

訓(xùn)練過(guò)程:像往常一樣,我們?cè)诙诸惖那闆r下測(cè)試我們的模型,并比較有無(wú)正則化的模型。

沒(méi)有正則化的模型

有正則化的模型

實(shí)際上,當(dāng)?shù)螖?shù)增加時(shí),該模型將繼續(xù)過(guò)擬合,從而導(dǎo)致除法運(yùn)算出錯(cuò),造成這種問(wèn)題的原因可能是在正向過(guò)程中,結(jié)果A太接近于0。

相反,具有正則化的模型不會(huì)過(guò)擬合。

Dropout

Dropout通過(guò)隨機(jī)關(guān)閉某些輸出單元來(lái)防止過(guò)度擬合。

在上述過(guò)程中,在每次迭代中,層[2]上的某些單元將被隨機(jī)關(guān)閉,這意味著在正向過(guò)程中將工作的神經(jīng)元更少,因此簡(jiǎn)化了神經(jīng)網(wǎng)絡(luò)的整體結(jié)構(gòu)。

同時(shí),訓(xùn)練后的模型將更加健壯,因?yàn)樵撃P筒辉倏梢砸蕾嚾魏翁囟ǖ纳窠?jīng)元(因?yàn)樵诖诉^(guò)程中它們可能會(huì)被靜音),因此所有其他神經(jīng)元都需要在訓(xùn)練中學(xué)習(xí)。

前向傳播:你可以理解為Dropout是在前向傳播過(guò)程中增加了一層。

一般情況下,正向傳播方程如下:

其中g(shù)是激活函數(shù)。現(xiàn)在,通過(guò)Dropout將一個(gè)額外的圖層應(yīng)用于A ^ [l]。

添加了Dropout如下:

其中D是Dropout層。Dropout層中的關(guān)鍵因素是keep_prob參數(shù),該參數(shù)指定保留每個(gè)單元的可能性。假設(shè)keep_prob = 0.8,我們將有80%的機(jī)會(huì)保持每個(gè)輸出單位不變,而有20%的機(jī)會(huì)將其設(shè)置為0。

該實(shí)現(xiàn)將為結(jié)果A添加一個(gè)額外的掩碼。假設(shè)我們有一個(gè)包含四個(gè)元素的輸出A ^ {[l]},如下所示,

我們希望在保持其余部分不變的情況下使第三個(gè)單元關(guān)閉,我們需要的是形狀相同的矩陣,并按以下方式進(jìn)行元素逐次乘法,

前向傳播:

def forward(X):

# intermediate layer use relu as activation

# last layer use sigmoid

n_layers = int(len(params)/2)

A = X

cache = {}

for i in range(1, n_layers):

W, b = params['W'+str(i)], params['b'+str(i)]

Z = np.dot(W, A) + b

A = relu(Z)

# dropout

keep_prob = keep_probs[i-1]

D = np.random.rand(A.shape[0], A.shape[1])

D = (D < keep_prob).astype(int)

A = np.multiply(D, A)

# rescale

A = A/keep_prob

cache['Z'+str(i)] = Z

cache['A'+str(i)] = A

cache['D'+str(i)] = D

# last layer

W, b = params['W'+str(i+1)], params['b'+str(i+1)]

Z = np.dot(W, A) + b

A = sigmoid(Z)

cache['Z'+str(i+1)] = Z

cache['A'+str(i+1)] = A

return cache, A

在這里,我們將D初始化為與A相同的形狀,并根據(jù)keep_prob將其轉(zhuǎn)換為0和1矩陣。

請(qǐng)注意,dropout后,結(jié)果A需要重新縮放!由于在此過(guò)程中某些神經(jīng)元被靜音,因此需要增加左神經(jīng)元以匹配預(yù)期值。

反向傳播:過(guò)程是將相同的函數(shù)D屏蔽為相應(yīng)的dA。

# dummy code, full version needs to be inside a Class

def backward(self, cache, X, Y, keep_probs):

"""

cache: result [A, Z]

Y: shape (1, m)

"""

grad = {}

n_layers = int(len(self.params)/2)

m = Y.shape[1]

cache['A0'] = X

for l in range(n_layers, 0, -1):

A, A_prev, Z = cache['A' + str(l)], cache['A' + str(l-1)], cache['Z' + str(l)]

W = self.params['W'+str(l)]

if l == n_layers:

dA = -np.divide(Y, A) + np.divide(1 - Y, 1 - A)

if l == n_layers:

dZ = np.multiply(dA, self.sigmoid_grad(A, Z))

else:

# dropout version

D = cache['D' + str(l)]

dA = np.multiply(dA, D)

# rescale

dA = dA/keep_probs[l-1]

dZ = np.multiply(dA, self.relu_grad(A, Z))

dW = np.dot(dZ, A_prev.T)/m

db = np.sum(dZ, axis=1, keepdims=True)/m

dA = np.dot(W.T, dZ)

grad['dW'+str(l)] = dW

grad['db'+str(l)] = db

return grad

反向傳播方程式與一般的神經(jīng)網(wǎng)絡(luò)網(wǎng)絡(luò)中引入的方程式相同。唯一的區(qū)別在于矩陣D。除最后一層外,所有其他具有丟失的層將對(duì)dA施加相應(yīng)的蒙版D。

注意,在反向傳播中,dA也需要重新縮放。

結(jié)論

正則化和dropout都被廣泛采用以防止過(guò)度擬合,正則化通過(guò)在損失函數(shù)的末尾添加一個(gè)額外的懲罰項(xiàng)來(lái)實(shí)現(xiàn),并通過(guò)在正向過(guò)程中隨機(jī)地使某些神經(jīng)元靜音來(lái)使其退出以使網(wǎng)絡(luò)更加簡(jiǎn)潔來(lái)實(shí)現(xiàn)正則化。

最后所有的代碼都可以在這里找到:https://github.com/MJeremy2017/deep-learning/tree/main/regularization

作者:Jeremy Zhang

deephub翻譯組


贊助本站

相關(guān)內(nèi)容
AiLab云推薦
推薦內(nèi)容
展開(kāi)

熱門(mén)欄目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能實(shí)驗(yàn)室 版權(quán)所有    關(guān)于我們 | 聯(lián)系我們 | 廣告服務(wù) | 公司動(dòng)態(tài) | 免責(zé)聲明 | 隱私條款 | 工作機(jī)會(huì) | 展會(huì)港