白話RNN系列(一)

RNN,循環神經網絡,全稱Recurrent Neural Network。

本文,從RNN的基本原理講起,會探討RNN的前向傳播和反向傳播,並通過一些淺顯易懂的小例子,展示RNN這個東東的神奇之處,盡最大可能以通俗易懂的方式,讓看到本文的童鞋都能夠掌握RNN。

1:RNN的基本原理

即便是RNN,也依舊脫離不了神經網絡的基本架構,換句話說,我們看RNN的時候,一定要記住一句,它不過是高級一些的神經網絡而已,其深層也不過是神經網絡而已,沒什麼可怕的。

我們先拿個神經網絡來做例子:

è¿éåå¾çæè¿°

上圖展示的是最基礎的神經網絡,即全連接神經網絡,除了最左側的輸入層和最右側的輸出層,其他均爲隱藏層,其之所以叫做全連接神經網絡,從圖中我們也可以看出,輸入元素會與隱藏層的每一個節點產生連接,同時,隱層的每個節點又會與下一層的所有節點產生連接,因此,叫做全連接神經網絡。

而我們神經網絡最終的目的是什麼?求取的實際上是一個權重矩陣。

舉個例子來說,如上圖,我們可以看到輸入層有五個節點,可以假設一個輸入有五個特徵的向量,如X=(x1,x2,x3,x4,x5)。

而隱藏層只有四個節點,這時候,我們需要一個維度爲5*4的權重矩陣W,將其轉化爲4個特徵的向量,而這個權重矩陣,就是我們最終需要的東西。

有些童鞋會提到偏置,我們這裏不予考慮,或者可以將其簡化入權重矩陣內。

那是不是神經網絡就是這一層層的權重矩陣相乘,最後得到一個我們需要維度的輸出呢?比如說最終我們需要做一個softmax的多分類,比如常見的手寫字體識別,是不是最後輸出一個十個維度的的向量,交給softmax就可以了呢?

顯然不是。

這種方式下,可以看出,就成了完全的線性變換,如輸入層與第一隱層之間的權重矩陣爲W1,第一隱層與第二隱層之間的權重矩陣爲W2,循環往復,最終的輸出可能爲:

Y = W1 * W2 * ···Wn * X

前面的多個矩陣的乘積,與一個單獨的矩陣沒什麼本質區別,換句話說,我們多個隱層的存在是沒有意義的,我們完全可以用一個簡單的線性變換來完成我們的工作。

討論到此結束,大家都去琢磨線性變換就可以了。

但是,神經網絡絕不是那麼簡單的,其在線性變換的同時,於隱藏層的神經元內,做了非線性變換,線性變換與非線性變換的結合,最終完成了很多不可思議的任務。

必須注意,直到這裏,我們談論的也只是全連接神經網絡,而其妙處,則是在隱藏層神經元上,我們看下隱藏層神經元的結構:

這是簡單的M-P神經元模型,圖片來自於周志華老師的機器學習一書;這裏,我們單獨看隱藏層的一個節點,其他節點的處理雷同。

上面所說的輸入層與第一隱層之間的權重矩陣,其維度爲5*4,原因在於,我們輸入的特徵是5維的,而隱藏層神經元的個數爲4層;換算到這裏,就相當於n=5,我們用一個隱藏層節點來分析的話,會發現對於這個節點來說,我們輸入向量實際上是左乘了一個5維的向量,得到了一個實數。

向量乘法很簡單: (1 * 5) * (5 * 1),得到一個實數;前面的1 * 5 是輸入層與第一個神經元之間的權重關係,那麼,如果隱藏層神經元爲4個的話,我們把四個權重向量堆疊成權重矩陣,自然而然得到了一個 4 * 5 的權重矩陣;而這個權重矩陣與輸入向量乘積,得到的則是一個 4 * 1的向量,正好對應於隱藏層神經元,每個節點的輸出。

我們在吳恩達老師的課程中會看到,其寫的是權重矩陣的轉置,即這裏的4 * 5 是權重矩陣的轉置,實際上的權重矩陣應該是5 * 4的矩陣。

