學(xué)習(xí)筆記 — 神經(jīng)網(wǎng)絡(luò)和深度學(xué)習(xí)(ng)_第三周

更好的閱讀體驗(yàn),請(qǐng)點(diǎn)擊這里


內(nèi)容概要:

  • 四種常用的激活函數(shù)、導(dǎo)數(shù),以及為什么需要非線性激活函數(shù)

  • 神經(jīng)元模型

  • 參數(shù)隨機(jī)初始化,為什么不能將所有參數(shù)初始化為0

  • 單隱層神經(jīng)網(wǎng)絡(luò)簡(jiǎn)介

  • 分步驟實(shí)現(xiàn)單隱層神經(jīng)網(wǎng)絡(luò)(forward propagation & back propagation)

  • TensorFlow 中實(shí)現(xiàn)單隱層神經(jīng)網(wǎng)絡(luò)

0 - 符號(hào)說(shuō)明


1 - 激活函數(shù)


激活函數(shù)是神經(jīng)網(wǎng)絡(luò)中非常關(guān)鍵的一個(gè)組成部分,常用的激活函數(shù)都是非線性的,如sigmoid、tanh、ReLU、Leaky_ReLU等。四種常用激活函數(shù)的圖像如下:

為什么要使用非線性激活函數(shù)?

如果不使用非線性激活函數(shù),那個(gè)神經(jīng)網(wǎng)絡(luò)僅僅是將輸入線性組合后輸出,而兩個(gè)線性方程的組合依然是線性方程。這樣的話,神經(jīng)網(wǎng)絡(luò)就沒(méi)法逼近復(fù)雜的非線性函數(shù)。當(dāng)然,在一些比較特殊的問(wèn)題中,如回歸等,也會(huì)使用線性激活函數(shù)。

1.1 - sigmoid & tanh


sigmoid 常用于二分類(binary classification)網(wǎng)絡(luò)的輸出層;在隱藏層中,通常使用 tanh,而不是sigmoid。這主要是因?yàn)閠anh的輸出為(-1,1),均值為0,所以下一層的輸入是centered;而sigmoid的均值是0.5。tanh其實(shí)就是sigmoid在y軸方向向下移動(dòng)1個(gè)單位的版本。

1.2 - ReLU & Leaky_ReLU


ReLU (Rectified Linear Unit)激活函數(shù)在深度學(xué)習(xí)中比sigmoid和tanh更常用。
當(dāng)激活函數(shù)的輸入z的值很大或很小的時(shí)候,sigmoid和tanh的梯度非常小,這會(huì)大大減緩梯度下降的學(xué)習(xí)速度。所以與sigmoid和tanh相比,ReLU的訓(xùn)練速度要快很多。Leaky ReLU比ReLU要表現(xiàn)得稍微好一丟丟但是實(shí)踐中大家往往都用ReLU。

2 - 神經(jīng)元


典型的神經(jīng)元如下圖所示:

神經(jīng)元中包含兩個(gè)計(jì)算過(guò)程:

step1. 由線性方程計(jì)算輸入向量 $x$ 的線性回歸值,即 $z=w^Tx+b$ ;

step2. 將線性回歸值輸入激活函數(shù) $\alpha=\sigma(z)$,得到結(jié)果。

可以發(fā)現(xiàn),神經(jīng)元長(zhǎng)得和LR一樣。事實(shí)上,當(dāng)神經(jīng)元采用sigmoid函數(shù)作為激活函數(shù)時(shí),就是LR模型,因此,LR是神經(jīng)元的一個(gè)特例。

3 - 參數(shù)隨機(jī)初始化


和LR模型一樣,每一個(gè)神經(jīng)元中都有兩組參數(shù),$w$ 和 $b$。

對(duì)于Logistic Regression,將參數(shù)初始化為0沒(méi)有問(wèn)題;但是,在神經(jīng)網(wǎng)絡(luò)中,如果將所有參數(shù)初始化為0,再使用梯度下降算法訓(xùn)練,就會(huì)完全無(wú)效。因?yàn)?,所有參?shù)初始化為0之后,單個(gè)隱層中的所有神經(jīng)元每一次迭代的計(jì)算內(nèi)容就完全一樣了,參數(shù)更新也一樣,也就是說(shuō)參數(shù)矩陣的每一行的元素都是一樣的,這樣就無(wú)法達(dá)到訓(xùn)練的目的。

隨機(jī)初始化參數(shù)可以解決以上問(wèn)題。ng給出的一個(gè)初始化方法是使用 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ò)簡(jiǎn)介


將若干個(gè)神經(jīng)元分層組合,就是神經(jīng)網(wǎng)絡(luò)。典型的單隱層神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)如下圖:

其中,紅色覆蓋的是【輸入層】,黃色覆蓋的是【隱含層】,綠色覆蓋的是【輸出層】。

上圖中,隱層中有4個(gè)神經(jīng)元,神經(jīng)元數(shù)量可以根據(jù)任務(wù)的需求調(diào)整。

