假設我們當前要做一個人工智慧客服系統,那該系統就需要對使用者輸入的話語進行辨認,例如使用者輸入:
I want to arrive Taipei on November 2nd
那麼該系統就能夠辨認出來Taipei是目的地,而後面是時間。那麼我們可以用一個簡單的前向網路來實現這個事情,輸出為這個單詞屬於哪個含義的概率。但這會存在問題,例如輸入以下:
I want to leave Taipei on November 2nd
同樣輸入都是Taipei,但是第一個句子是作為目的地,第二個句子是作為出發地,那麼普通的前向網路是無法對同一個輸出做出不同的輸出的。因此就希望此時使用的網路能夠具有一定的記憶性,即在看到Taipei之前因為已經讀入了前一個詞彙(arrive、leave),那麼就根據這前面的詞彙來進行輔助判斷。
其主要的特點在於每個隱含層的輸出都會存放在一個另外的位置中(\(a_1,a_2\)),並且隱含層接受的輸入包括原本的輸入和當前儲存記憶中的值,假設權重都是1,那麼該隱含層的輸入就是\(a_1+a_2+x_1+x_2\)。並且在第一次輸入的時候由於記憶中沒有值因此需要賦予初始值。
而這樣存在記憶的結構就使得RNN對於輸入的順序是敏感的,不同的輸入之間並不是獨立的,它們順序一旦變化就會引起輸出的大不相同。那麼如果用RNN來處理之前的任務:
注意這裡並不是用到了三個網路結構,而是同一個網路在不同的時間點被使用了三次。那麼這就可能使得輸入同樣的詞彙結果輸出是不一樣的,因為前面的輸入也會影響該結果。
而RNN同樣也可以往deep發展:
下面介紹RNN網路的變體:
這兩種網路都是RNN的推廣,架構的主要區別在於:
這個結構的特點在於對於網路的架構是雙向的,即正向是跟前面一樣,反向呢是從尾部不斷讀到頭部(因為順序不同輸出也就不相同),然後再把每個對應的輸出結合起來給輸出層作為輸入,即將正向的\(x^t\)的輸出和反向的\(x^t\)的輸出一起作為輸出層的輸入得到真正輸出\(y^t\):
那麼這就導致在在對每個輸入做判斷的時候,相當於綜合了前後的所有資訊來做判斷。
顧名思義,就是具有比較長期記憶能力的RNN網路,前面的RNN 網路都是隻要有了新的輸入進來,記憶結點中就會被重寫,但LSTM不一樣,其主要特點的結構如下,其具有三個Gate
上面各個Gata的開啟和關閉都是網路自己學習到的。因此每一個記憶結點就有四個輸入(輸入數值和三個控制訊號)和一個輸出
下面來看其具體的運作行為:
為什麼採用Sigmoid函數來作為Gate的啟用函數呢?因為它的輸出在0到1之間,可以認為是該閘門開啟的程度。而這裡可以看出ForgetGate開啟的時候(輸出為1)是對原來的值進行記憶的,只有關閉的時候才是對原來的值清零的。也可以看出輸出的值跟所有閘門的開啟關閉是息息相關的。這邊所有Gate的輸入都是學習得到的。
上面所說的只是單個結點,整體的網路就相當於將神經元換成這整個記憶單元,如下圖:
因此認為神經元數目相同時,LSTM引數量是普通的四倍。而實際上LSTM並不會這麼簡單:
可以認為x是乘以了四個矩陣(權重矩陣)得到了四個向量,這四個向量的長度和該層LSTM記憶單元的數目一樣,然後每一個作為LSTM的輸入,因此剛好就四個輸入,如上圖。因此如果多個串起來就是:
但實際上仍不是LSTM的完全體,完全體如下:
就是將上一層的輸出和記憶單元當前的值和這一層的輸入拼在一起作為輸入,再加上多層:
這就是LSTM的完全體了。
將輸出的詞性或者是標註作為目標向量,損失函數就是輸出向量與目標向量的距離。
跟之前的網路一樣,RNN對於網路引數的學習仍然是採用梯度下降的方式。而為了高效的計算梯度就有了BPTT這個演演算法(課程沒有介紹這部分)。
但是RNN的訓練並不容易:
這是因為它的損失函數非常地特殊:
這就導致損失函數計算梯度的時候經常跳動,總體損失也劇烈變化。而實際上做法可以將梯度設定一個閾值,超過則預設為閾值就可以了,不然可能會陡峭導致梯度無窮大。為什麼會有上面這麼陡峭的損失函數呢?來看下圖的結構:
在很小的區間內,權重非常微小的變化就會導致輸出劇烈的變化,因此很難通過學習率來應對。這主要是因為同一個引數在不同的時間點多次被使用所導致的。
而如果將RNN換成LSTM,它可以解決上述出現的梯度消失(Gradient vanishing)的問題,這可能會在面試中提及。
或者可以採用GRU,其只有兩個gate,更簡單但是表現也不差