目錄
- 一、神經(jīng)網(wǎng)絡(luò)介紹:
- 二、數(shù)據(jù)集
- 三、激活函數(shù)
- 四、正向傳播
- 五、損失函數(shù)
- 六、反向傳播
- 七、總體思路
一、神經(jīng)網(wǎng)絡(luò)介紹:
神經(jīng)網(wǎng)絡(luò)算法參考人的神經(jīng)元原理(軸突、樹(shù)突、神經(jīng)核),在很多神經(jīng)元基礎(chǔ)上構(gòu)建神經(jīng)網(wǎng)絡(luò)模型,每個(gè)神經(jīng)元可看作一個(gè)個(gè)學(xué)習(xí)單元。這些神經(jīng)元采納一定的特征作為輸入,根據(jù)自身的模型得到輸出。
圖1 神經(jīng)網(wǎng)絡(luò)構(gòu)造的例子(符號(hào)說(shuō)明:上標(biāo)[l]表示與第l層;上標(biāo)(i)表示第i個(gè)例子;下標(biāo)i表示矢量第i項(xiàng))
圖2 單層神經(jīng)網(wǎng)絡(luò)示例
神經(jīng)元模型是先計(jì)算一個(gè)線性函數(shù)(z=Wx+b),接著再計(jì)算一個(gè)激活函數(shù)。一般來(lái)說(shuō),神經(jīng)元模型的輸出值是a=g(Wx+b),其中g(shù)是激活函數(shù)(sigmoid,tanh, ReLU, …)。
二、數(shù)據(jù)集
假設(shè)有一個(gè)很大的數(shù)據(jù)庫(kù),里面記錄了很多天氣數(shù)據(jù),例如,氣溫、濕度、氣壓和降雨率。
問(wèn)題陳述:
一組訓(xùn)練數(shù)據(jù)m_train,下雨標(biāo)記為(1),不下雨標(biāo)記為(0)。
一個(gè)測(cè)試數(shù)據(jù)組m_test,標(biāo)記是否下雨。
每一個(gè)天氣數(shù)據(jù)包含x1=氣溫,x2=濕度,x3=氣壓。
機(jī)器學(xué)習(xí)中一個(gè)常見(jiàn)的預(yù)處理步驟是將數(shù)據(jù)集居中并標(biāo)準(zhǔn)化,這意味著從每個(gè)示例中減去整個(gè)numpy數(shù)組的平均值,然后將每個(gè)示例除以整個(gè)numpy數(shù)組的標(biāo)準(zhǔn)偏差。
通用方法(建立部分算法)
使用深度學(xué)習(xí)來(lái)建造模型
1. 定義模型構(gòu)造(例如,數(shù)據(jù)的輸入特征)
2. 初始化參數(shù)并定義超參數(shù)(迭代次數(shù)、在神經(jīng)網(wǎng)絡(luò)中的L層的層數(shù)、隱藏層大小、學(xué)習(xí)率α)
3. 迭代循環(huán)(正向傳播(計(jì)算電流損耗)、計(jì)算成本函數(shù)、反向傳播(計(jì)算電流損耗)、升級(jí)參數(shù)(使用背景參數(shù)和梯度))
4. 使用訓(xùn)練參數(shù)來(lái)預(yù)測(cè)標(biāo)簽(初始化)
更深層次的L-層神經(jīng)網(wǎng)絡(luò)的初始化更為復(fù)雜,因?yàn)橛懈嗟臋?quán)重矩陣和偏置向量。下表展示了不同結(jié)構(gòu)的各種層級(jí)。
表1 L層的權(quán)重矩陣w、偏置向量b和激活函數(shù)z
表2 示例架構(gòu)中的神經(jīng)網(wǎng)絡(luò)權(quán)重矩陣w、偏置向量b和激活函數(shù)z
表2幫助我們?yōu)閳D1中的示例神經(jīng)網(wǎng)絡(luò)架構(gòu)的矩陣準(zhǔn)備了正確的維度。
import numpy as np
import matplotlib.pyplot as plt
nn_architecture = [
{"layer_size": 4,"activation": "none"}, # input layer
{"layer_size": 5,"activation": "relu"},
{"layer_size": 4,"activation": "relu"},
{"layer_size": 3,"activation": "relu"},
{"layer_size": 1,"activation": "sigmoid"}
]
def initialize_parameters(nn_architecture, seed = 3):
np.random.seed(seed)
# python dictionary containingour parameters "W1", "b1", ..., "WL","bL"
parameters = {}
number_of_layers = len(nn_architecture)
for l in range(1,number_of_layers):
parameters['W' + str(l)] =np.random.randn(
nn_architecture[l]["layer_size"],
nn_architecture[l-1]["layer_size"]
) * 0.01
parameters['b' + str(l)] =np.zeros((nn_architecture[l]["layer_size"], 1))
return parameters
代碼段1 參數(shù)初始化
使用小隨機(jī)數(shù)初始化參數(shù)是一種簡(jiǎn)單的方法,但同時(shí)也保證算法的起始值足夠好。
記?。?/p>
- 不同的初始化工具,例如Zero,Random, He or Xavier,都會(huì)導(dǎo)致不同的結(jié)果。
- 隨機(jī)初始化能夠確保不同的隱藏單元可以學(xué)習(xí)不同的東西(初始化所有權(quán)重為零會(huì)導(dǎo)致,所有層次的所有感知機(jī)都將學(xué)習(xí)相同的東西)。
- 不要初始化為太大的值
三、激活函數(shù)
激活函數(shù)的作用是為了增加神經(jīng)網(wǎng)絡(luò)的非線性。下例將使用sigmoid and ReLU。
Sigmoid輸出一個(gè)介于0和1之間的值,這使得它成為二進(jìn)制分類的一個(gè)很好的選擇。如果輸出小于0.5,可以將其分類為0;如果輸出大于0.5,可以將其分類為1。
def sigmoid(Z):
S = 1 / (1 + np.exp(-Z))
return S
def relu(Z):
R = np.maximum(0, Z)
return R
def sigmoid_backward(dA, Z):
S = sigmoid(Z)
dS = S * (1 - S)
return dA * dS
def relu_backward(dA, Z):
dZ = np.array(dA, copy=True)
dZ[Z = 0] = 0
return dZ
代碼段2 Sigmoid和ReLU激活函數(shù),及其衍生物
在代碼段2中,可以看到激活函數(shù)及其派生的矢量化編程實(shí)現(xiàn)。該代碼將用于進(jìn)一步的計(jì)算。
四、正向傳播
在正向傳播中,在層l的正向函數(shù)中,需要知道該層中的激活函數(shù)是哪一種(sigmoid、tanh、ReLU等)。前一層的輸出值為這一層的輸入值,先計(jì)算z,再用選定的激活函數(shù)計(jì)算。
圖3 神經(jīng)網(wǎng)絡(luò)的正向傳播
線性正向模塊(對(duì)所有示例進(jìn)行矢量化)計(jì)算以下方程式:
方程式1 線性正向函數(shù)
def L_model_forward(X, parameters, nn_architecture):
forward_cache = {}
A = X
number_of_layers = len(nn_architecture)
for l in range(1, number_of_layers):
A_prev = A
W = parameters['W' + str(l)]
b = parameters['b' + str(l)]
activation = nn_architecture[l]["activation"]
Z, A = linear_activation_forward(A_prev, W, b, activation)
forward_cache['Z' + str(l)] = Z
forward_cache['A' + str(l)] = A
AL = A
return AL, forward_cache
def linear_activation_forward(A_prev, W, b, activation):
if activation == "sigmoid":
Z = linear_forward(A_prev, W, b)
A = sigmoid(Z)
elif activation == "relu":
Z = linear_forward(A_prev, W, b)
A = relu(Z)
return Z, A
def linear_forward(A, W, b):
Z = np.dot(W, A) + b
return Z
代碼段3 正向傳播模型
使用“cache”(python字典包含為特定層所計(jì)算的a和z值)以在正向傳播至相應(yīng)的反向傳播期間傳遞變量。它包含用于反向傳播計(jì)算導(dǎo)數(shù)的有用值。
五、損失函數(shù)
為了管程學(xué)習(xí)過(guò)程,需要計(jì)算代價(jià)函數(shù)的值。下面的公式用于計(jì)算成本。
方程式2 交叉熵成本
def compute_cost(AL, Y):
m = Y.shape[1]
# Compute loss from AL and y
logprobs = np.multiply(np.log(AL), Y) + np.multiply(1 - Y, np.log(1 - AL))
# cross-entropy cost
cost = - np.sum(logprobs) / m
cost = np.squeeze(cost)
return cost
代碼段4 代價(jià)函數(shù)的計(jì)算
六、反向傳播
反向傳播用于計(jì)算參數(shù)的損失函數(shù)梯度。該算法是由微分學(xué)中已知的“鏈規(guī)則”遞歸使用的。
反向傳播計(jì)算中使用的公式:
方程式3 反向傳播計(jì)算公式
鏈?zhǔn)椒▌t是計(jì)算復(fù)合函數(shù)導(dǎo)數(shù)的公式。復(fù)合函數(shù)就是函數(shù)套函數(shù)。
方程式4 鏈規(guī)則示例
“鏈規(guī)則”在計(jì)算損失時(shí)十分重要(以方程式5為例)。
方程式5 損失函數(shù)(含替換數(shù)據(jù))及其相對(duì)于第一權(quán)重的導(dǎo)數(shù)
神經(jīng)網(wǎng)絡(luò)模型反向傳播的第一步是計(jì)算最后一層損失函數(shù)相對(duì)于z的導(dǎo)數(shù)。方程式6由兩部分組成:方程式2損失函數(shù)的導(dǎo)數(shù)(關(guān)于激活函數(shù))和激活函數(shù)“sigmoid”關(guān)于最后一層Z的導(dǎo)數(shù)。
方程式6 從4層對(duì)z的損失函數(shù)導(dǎo)數(shù)
方程式6的結(jié)果可用于計(jì)算方程式3的導(dǎo)數(shù)。
方程式7 損失函數(shù)相對(duì)于3層的導(dǎo)數(shù)
在進(jìn)一步計(jì)算中,使用了與第三層激活函數(shù)有關(guān)的損失函數(shù)的導(dǎo)數(shù)(方程式7)。
方程式8 第三層的導(dǎo)數(shù)
方程式7的結(jié)果和第三層活化函數(shù)“relu”的導(dǎo)數(shù)用于計(jì)算方程式8的導(dǎo)數(shù)(損失函數(shù)相對(duì)于z的導(dǎo)數(shù))。然后,我們對(duì)方程式3進(jìn)行了計(jì)算。
我們對(duì)方程9和10做了類似的計(jì)算。
方程式9 第二層的導(dǎo)數(shù)
方程式10 第一層的導(dǎo)數(shù)
七、總體思路
從第一層層對(duì)z的損失函數(shù)導(dǎo)數(shù)有助于計(jì)算(L-1)層(上一層)對(duì)損失函數(shù)的導(dǎo)數(shù)。結(jié)果將用于計(jì)算激活函數(shù)的導(dǎo)數(shù)。
圖4 神經(jīng)網(wǎng)絡(luò)的反向傳播
def L_model_backward(AL, Y, parameters, forward_cache, nn_architecture):
grads = {}
number_of_layers =len(nn_architecture)
m = AL.shape[1]
Y = Y.reshape(AL.shape) # afterthis line, Y is the same shape as AL
# Initializing thebackpropagation
dAL = - (np.divide(Y, AL) -np.divide(1 - Y, 1 - AL))
dA_prev = dAL
for l in reversed(range(1,number_of_layers)):
dA_curr = dA_prev
activation =nn_architecture[l]["activation"]
W_curr = parameters['W' +str(l)]
Z_curr = forward_cache['Z' +str(l)]
A_prev = forward_cache['A' +str(l-1)]
dA_prev, dW_curr, db_curr =linear_activation_backward(dA_curr, Z_curr, A_prev, W_curr, activation)
grads["dW" +str(l)] = dW_curr
grads["db" +str(l)] = db_curr
return grads
def linear_activation_backward(dA, Z, A_prev, W, activation):
if activation =="relu":
dZ = relu_backward(dA, Z)
dA_prev, dW, db =linear_backward(dZ, A_prev, W)
elif activation =="sigmoid":
dZ = sigmoid_backward(dA, Z)
dA_prev, dW, db =linear_backward(dZ, A_prev, W)
return dA_prev, dW, db
def linear_backward(dZ, A_prev, W):
m = A_prev.shape[1]
dW = np.dot(dZ, A_prev.T) / m
db = np.sum(dZ, axis=1,keepdims=True) / m
dA_prev = np.dot(W.T, dZ)
return dA_prev, dW, db
代碼段5 反向傳播模塊
更新參數(shù)
該函數(shù)的目標(biāo)是通過(guò)梯度優(yōu)化來(lái)更新模型的參數(shù)。
def update_parameters(parameters, grads, learning_rate):
L = len(parameters)
for l in range(1, L):
parameters["W" +str(l)] = parameters["W" + str(l)] - learning_rate *grads["dW" + str(l)]
parameters["b" +str(l)] = parameters["b" + str(l)] - learning_rate *grads["db" + str(l)]
return parameters
全模型
神經(jīng)網(wǎng)絡(luò)模型的完整實(shí)現(xiàn)包括在片段中提供的方法。
def L_layer_model(X, Y, nn_architecture, learning_rate = 0.0075,num_iterations = 3000, print_cost=False):
np.random.seed(1)
# keep track of cost
costs = []
# Parameters initialization.
parameters =initialize_parameters(nn_architecture)
# Loop (gradient descent)
for i in range(0,num_iterations):
# Forward propagation:[LINEAR -> RELU]*(L-1) -> LINEAR -> SIGMOID.
AL, forward_cache =L_model_forward(X, parameters, nn_architecture)
# Compute cost.
cost = compute_cost(AL, Y)
# Backward propagation.
grads = L_model_backward(AL,Y, parameters, forward_cache, nn_architecture)
# Update parameters.
parameters =update_parameters(parameters, grads, learning_rate)
# Print the cost every 100training example
if print_cost and i % 100 ==0:
print("Cost afteriteration %i: %f" %(i, cost))
costs.append(cost)
# plot the cost
plt.plot(np.squeeze(costs))
plt.ylabel('cost')
plt.xlabel('iterations (pertens)')
plt.title("Learning rate=" + str(learning_rate))
plt.show()
return parameters
代碼段7 整個(gè)神經(jīng)網(wǎng)絡(luò)模型
只需要將已知的權(quán)重和系列測(cè)試數(shù)據(jù),應(yīng)用于正向傳播模型,就能預(yù)測(cè)結(jié)果。
可以修改snippet1中的nn_架構(gòu),以構(gòu)建具有不同層數(shù)和隱藏層大小的神經(jīng)網(wǎng)絡(luò)。此外,準(zhǔn)備正確實(shí)現(xiàn)激活函數(shù)及其派生函數(shù)(代碼段2)。所實(shí)現(xiàn)的函數(shù)可用于修改代碼段3中的線性正向激活方法和代碼段5中的線性反向激活方法。
進(jìn)一步改進(jìn)
如果訓(xùn)練數(shù)據(jù)集不夠大,則可能面臨“過(guò)度擬合”問(wèn)題。這意味著所學(xué)的網(wǎng)絡(luò)不會(huì)概括為它從未見(jiàn)過(guò)的新例子??梢允褂谜齽t化方法,如L2規(guī)范化(它包括適當(dāng)?shù)匦薷某杀竞瘮?shù))或退出(它在每次迭代中隨機(jī)關(guān)閉一些感知機(jī))。
我們使用梯度下降來(lái)更新參數(shù)和最小化成本。你可以學(xué)習(xí)更多高級(jí)優(yōu)化方法,這些方法可以加快學(xué)習(xí)速度,甚至可以為成本函數(shù)提供更好的最終價(jià)值,例如:
- 小批量梯度下降
- 動(dòng)力
- Adam優(yōu)化器
參考:http://www.uml.org.cn/ai/201911251.asp
到此這篇關(guān)于Python建立任意層數(shù)的深度神經(jīng)網(wǎng)絡(luò)的文章就介紹到這了,更多相關(guān)Python神經(jīng)網(wǎng)絡(luò)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- numpy創(chuàng)建神經(jīng)網(wǎng)絡(luò)框架
- python神經(jīng)網(wǎng)絡(luò)編程之手寫數(shù)字識(shí)別
- python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)
- pytorch動(dòng)態(tài)神經(jīng)網(wǎng)絡(luò)(擬合)實(shí)現(xiàn)
- Python如何使用神經(jīng)網(wǎng)絡(luò)進(jìn)行簡(jiǎn)單文本分類
- pytorch之深度神經(jīng)網(wǎng)絡(luò)概念全面整理