由于輸入層沒(méi)有任何計(jì)算,僅僅是數(shù)據(jù)的輸入,在計(jì)算神經(jīng)網(wǎng)絡(luò)的層數(shù)時(shí),通常不考慮輸入層。因此,單隱層神經(jīng)網(wǎng)絡(luò)的層數(shù)是2。

5 - 單隱層神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)過(guò)程


單隱層神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)主要有以下幾個(gè)步驟:

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. 計(jì)算損失(loss)
3. 執(zhí)行后向傳播(backward propagation),得到所有參數(shù)的梯度(gradients)
4. 使用梯度下降法(gradient descent)更新參數(shù)

step 4(可選). 調(diào)參:hidden layer size、learning rate等

Note: 參數(shù)更新方法可以視情況調(diào)整,在很多問(wèn)題中,Adam的表現(xiàn)會(huì)優(yōu)于其他方法。

5.1 - 定義網(wǎng)絡(luò)結(jié)構(gòu)


網(wǎng)絡(luò)結(jié)構(gòu)的定義其實(shí)就是確定神經(jīng)網(wǎng)絡(luò)中各層的units數(shù)量,通常設(shè)定輸入層大小為單個(gè)樣本的特征數(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ù)初始化為0!?。?/strong>

5.3 - 循環(huán)迭代訓(xùn)練,更新參數(shù)


循環(huán)迭代過(guò)程是神經(jīng)網(wǎng)絡(luò)中最核心的部分,這一步包含四項(xiàng)內(nèi)容:前向傳播、計(jì)算損失、后向傳播、參數(shù)更新。

5.3.1 - 執(zhí)行前向傳播(forward propagation)


前向傳播分為兩個(gè)步驟:linear forward和activation forward。

對(duì)于單個(gè)樣本 $x^{(i)}$, 其前向傳播過(guò)程的相關(guān)計(jì)算如下:

對(duì)于全部樣本的計(jì)算,在Python中實(shí)現(xiàn)時(shí)采用向量化的計(jì)算方法,即將所有輸入樣本堆疊成一個(gè)輸入矩陣,然后再分別執(zhí)行每一層的 linear forward 和 activation forward。

Note:每一層 activation forward 過(guò)程中使用的激活函數(shù)可以不一樣,通常隱含層使用tanh,輸出層使用sigmoid。

5.3.2 - 計(jì)算損失(loss)


得到所有樣本的預(yù)測(cè)值后,使用以下公式計(jì)算損失Loss(又稱“訓(xùn)練成本 cost”):

5.3.3 - 執(zhí)行后向傳播(backward propagation),得到所有參數(shù)的梯度(gradients)


后向傳播過(guò)程與前向傳播過(guò)程的計(jì)算路線相反,先計(jì)算輸出層(第2層)相關(guān)參數(shù)的梯度,然后計(jì)算隱含層(第1層)相關(guān)參數(shù)的梯度,其計(jì)算公式如下圖:

圖中,棕色色塊覆蓋的部分表示單個(gè)樣本的后向傳播計(jì)算過(guò)程;綠色色塊覆蓋的是所有樣本的堆疊在一起之后的后向傳播向量化計(jì)算過(guò)程,也就是python實(shí)現(xiàn)后向傳播過(guò)程所參照的計(jì)算公式。

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è)定對(duì)梯度下降法有著顯著的影響,下面有兩張動(dòng)圖(Adam Harley制作的)可以展示學(xué)習(xí)率設(shè)定好壞對(duì)梯度下降過(guò)程的影響:

好的學(xué)習(xí)率(learning rate)大小,隨著訓(xùn)練的進(jìn)行,逐步逼近函數(shù)最小值:

差的學(xué)習(xí)率(learning rate)大小,訓(xùn)練開始不久,就在最小值附近跳動(dòng),難以收斂:

6 - TensorFlow中單隱層神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)


使用ng在本周編程作業(yè)中提供的數(shù)據(jù)生成方法生成數(shù)據(jù),在TensorFlow中實(shí)現(xiàn)單隱層神經(jīng)網(wǎng)絡(luò)對(duì)數(shù)據(jù)進(jìn)行訓(xùn)練,實(shí)現(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('請(qǐng)復(fù)制以下代碼到cmd,執(zhí)行,啟動(dòng)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
請(qǐng)復(fù)制以下代碼到cmd,執(zhí)行,啟動(dòng)tensorboard: tensorboard --logdir=C:\Users\Mike\Documents\Blog\notes_deeplearning.ai\log

參考資料


Deep Learning - Adaptive Computation and Machine Learning series by Ian Goodfellow (Author), Yoshua Bengio (Author), Aaron Courville (Author)

吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (下)

https://en.wikipedia.org/wiki/Sigmoid_function

https://en.wikipedia.org/wiki/Hyperbolic_function

https://en.wikipedia.org/wiki/Rectifier_(neural_networks)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容