更好的閱讀體驗烁登,請點(diǎn)擊這里
內(nèi)容概要:
四種常用的激活函數(shù)、導(dǎo)數(shù)蔚舀,以及為什么需要非線性激活函數(shù)
神經(jīng)元模型
參數(shù)隨機(jī)初始化饵沧,為什么不能將所有參數(shù)初始化為0
單隱層神經(jīng)網(wǎng)絡(luò)簡介
分步驟實現(xiàn)單隱層神經(jīng)網(wǎng)絡(luò)(forward propagation & back propagation)
TensorFlow 中實現(xiàn)單隱層神經(jīng)網(wǎng)絡(luò)
0 - 符號說明
1 - 激活函數(shù)
激活函數(shù)是神經(jīng)網(wǎng)絡(luò)中非常關(guān)鍵的一個組成部分锨络,常用的激活函數(shù)都是非線性的,如sigmoid狼牺、tanh羡儿、ReLU、Leaky_ReLU等是钥。四種常用激活函數(shù)的圖像如下:
為什么要使用非線性激活函數(shù)掠归?
如果不使用非線性激活函數(shù),那個神經(jīng)網(wǎng)絡(luò)僅僅是將輸入線性組合后輸出悄泥,而兩個線性方程的組合依然是線性方程虏冻。這樣的話,神經(jīng)網(wǎng)絡(luò)就沒法逼近復(fù)雜的非線性函數(shù)码泞。當(dāng)然,在一些比較特殊的問題中狼犯,如回歸等余寥,也會使用線性激活函數(shù)。
1.1 - sigmoid & tanh
sigmoid 常用于二分類(binary classification)網(wǎng)絡(luò)的輸出層悯森;在隱藏層中宋舷,通常使用 tanh,而不是sigmoid瓢姻。這主要是因為tanh的輸出為(-1祝蝠,1),均值為0幻碱,所以下一層的輸入是centered绎狭;而sigmoid的均值是0.5。tanh其實就是sigmoid在y軸方向向下移動1個單位的版本褥傍。
1.2 - ReLU & Leaky_ReLU
ReLU (Rectified Linear Unit)激活函數(shù)在深度學(xué)習(xí)中比sigmoid和tanh更常用儡嘶。
當(dāng)激活函數(shù)的輸入z的值很大或很小的時候,sigmoid和tanh的梯度非常小恍风,這會大大減緩梯度下降的學(xué)習(xí)速度蹦狂。所以與sigmoid和tanh相比,ReLU的訓(xùn)練速度要快很多朋贬。Leaky ReLU比ReLU要表現(xiàn)得稍微好一丟丟但是實踐中大家往往都用ReLU凯楔。
2 - 神經(jīng)元
典型的神經(jīng)元如下圖所示:
神經(jīng)元中包含兩個計算過程:
step1. 由線性方程計算輸入向量 $x$ 的線性回歸值,即 $z=w^Tx+b$ ;
step2. 將線性回歸值輸入激活函數(shù) $\alpha=\sigma(z)$锦募,得到結(jié)果摆屯。
可以發(fā)現(xiàn),神經(jīng)元長得和LR一樣糠亩。事實上鸥拧,當(dāng)神經(jīng)元采用sigmoid函數(shù)作為激活函數(shù)時党远,就是LR模型,因此富弦,LR是神經(jīng)元的一個特例沟娱。
3 - 參數(shù)隨機(jī)初始化
和LR模型一樣,每一個神經(jīng)元中都有兩組參數(shù)腕柜,$w$ 和 $b$济似。
對于Logistic Regression,將參數(shù)初始化為0沒有問題盏缤;但是砰蠢,在神經(jīng)網(wǎng)絡(luò)中,如果將所有參數(shù)初始化為0唉铜,再使用梯度下降算法訓(xùn)練台舱,就會完全無效。因為潭流,所有參數(shù)初始化為0之后竞惋,單個隱層中的所有神經(jīng)元每一次迭代的計算內(nèi)容就完全一樣了,參數(shù)更新也一樣灰嫉,也就是說參數(shù)矩陣的每一行的元素都是一樣的拆宛,這樣就無法達(dá)到訓(xùn)練的目的。
隨機(jī)初始化參數(shù)可以解決以上問題讼撒。ng給出的一個初始化方法是使用 np.random.randn(n_h, n_x)*0.01 ,即:使用標(biāo)準(zhǔn)正態(tài)分布(又稱“高斯分布”)生成均值為0浑厚,方差為1的隨機(jī)數(shù),然后乘以0.01根盒。當(dāng) $w$ 初始化為均值為0.01的正態(tài)分布隨機(jī)數(shù)之后钳幅,參數(shù) $b$ 初始化為0也是可以的。
4 - 單隱層神經(jīng)網(wǎng)絡(luò)簡介
將若干個神經(jīng)元分層組合炎滞,就是神經(jīng)網(wǎng)絡(luò)贡这。典型的單隱層神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)如下圖:
其中,紅色覆蓋的是【輸入層】厂榛,黃色覆蓋的是【隱含層】盖矫,綠色覆蓋的是【輸出層】。
上圖中击奶,隱層中有4個神經(jīng)元辈双,神經(jīng)元數(shù)量可以根據(jù)任務(wù)的需求調(diào)整。
由于輸入層沒有任何計算柜砾,僅僅是數(shù)據(jù)的輸入湃望,在計算神經(jīng)網(wǎng)絡(luò)的層數(shù)時,通常不考慮輸入層。因此证芭,單隱層神經(jīng)網(wǎng)絡(luò)的層數(shù)是2瞳浦。
5 - 單隱層神經(jīng)網(wǎng)絡(luò)的實現(xiàn)過程
單隱層神經(jīng)網(wǎng)絡(luò)的實現(xiàn)主要有以下幾個步驟:
step 1. 定義網(wǎng)絡(luò)結(jié)構(gòu),即:確定輸入層废士、隱含層和輸出層的units數(shù)量
step 2. 隨機(jī)初始化網(wǎng)絡(luò)參數(shù)
step 3. 循環(huán)迭代訓(xùn)練叫潦,更新參數(shù)
1. 執(zhí)行前向傳播(forward propagation)
2. 計算損失(loss)
3. 執(zhí)行后向傳播(backward propagation),得到所有參數(shù)的梯度(gradients)
4. 使用梯度下降法(gradient descent)更新參數(shù)
step 4(可選). 調(diào)參:hidden layer size官硝、learning rate等
Note: 參數(shù)更新方法可以視情況調(diào)整矗蕊,在很多問題中,Adam的表現(xiàn)會優(yōu)于其他方法氢架。
5.1 - 定義網(wǎng)絡(luò)結(jié)構(gòu)
網(wǎng)絡(luò)結(jié)構(gòu)的定義其實就是確定神經(jīng)網(wǎng)絡(luò)中各層的units數(shù)量傻咖,通常設(shè)定輸入層大小為單個樣本的特征數(shù)量,隱含層大小為4-10之間岖研,輸出層大小為標(biāo)簽數(shù)量卿操。
5.2 - 隨機(jī)初始化參數(shù)
這一步主要是將 連接輸入層與隱含層的 $W_1$ 和 $b_1$ 以及 連接隱含層與輸出層的 $W_2$ 和 $b_2$ 隨機(jī)初始化。通常使用標(biāo)準(zhǔn)正態(tài)分布進(jìn)行隨機(jī)初始化孙援。在后面的課程中害淤,ng還介紹了一些更為有效的參數(shù)隨機(jī)初始化方法。
切記:不能將所有參數(shù)初始化為0T吣ァs菁摇洼裤!
5.3 - 循環(huán)迭代訓(xùn)練邻辉,更新參數(shù)
循環(huán)迭代過程是神經(jīng)網(wǎng)絡(luò)中最核心的部分钞瀑,這一步包含四項內(nèi)容:前向傳播银舱、計算損失、后向傳播而柑、參數(shù)更新移国。
5.3.1 - 執(zhí)行前向傳播(forward propagation)
前向傳播分為兩個步驟:linear forward和activation forward吱瘩。
對于單個樣本 $x^{(i)}$, 其前向傳播過程的相關(guān)計算如下:
對于全部樣本的計算迹缀,在Python中實現(xiàn)時采用向量化的計算方法使碾,即將所有輸入樣本堆疊成一個輸入矩陣,然后再分別執(zhí)行每一層的 linear forward 和 activation forward祝懂。
Note:每一層 activation forward 過程中使用的激活函數(shù)可以不一樣票摇,通常隱含層使用tanh,輸出層使用sigmoid砚蓬。
5.3.2 - 計算損失(loss)
得到所有樣本的預(yù)測值后矢门,使用以下公式計算損失Loss(又稱“訓(xùn)練成本 cost”):
5.3.3 - 執(zhí)行后向傳播(backward propagation),得到所有參數(shù)的梯度(gradients)
后向傳播過程與前向傳播過程的計算路線相反,先計算輸出層(第2層)相關(guān)參數(shù)的梯度祟剔,然后計算隱含層(第1層)相關(guān)參數(shù)的梯度隔躲,其計算公式如下圖:
圖中,棕色色塊覆蓋的部分表示單個樣本的后向傳播計算過程物延;綠色色塊覆蓋的是所有樣本的堆疊在一起之后的后向傳播向量化計算過程,也就是python實現(xiàn)后向傳播過程所參照的計算公式教届。
5.3.4 - 使用梯度下降法(gradient descent)更新參數(shù)
gradient descent參數(shù)更新規(guī)則:
$$ \theta = \theta - \alpha \frac{\partial J }{ \partial \theta }$$
其中:$\alpha$ 是學(xué)習(xí)率(learning rate);$\theta$ 是需要更新的參數(shù)
學(xué)習(xí)率(learning rate)大小的設(shè)定對梯度下降法有著顯著的影響,下面有兩張動圖(Adam Harley制作的)可以展示學(xué)習(xí)率設(shè)定好壞對梯度下降過程的影響:
好的學(xué)習(xí)率(learning rate)大小榨为,隨著訓(xùn)練的進(jìn)行随闺,逐步逼近函數(shù)最小值:
差的學(xué)習(xí)率(learning rate)大小,訓(xùn)練開始不久蔓腐,就在最小值附近跳動矩乐,難以收斂:
6 - TensorFlow中單隱層神經(jīng)網(wǎng)絡(luò)的實現(xiàn)
使用ng在本周編程作業(yè)中提供的數(shù)據(jù)生成方法生成數(shù)據(jù),在TensorFlow中實現(xiàn)單隱層神經(jīng)網(wǎng)絡(luò)對數(shù)據(jù)進(jìn)行訓(xùn)練回论,實現(xiàn)代碼如下:
# planar數(shù)據(jù)集生成
import numpy as np
def load_planar_dataset():
np.random.seed(1)
m = 400 # number of examples
N = int(m/2) # number of points per class
D = 2 # dimensionality
X = np.zeros((m,D), dtype='float32') # data matrix where each row is a single example
Y = np.zeros((m,1), dtype='uint8') # labels vector (0 for red, 1 for blue)
a = 4 # maximum ray of the flower
for j in range(2):
ix = range(N*j,N*(j+1))
t = np.linspace(j*3.12,(j+1)*3.12,N) + np.random.randn(N)*0.2 # theta
r = a*np.sin(4*t) + np.random.randn(N)*0.2 # radius
X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
Y[ix] = j
X = X.T
Y = Y.T
return X, Y
import tensorflow as tf
# 加載數(shù)據(jù)
X, Y = load_planar_dataset()
# 定義神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
n_x, n_h, n_y = X.shape[0], 4, Y.shape[0]
m = X.shape[1]
# 參數(shù)初始化
W1 = tf.Variable(tf.random_normal([n_h, n_x], stddev=1, seed=1))
b1 = tf.Variable(tf.zeros([n_h, 1]))
W2 = tf.Variable(tf.random_normal([n_y, n_h], stddev=1, seed=1))
b2 = tf.Variable(tf.zeros([n_y, 1]))
# 數(shù)據(jù)輸入
x = tf.placeholder(tf.float32, shape=(n_x, None), name='x-input')
y_ = tf.placeholder(tf.float32, shape=(n_y, None), name='y-input')
# 前向傳播
z1 = tf.matmul(W1, x) + b1
a1 = tf.nn.tanh(z1)
z2 = tf.matmul(W2, a1) + b2
a2 = tf.nn.sigmoid(z2)
# 成本函數(shù) & 訓(xùn)練圖
cost = - tf.reduce_sum(tf.add(tf.multiply(y_ , tf.log(a2)), tf.multiply(1-y_ ,tf.log(1-a2)))) / m
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(cost) # 0.1 為 learning_rate
# train_step = tf.train.AdamOptimizer(0.001).minimize(cost)
# 創(chuàng)建 Session散罕,運(yùn)行
with tf.Session() as sess:
# 全局參數(shù)初始化
init_op = tf.global_variables_initializer()
sess.run(init_op)
# 訓(xùn)練模型
num_iterations = 10000
for i in range(num_iterations):
sess.run(train_step, feed_dict={x: X, y_: Y})
if i % 1000 == 0:
total_cost = sess.run(cost, feed_dict={x: X, y_: Y})
print ("Cost after iteration %i: %f" %(i, total_cost))
# 啟用TensorBoard
import os
if not os.path.exists('log'):
os.mkdir('log')
logdir = os.path.join(os.getcwd(), 'log') # 將日志寫到當(dāng)前工作目錄下的log文件夾
print('請復(fù)制以下代碼到cmd,執(zhí)行傀蓉,啟動tensorboard:\n', 'tensorboard --logdir=' + logdir)
writer = tf.summary.FileWriter(logdir, tf.get_default_graph())
writer.close()
Cost after iteration 0: 0.714734
Cost after iteration 1000: 0.336571
Cost after iteration 2000: 0.318074
Cost after iteration 3000: 0.309604
Cost after iteration 4000: 0.304108
Cost after iteration 5000: 0.299986
Cost after iteration 6000: 0.296653
Cost after iteration 7000: 0.293828
Cost after iteration 8000: 0.291358
Cost after iteration 9000: 0.289151
請復(fù)制以下代碼到cmd欧漱,執(zhí)行,啟動tensorboard: tensorboard --logdir=C:\Users\Mike\Documents\Blog\notes_deeplearning.ai\log
參考資料
吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (下)
https://en.wikipedia.org/wiki/Sigmoid_function