但是,這對於問題的理解並無影響,只是寫起來更加方便,我們可以輕鬆地通過輸入層的特徵數目 * 隱藏層神經元的數目,得到第一個權重矩陣的維度。

在代碼中的實現形如(手寫字體的部分代碼):

x = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder(tf.float32)
# 自己定義一個學習率
lr = tf.Variable(0.001, dtype=tf.float32)

# 設計第一層神經網絡 : 784 * 2000
# 因爲輸入樣本是784維向量,而輸出時2000個神經元
W1 = tf.Variable(tf.truncated_normal([784, 500], stddev=0.1))
b1 = tf.Variable(tf.zeros([500]) + 0.1)
L1 = tf.nn.tanh(tf.matmul(x, W1) + b1)
L1_drop = tf.nn.dropout(L1, keep_prob)

手寫字體識別的輸入向量,是1 * 784維的,即具有784個特徵的向量,而我們的權重矩陣,則是784 * 500維的,這種寫法更好理解一些。

插了一些關於權重矩陣的閒話,我們繼續看隱藏層神經元中隱藏的非線性變換。

常見的有sigmoid,tanh,relu等,我們通過矩陣與向量相乘得到的輸入,在每個隱藏層節點內都會經過非線性變換,才能作爲下一層神經元節點的輸入。

神經網絡就是這麼簡單,沒什麼神祕的地方,說起來加入了那麼多東西,其實質也就是我們平日裏見到的線性和非線性變換而已。

說了這麼多,我們認真看下全連接神經網絡到底存在什麼缺點,才催生出後續的卷積神經網絡和循環神經網絡。

1:全連接,導致權重矩陣過大,同時特徵會被割裂。

簡單說,如果我們輸入的是非常大的圖片,比如1920 * 1920這種高清圖片,光是輸入特徵的維度就高達百萬級別,再加上隱藏層的的維度,比如說隱藏層設置128個節點,那第一個權重矩陣的維度就高達千萬個參數,別忘了,我們還有偏置......

這個代價很高,如果全連接神經網絡的層數再多一些,那計算代價,高的可怕,所以我們平常用到的全連接神經網絡速度慢,就可以理解了。

特徵割裂,是我對於不考慮特徵之間相互關係的一個稱呼,能看得出來,全連接建立在一個假設的基礎上,即各個特徵之間完全不存在相關關係,因此對於每個隱藏層節點而言,都有自己的權重,在一些情況下,這是合理的,但很遺憾,現在大多數數據都存在相關性,如果完全不考慮其相關關係,不僅權重矩陣過大,計算代價高,往往還不會得到理想的效果。

所以權值共享的概念被提了出來,在卷積神經網絡和循環神經網絡裏,我們都可以看到其蹤跡。

2:隱層內部的神經元互相之間,其實是沒有任何連接的。

很簡單,上面的圖都可以看到這點,每個神經元節點的輸出,只會不斷向後傳遞,同一層神經元之間,不存在任何的相互關聯。

乍一看,沒啥問題;但隨着我們處理的任務越來越多,尤其是NLP的高速發展,神經網絡在NLP方面的缺陷就暴露出來,爲什麼?

每個人說一句話,都會摻雜進自己先前的背景知識,即記憶,一句話的前言和後語,通常都是有聯繫的,可惜的是,當前的神經網絡解決這類問題效果不是很好,因爲其不存在記憶。

在這種情況下,有人提出了循環神經網絡,其實質在於,在隱藏層的神經元節點之間加入了聯繫,產生的效果就是,第一個神經元節點的輸出,可以被第二個神經元節點獲取到;同理,最後一個隱層神經元節點會接收到幾乎上面所有神經元節點的輸出(只不過最近的神經元肯定對其輸入影響最大而已)。

通俗來說,就是RNN在分析每一句話的時候,會盡最大可能考慮前面用戶輸入的每個字,以期望達到一個比較好的效果,這是非常好的設想,也的確達到了不錯的效果。

而這個RNN,就是我們接下來需要探討的重點;其內部不僅有循環輸入,同樣也加入了權值共享,對於我們深入對其他神經網絡的理解,很有幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章