李宏毅深度學習筆記-RNN循環神經網絡


RNN應用案例

智慧訂票系統

image-20200605100532766

例如一些智慧客服或者智慧訂票系統里,往往需要槽填充。

什么是槽填充?

系統里有兩個槽位,分別叫做目的地和到達時間。假如一個人對訂票系統說“ i would like to arrive Taipei on November 2nd”,那么系統要自動知道每個詞匯屬於哪一個槽位,例如“Taipei”屬於目的地這個槽位,“November 2nd”屬於到達時間這個槽位,其他詞匯不屬於任何槽位。

image-20200605101712316

如何進行槽填充?

思考是否可以用一個前饋神經網絡來解

input一個詞匯,例如把“Taipei”轉化為向量丟到神經網絡里去

image-20200605101943491

如何把詞匯轉化為向量?

最簡單的方式是1-of-N encoding,類似獨熱編碼

image-20200605102219981

如何把詞匯轉化為向量?

dimension for “Other”:

有時候只用1-of-N encoding描述一個詞匯會出現問題,因為向量是根據詞典制作的,如果出現了不在詞典里的新詞匯,原來的向量就沒法表達,那么在原來向量里添加一個新的維度“other”,所有遇到的新詞匯都歸到“other”類。比如“Gandalf、Sauron”不在詞典里,就歸為“other”類。

Word hashing:

也可以用某個詞匯的字母來表示成詞向量,如果用n-gram(n元)字母表示的話,就不會出現不在詞典中的新詞匯問題。比如一個詞匯“apple”,用三元字母可表示為“app”,“ppl”,“ple”,那么"apple"在詞向量里的“app”、“ppl”、“ple”維度都為1,其余維度為0

image-20200605103501514

把詞匯表示為詞向量后,作為input丟到前饋神經網絡里去,在槽填充這個任務里,希望輸出是一個概率分布(屬於哪個槽的概率)。

例如上圖Taipei屬於槽“目的地”的概率、屬於槽"出發時間"的概率等等。

image-20200605132729141

光有前饋神經網絡是不能夠做槽填充的

為什么不夠?

假設一個使用者說"arrive Taipei on November 2nd",arrive是other,Taipei是目的地,on是other,November是時間,2nd也是時間。另外一個使用者說"leave Taipei on November 2nd",那Taipei就應該是出發地而不是目的地。但是對前饋神經網絡來說,輸入一樣,輸出也是一樣的,不能讓Taipei的輸出即是目的地又是出發地。這個時候我們就希望神經網絡是有記憶力的,在看到紅色Taipei的時候,記得Taipei前的arrive,看到綠色Taipei的時候記得leave,可以根據詞語的上下文,產生不同的輸出。那有記憶的神經網絡就做到相同輸入,不同輸出。

什么是RNN

image-20200605133857027

有記憶的神經網絡叫做RNN循環神經網絡

每次隱藏層里的神經元產生輸出的時候,這個輸出會被存到memory里去(上圖藍色方塊表示memory)。下一次有輸入的時候,神經元不是只考慮\(\large x_1,x_2\) ,還會考慮存在memory里的值,即\(\large a_1,a_2\)也會影響神經元的輸出。

image-20200605134345934

舉個例子

上圖網絡所有的權重為1,所有的神經元沒有偏置,假設所有的激活函數都是線性激活函數(讓計算不要太復雜)。

現在假設輸入是一個序列\(\begin{bmatrix} 1 \\ 1 \\ \end{bmatrix}\begin{bmatrix} 1 \\ 1 \\ \end{bmatrix}\begin{bmatrix} 2 \\ 2 \\ \end{bmatrix} \cdots\),輸入到循環神經網絡里。在開始使用RNN前,要先設置memory的初始值,現在假設初始值為0,0。輸入1,1后,上圖第一個綠色神經元除了連接到輸入1,1外,還連接到memory 0,0,那么輸出等於2,第二個綠色神經元輸出因為2,那么兩個紅色神經元的輸出都為4。

輸入[1,1],輸出[4,4]

image-20200605135355852

接下來RNN會把綠色神經元的輸出存在memory里去,memory里的值更新為2

再輸入[1,1],這時候綠色神經元的輸入為4個,[1,1]和[2,2],權重都為1,所以輸出為2+2+1+1=6,最后紅色神經元的輸出為6+6=12

所以對RNN來說,就算是同樣的輸入,也可能會有不同的輸入,因為存在memory里的值是不一樣的

image-20200605142830972

因為綠色神經元的輸出是[6,6],被存到memory里去,memory的值更新為6

接下來輸入[2,2],綠色神經元考慮4個輸入,[2,2]和[6,6],輸出為6+6+2+2=16,那么紅色神經元的輸出為16+16=32

做RNN的時候有一件很重要的事情是,RNN認為輸入的序列不是獨立的,如果調換輸入序列的順序(比如把\(\begin{bmatrix} 2 \\ 2 \\ \end{bmatrix}\)換到最前面),那么輸出就會完全不一樣,所以RNN會考慮輸入序列的順序

RNN架構

image-20200605143804440

用RNN做槽填充

有一個使用者說“arrive Taipei on November 2nd”,則把arrive變成一個向量丟到神經網絡里,隱藏層的輸出為\(\large a^1\) (是一排神經元的輸出,是一個向量),根據\(\large a^1\) 產生\(\large y^1\) (arrive屬於哪一個槽的概率),然后\(\large a^1\)被存到memory里去。

接下來輸入表示Taipei的向量,隱藏層會同時考慮Taipei和memory \(\large a^1\),得到\(\large a^2\),再根據\(\large a^2\)得到\(\large y^2\)(Taipei屬於哪一個槽的概率),然后\(\large a^2\)被存到memory里去。

后面的詞語處理類推之前的過程,輸入表示on的向量,隱藏層同時考慮輸入和memory \(\large a^2\),得到\(\large a^3\)再得到\(\large y^3\)(on屬於哪一個槽的概率)。

這里要注意,有人看到上圖會覺得有3個網絡,其實是同一個網絡在3個不同的時間點被使用了3次。上圖同樣的weight用相同的顏色表示。

image-20200605145428281

有了memory之后,輸入相同,就可以有不同輸出了。例如上圖的Taipei,紅色Taipei前面接的是leave,綠色Taipei前面接的是arrive,因為leave和arrive的向量不同,所以memory 的值不同,隱藏層的輸出也會不同。

其他RNN架構

Elman Network

保存隱藏層的輸出值,在下一個時間點被隱藏層使用

image-20200605145851113

RNN的架構是可以任意設計的,可以變得很深

疊加隱藏層,每個隱藏層的輸出都被存在memory里,在下一個時間點的隱藏層會讀取上一個時間點保存的memory 值。

Jordan Network

保存整個網絡的輸出值,在下一個時間點被隱藏層使用

image-20200605150314095

據說Jordan Network 可以得到更好的效果,因為隱藏層是沒有學習目標的,學什么樣的隱藏信息很難控制(學到的東西放到memory里),但是\(y\)(輸出層)是有學習目標的,可以比較清楚地知道存在memory里的是什么樣的東西

雙向RNN

image-20200605150924396

RNN可以是雙向的

之前input一個句子是從句首讀到句尾,假設詞語用\(x^t\)表示,那就是先讀\(x^t\),再讀\(x^{t+1}\),再讀\(x^{t+2}\)

讀取方向也可以反過來,先讀\(x^{t+2}\),再讀\(x^{t+1}\),再讀\(x^{t}\),可以同時訓練一個正向的RNN和一個反向的RNN,然后把兩個RNN的隱藏層拿出來,接到同一個輸出層得到最后的\(y\)

如上圖,正向RNN的\(x^t\)的輸出和反向RNN的\(x^t\)的輸出,都輸入到一個輸出層得到\(y^t\)

用雙向RNN有什么好處?

雙向RNN在產生輸出的時候,看得范圍是比較廣的。如果只有正向RNN,在輸出\(y^{t+1}\)時,RNN只看過\(x^1\)\(x^{t+1}\)的部分,但是雙向RNN在輸出\(y^{t+1}\)時,不僅看了\(x^1\)\(x^{t+1}\)的所有輸入,而且看了句尾到\(x^{t+1}\)的所有輸入,等於看了整個輸入序列,再去決定詞匯的槽位是什么,這樣效果比只看一半句子會好。

LSTM

image-20200605152102653

之前的RNN是比較簡單的版本,隨時可以把值存到memory中,也可以隨時讀取memory中的值

現在比較常用的memory稱為Long Short-term Memory(長短期記憶單元),比較復雜有3個門

  1. 輸入門:隱藏層的值要存到memory時,要先通過輸入門,被打開時才可以把值保存到memory,門是打開還是關閉是神經元自己學習的。
  2. 輸出門:輸出的地方也有一個門,表示其他的神經元可不可以從memory里讀取值,只有被打開的時候才可以讀取,輸出門什么時候打開關閉也是神經元自己學習的。
  3. 遺忘門:第三個門,表示什么時候memory要把過去保存的東西忘記,或者什么時候要把保存的東西做一些格式化,格式化掉還是保存下來也是神經元自己學習的。

一個LSTM memory cell,可以看成有4個輸入,1個輸出。4個輸入分別是

  1. 想要被存到memory cell里的值(由輸入門控制是否保存)
  2. 操控輸入門的信號
  3. 操控輸入門的信號
  4. 操控遺忘門的信號

一個小小的冷知識,Long Short-term里的划線應該被放在哪里?

有些人把划線放在Long和Short之間,這是沒有意義的,應該放在Short和term之間

因為LSTM的memory還是一個比較短期的記憶(只是稍微長一點的短期記憶),RNN的memory在每個時間點都會被更新掉,只保存前一個時間點的東西,LSTM可以記得稍微長一點的東西,只要遺忘門不要決定遺忘掉

image-20200605154335998

詳細的LSTM cell 公式如上圖所示。

  • \(\large z\)是輸入
  • \(\large z_i\)(一個數值)是操控輸入門的信號
  • \(\large z_f\)是操控遺忘門的信號
  • \(\large z_o\)是操控輸出門的信號
  • 最后得到一個輸出\(\large a\)

假設一個單元里,有上面4個輸入(\(\large z,z_i,z_f,z_o\))之前,已經保存了值\(\large c\)

\(\large z_i,z_f,z_o\)通過的激活函數通常選擇sigmoid函數(取值0-1,代表門被打開的程度),激活函數輸出為1代表門是處於打開的狀態,為0表示門處於關閉的狀態

計算當前時刻要保留的新信息\(\large g(z)f(z_i)\)

  • \(\large z\)通過一個激活函數得到\(\large g(z)\)\(\large z_i\)通過另一個激活函數得到\(\large f(z_i)\)(當前時刻信息保留程度)
  • \(\large g(z)\)乘以\(\large f(z_i)\)

接下來計算當前時刻的保留信息(新的memory值)\(\large c'=g(z)f(z_i)+cf(z_f)\)

  • \(\large z_f\)通過另一個激活函數得到\(\large f(z_f)\)(上一個時刻的信息保留程度)
  • 把存在memory 里的\(\large c\)乘上\(\large f(z_f)\) (上一時刻要保留的信息)
  • 計算\(\large c'=g(z)f(z_i)+cf(z_f)\) (當前時刻要保留的新信息+上一時刻要保留的信息)
  • \(\large c'\)是新的保存在memory里的值(當前時刻的保留信息)

根據到目前為止的計算發現

  • \(\large f(z_i)\)在控制\(\large g(z)\)\(\large f(z_i)\)=0就好像沒有輸入,\(\large f(z_i)\)=1就好像直接把\(\large g(z)\)輸入
  • \(\large f(z_f)\)決定要不要把之前存在memory里的\(\large c\)洗掉,\(\large f(z_f)\)=1意思是保留之前的值,\(\large f(z_f)\)=0意思是洗掉之前保留的值

遺忘門跟我們直覺的想法是相反的,遺忘門打開的時候表示記得,關閉的時候表示遺忘

最后計算要輸出的信息\(\large a=h(c')f(z_o)\)

  • \(\large c'\)通過\(h\)得到\(\large h(c')\)
  • 遺忘門受\(\large z_o\)操控,\(\large z_o\)通過\(f\)得到\(\large f(z_o)\)\(\large f(z_o)\)=0表示memory的值無法通過輸出門
  • \(\large h(c')\)\(\large f(z_o)\) 乘起來(當前時刻要輸出的信息)

LSTM計算例子

image-20200605164033545

一個LSTM例子

在網絡里只有一個LSTM的單元,輸入是三維的向量,輸出是一維的向量

三維的輸入和輸出、memory的值有什么關系?

假設

  • 第2個維度\(\large x_2\)的值為1的時候,\(\large x_1\)的值被保存到memory里
  • \(\large x_2\)的值為-1的時候,memory的值被遺忘(重置)
  • \(\large x_3\)為1的時候,輸出門被打開,才可以有輸出

如上所示的,假設原來memory的值為0

  • 第2個時間點的\(\large x_2=1\),3被存到memory里,則第3個時間點的memory值為3
  • 第4個時間點的\(\large x_2=1\),所以4被存到memory,則第5個時間點的memory為7
  • 第6個時間點的\(\large x_3=1\),所以輸出memory的值7
  • 第7個時間點的\(\large x_2=-1\),memory的值被重置,則第8個時間的memory為0
  • 第8個時間點的\(\large x_2=1\),6被存到memory,則第9個時間的memory為6
  • 第9個時間點的\(\large x_2=1\),memory的值為6,且\(\large x_3=1\),所以輸出memory的值6

image-20200605171153413

實際做一下運算,上圖是一個LSTM的memory cell,有4個輸入值

4個輸入值為:

  • \(\large z\):三維向量值+偏置的一個線性轉換
  • \(\large z_i\):三維向量值+偏置的一個線性轉換
  • \(\large z_f\):三維向量值+偏置的一個線性轉換
  • \(\large z_o\):三維向量值+偏置的一個線性轉換

\(x_1、x_2、x_3\)的權重和偏置是通過訓練數據(梯度下降)學習的,現在先假設我們已經知道了

來分析下可能得到的結果

在input部分,轉換公式為 \(1 \times x_1\) ,就是把\(x_1\)當做input

  • 在輸入門部分,轉換公式為\(100 \times x_2-10 \times 1\),如果\(x_2\)沒有值,由於偏置為-10,通過激活函數后的值接近於0,代表門是關閉的,只有\(x_2\)有值(比如1)的時候,激活函數的值接近於1,代表門是開的
  • 在遺忘門門部分,轉換公式為\(100 \times x_2+10 \times 1\),偏置是10,代表輸出門平時是打開的,只有\(x_2\)取一個很大的負值的之后,門才會關閉
  • 在輸出門部分,轉換公式為\(100 \times x_3-10 \times 1\),偏置是-10,代表輸出門平時是關閉的,只有\(x_3\)取一個很大的正值的之后,門才會打開

假設\(\large g\)\(\large h\)都是線性的,這樣計算比較方便,memory 初始值為0

image-20200605204510962

input第一個向量\(\begin{bmatrix} 3 \\ 1 \\ 0\end{bmatrix}\)

  • 向量轉化后輸出為3
  • 輸入門\(\approx1\),是打開的
  • 通過輸入門的輸出為\(1 \times 3 =3\)
  • 遺忘門\(\approx1\),是打開的
  • 通過遺忘門,memory更新為\(0 \times 1+3=3\)
  • memory通過線性函數轉化后仍為3
  • 輸出門\(\approx 0\),是關閉的
  • 無法通過輸出門,最后的輸出為0

image-20200605205349567

接下來input 向量\(\begin{bmatrix} 4 \\ 1 \\ 0\end{bmatrix}\)

  • 向量轉化后輸出為4
  • 輸入門\(\approx1\),是打開的
  • 通過輸入門的輸出為\(1 \times 4 =4\)
  • 遺忘門\(\approx1\),是打開的
  • 通過遺忘門,memory更新為\(1 \times 3+4=7\)
  • 輸出門\(\approx 0\),是關閉的
  • 無法通過輸出門,最后的輸出為0

image-20200605205424428

接下來input 向量\(\begin{bmatrix} 2 \\ 0 \\ 0\end{bmatrix}\)

  • 向量轉化后輸出為2
  • 輸入門\(\approx 0\),是關閉的
  • 通過輸入門的輸出為\(0 \times 2 =0\)
  • 遺忘門\(\approx1\),是打開的
  • 通過遺忘門,memory更新為\(1 \times 7+0=7\)
  • 輸出門\(\approx 0\),是關閉的
  • 無法通過輸出門,最后的輸出為0

image-20200605205652782

接下來input 向量\(\begin{bmatrix} 1 \\ 0 \\ 1\end{bmatrix}\)

  • 向量轉化后輸出為1
  • 輸入門\(\approx 0\),是關閉的
  • 通過輸入門的輸出為\(0 \times 1 =0\)
  • 遺忘門\(\approx1\),是打開的
  • 通過遺忘門,memory更新為\(1\times 7+0=7\)
  • 輸出門\(\approx 1\),是打開的
  • 通過輸出門,最后的輸出為\(7\times 1=7\)

image-20200605205911215

最后input 向量\(\begin{bmatrix} 3 \\ -1 \\ 0\end{bmatrix}\)

  • 向量轉化后輸出為3
  • 輸入門\(\approx 0\),是關閉的
  • 通過輸入門的輸出為\(0 \times 3 =0\)
  • 遺忘門\(\approx 0\),是關閉的
  • 通過遺忘門,memory更新為\(0 \times 7+0=0\)
  • 輸出門\(\approx 0\),是關閉的
  • 無法通過輸出門,最后的輸出為0

會有問題,這個東西和一般的神經網絡很不像啊

image-20200605210354815

LSTM和一般的神經網絡有什么關系?

在一般的神經網絡里有很多的神經元,會把input 乘上很多不同的權重,作為不同神經元的輸入,每個神經元都是一個函數,輸入一個值,輸出另一個值。

把LSTM的memory cell 想成是一個神經元

image-20200605210737513

現在input \(\large x_1,x_2\)會乘上不同的權重,當做LSTM的不同的輸入

例如上圖第一個LSTM

  • \(\large x_1,x_2\)乘上一組權重產生一個值,去操控輸出門
  • \(\large x_1,x_2\)乘上一組權重產生一個值,去操控輸出門
  • \(\large x_1,x_2\)乘上一組權重產生一個值,去操控遺忘門

對第二個LSTM也一樣

所以剛才講過LSTM有4個input,1個output,對LSTM來說4個input是不一樣的。在原來的神經元里,就是1個input,1個output。

假設LSTM cell的數量和一般神經網絡的神經元數量相同,那LSTM需要的參數量就是一般神經網絡的4倍。

LSTM看起來也不像RNN,那它跟RNN有什么關系

image-20200605211613557

LSTM跟RNN的關系是什么?

假設有一整排的LSTM cell,每個cell的memory都存了一個值

把所有memory值接起來變成一個向量,寫成\(\large c^{t-1}\) ,memory cell里存的memory 值代表向量的一個維度

在時間點\(\large t\) input一個向量\(\large x^t\)

  • \(\large x^t\)首先乘上一個線性的轉換函數(一個矩陣),變成另外一個向量\(\large z\)

    \(\large z\) 的每個維度是每個LSTM cell的input,第一維丟給第一個cell,第二維丟給第二個cell,以此類推

  • \(\large x^t\)再乘上另一個線性的轉換函數(一個矩陣)得到\(\large z^i\)

    \(\large z^i\) 的每個維度是每個LSTM cell的輸入門的input值(來操控輸入門打開的程度)

  • \(\large x^t\)再乘上另一個線性的轉換函數(一個矩陣)得到\(\large z^f\)

    \(\large z^f\) 的每個維度是每個LSTM cell的遺忘門的input值(來操控遺忘門打開的程度)

  • \(\large x^t\)再乘上另一個線性的轉換函數(一個矩陣)得到\(\large z^o\)

    \(\large z^o\) 的每個維度是每個LSTM cell的輸出門的input值(來操控輸出門打開的程度)

得到4個向量,每個向量的維度和cell 個數相同,那么4個向量合起來就會去操控所有memory cell的運作。

image-20200605212449495

注意4個\(\large z\)都是向量,input到每個cell里的只是向量中的一個維度,那么丟進不同cell的是不同維度的數據

雖然每個cell input的數據不一樣,但是可以被一起運算

所有的cell怎么被一起運算?

\(\large z^i\)通過激活函數的值,要乘以\(\large z\),即計算當前時刻要保留的新信息

\(\large z^f\)通過激活函數的值,要乘以memory 保存的值,即計算上一時刻要保留的信息

\(\large z^o\)通過激活函數的值,即保留信息的輸出程度

然后當前時刻要保留的新信息+上一時刻要保留的信息,再通過一個激活函數得到一個值,(這個值)乘(保留信息的輸出程度)得到最后的輸出\(\large y^t\)

image-20200606131620584

當前時刻要保留的新信息+上一時刻要保留的信息=當前時刻要保留的信息(memory里要存的值\(\large c^t\)

當前時刻要保留的信息 \(\times\) 保留信息的輸出程度=要輸出的信息(\(\large y^t\)

計算過程反復繼續下去,在下一個時間點input \(\large x^{t+1}\)

上圖不是LSTM的最終形態,只是一個簡單的版本

image-20200605214928480

真正的LSTM會把輸出接進來,把隱藏層的輸出當做下一個時間點的input ,下一個時間點操控門的值不只是只看\(x^{t+1}\),還會看\(h^t\)

還會加一個叫“peephole”的東西,peephole會把存在memory cell里的值也拉過來。所以在計算4個\(\large z\)的時候,同時考慮了\(\large x,h,c\)\(\large x,h,c\)並在一起乘上4個不同的transform,得到4個不同的\(\large z\)向量,再去操控LSTM的門。

image-20200606133545665

LSTM通常不會只有一層,多層如上圖所示

RNN架構如何學習

image-20200606134334334

之前說過,model要學習的話,要定義一個損失函數來評估model的參數是好是壞,選一個讓損失函數最小的參數。

在RNN里如何確定損失函數?

假設我們的任務是做槽填充,給你一些句子的訓練數據(詞語和label)

把“arrive"input進RNN得到一個輸出\(\large y^1\)\(\large y^1\)會和一個reference 向量計算交叉熵。希望丟進去arrive后輸出的\(\large y^1\),對應到other=1,其余為0的reference 向量。reference 向量的維度是槽位的數目,有40個槽位,則reference 向量的維度為40。

把Taipei(\(x^2\))input進去,希望\(y^2\)和reference 向量的距離越近越好,reference 向量里dest槽位為1,其余槽位為為0。這里要注意,input Taipei之前一定要先input arrive,不然就永遠不知道memory里的值是多少了。

在訓練的時候,不能把word sequence打散來看,word sequence仍要當成一個整體

所以損失函數就是每一個時間點輸出和reference 向量的交叉熵之和,去最小化。

image-20200606154541723

有了損失函數后怎么做?

也是使用梯度下降,現在有損失函數\(\large L\) ,使用梯度下降更新網絡里的每一個參數\(\large w\)

在前饋神經網絡里,為了實現高效率的梯度下降,設計出了BP算法

在RNN里,也有一種高效率的計算方式叫BPTT(Back propagation through time),是BP的進階算法,和BP很類似,由於RNN是在時間序列上運作,所以BPTT考慮了時間的信息。

RNN學習中的問題

image-20200606155112517

不幸的是RNN的訓練是比較困難的

一般我們在訓練的時候,希望學習誤差可以像上圖藍線一樣,隨着迭代次數增加,誤差減小,但是在訓練RNN時,會出現上圖綠線的情況,隨着迭代次數增加,訓練誤差劇烈抖動,甚至出現NAN

這個時候會有什么想法呢?

第一個想法是程序有BUG啊

image-20200606155721479

這個時候會有什么想法呢?

如上圖縱軸是Total Loss,x軸和y軸是兩個參數\(\large w_1,w_2\)

發現RNN的誤差超平面非常崎嶇,有些地方非常平坦,有些地方非常陡峭,就像懸崖峭壁一樣。

RNN的誤差超平面非常崎嶇會造成什么樣的問題?

假設橙點(-2.2和-2.0之間的那個點)為初始點,使用梯度下降調整參數,可能跳過懸崖導致Loss暴增(上下劇烈震盪)。有時候會正好處於懸崖腳下,之前的梯度很小(學習率調地比較大),而該點的梯度很大,再乘以一個比較大的學習率,參數就飛出去了(更新過多)變成NAN,程序就出錯了。

怎么處理誤差超平面非常崎嶇的問題?

使用裁剪,當梯度大於某一個閾值時就進行裁剪,比如當梯度大於15時裁剪為15。那就算是在懸崖腳上,使用的梯度也不會太大,參數不會飛出去。

image-20200606161646265

為什么RNN會有這種奇特的特性?

是不是可能來自於sigmoid函數,之前講ReLU的時候,說過梯度消失的問題,並且是從sigmoid函數來的。可能想到使用Relu試試,但在實際訓練RNN時,很少使用Relu,因為Relu的效果也是比較差的,所以激活函數不是這個問題的關鍵點。

有一個直觀的方法來看一個梯度的大小,把某個參數做個小小的變化,看對輸出的變化有多大,就可以知道這個參數梯度的大小。

舉一個簡單的RNN例子:

有一個最簡單的RNN,只有一個線性的神經元,input沒有偏置,input權重為1,output權重也為1,transition部分的權重為\(\large w\) (memory 接到神經元的權重為\(\large w\)) 。

現在input [1 0 0 0 0 0 ...],第一個時間段為1,接下來都是0,那最后一個時間點的輸出\(y^{1000}=w^{999}\)

\(\large w\)是要訓練的參數,需要知道它的梯度大小,即改變\(\large w\)的值,對輸出有多大的影響。如果\(\large w=1\),那\(y^{1000}=1\) ,當\(\large w=1.01\)時,\(y^{1000}\approx 20751\)。意味着\(\large w\)有一點小小的變化,對output的影響非常大,所以\(\large w\)有很大的梯度。可能會想把它的學習率設小一點,梯度大也沒什么關系。

但是事實上,如果把\(\large w\)設成0.99,那\(y^{1000} \approx 0\),如果把\(\large w\)設成0.01,\(y^{1000}\)還是約等於0。也就是說,在1這個地方有很大的梯度,但在0.99這個地方梯度就變得非常小,這時候又需要一個很大學習率。這樣就說明誤差超平面很崎嶇,設定學習率很麻煩,因為梯度時大時小,而且在非常短的區域內,梯度就會有很大的變化。

從這個例子看,RNN的問題來自於在transition的時候,不同時間點反復使用同樣的東西(從memory接到神經元的\(\large w\) )。導致\(\large w\)一有變化,有可能對梯度沒有影響(0.99和0.01的情況),也有可能造成天崩地裂的影響(1.01的情況),造成梯度時大時小。

所以RNN不容易訓練的問題不是來自於激活函數,而是來自於它有time sequence,同樣的\(\large w\)在不同的時間點被反復使用。

如何解決RNN學習中的問題

LSTM

image-20200606171239957

有什么技巧可以解決RNN訓練的問題?

現在最廣泛使用的技巧就是LSTM,LSTM可以把誤差超平面比較平坦的地方拿掉,可以解決梯度消失的問題,但是不會解決梯度爆炸的問題,有些地方仍然非常崎嶇(變化非常劇烈)。LSTM讓大部分的地方變化都很劇烈,就可以一直使用較小的學習率。

為什么LSTM可以處理梯度消失問題?

RNN和LSTM處理memory 的操作是不一樣的

RNN在每個時間點,memory 的信息會被洗掉,然后存入當前時間點的信息

LSTM在每個時間點,是把原來memory的值乘上一個值(上一時刻信息保留程度),再加上當前時刻要保留的新信息,作為新的memory的值。LSTM的memory 和 input 是相加的。

如果weight可以影響memory的值,這種影響在RNN中的每個時間點會被重置掉,而在LSTM中影響會遺留下來,除非遺忘門關閉(=0,意味着洗掉上一個時刻保留信息),所以可以處理梯度消失問題。

可是LSTM有遺忘門啊,遺忘門關閉的時候,就不能遺留影響了啊?

LSTM第一個版本是沒有遺忘門的,設計出來就是為了處理梯度消失問題,遺忘門是后來加上去的。

現在有說,要給遺忘門設置一個比較大的偏置,確保大部分情況下不是關閉的,只有少數情況會關閉洗掉memory的值。

GRU

現在有另外一個用門操控memory cell的方法叫做門控循環單元(GRU),GRU只有2個門,因此需要的參數比LSTM少1/3,參數少在訓練的時候會更魯棒。如果在訓練LSTM的時候覺得過擬合比較嚴重,那可以試一下GRU。

GRU為什么可以少用一個門?

精神就是舊的不去,新的不來,把輸入門和遺忘門連動起來。當輸入門打開的時候,遺忘門自動關閉(=0), 存在memory的值會被洗掉,當遺忘門打開的時候,輸入門關閉。要把存在memory的值清掉,才可以把新的值放進去

更多其他的方法

image-20200606200241005

還有很多其他技術可以用來處理梯度消失問題,比如Clockwise RNN和SCRN等等。

還有一個,使用一般RNN,但是用單位矩陣初始化為transition的weight,然后使用ReLU作為激活函數,可以得到比LSTM好的效果。如果transition的weight是隨機初始化的,那么使用ReLU會比使用sigmoid的效果差。

RNN的應用

image-20200606201028751

在前面槽填充的例子里,假設input和output的數量一樣多,input幾個word就給幾個word槽的label

Many to One

情感分析

image-20200606201220174

RNN可以做到更復雜的事情,input一個序列,output一個向量,這樣就可以做情感分析

比如公司想要知道產品在網絡上的評論是正面的還是負面的。

如何做情感分析?

學習一個RNN,input是一個character sequence,RNN把這個sequence讀一遍,在最后一個時間點把隱藏層輸出拿出來,再通過幾個transform,最后得到情感分析的預測結果。

關鍵詞提取

image-20200606202003555

收集一堆訓練數據集(許多文檔),每個文檔都有label(哪些詞語是關鍵詞),那就可以直接訓練一個RNN。這個RNN把document word sequences作為input,然后通過嵌入層,用RNN把這個文檔讀一次,把最后一個時間點的output拿出來做attention,把重要的信息抽出來,再丟到前饋神經網絡里去,得到最后的output。

Many to Many

語音識別

image-20200606202640248

前面的應用是多對一的,RNN也可以多對多。比如input/output 都是sequences,但是output sequences比input sequences短。

什么樣的任務是output sequences短,input sequences長呢?

比如語音識別,input是一串acoustic feature sequence(聲學特征序列),output是character sequence。

語音是一段聲音訊號,一般處理聲音訊號的方式就是每隔一小段時間,就用一個向量表示。一小段時間通常很短,比如0.01秒。

如果是使用槽填充的RNN,那把這一串input丟進去,只能告訴你每一個向量對應哪一個character。如果是中文的語音識別,output 的target就是所有可能的中文詞匯,常用的有8000個。input的每一個向量對應的時間很短,通常是0.01秒,所以通常是好多個向量對應同一個character,識別的結果就如上圖所示(好好好棒棒棒棒棒)

這不是語音識別的結果啊,怎么辦?

有一招叫做trimming(修剪),把重復的東西拿掉,結果變成好棒,但這樣有個問題,沒辦法識別好棒棒。

CTC

image-20200607140331498

怎么把好棒和好棒棒分開?

使用CTC,即我們在output的時候,不只output所有中文的character,還多output一個符號叫做null(沒有任何東西)。

今天input一串acoustic feature sequence,output就是好 null null 棒 null null null null,然后把null拿掉,就變成好棒。如果輸入另一個sequence,output是好 null null 棒 null 棒 null null,把null拿掉就變成好棒棒。

image-20200607140235876

CTC怎么訓練?

訓練數據告訴你,這一串acoustic feature對應到一串character sequence,但是不會告訴你“好”是第幾個frame對應到第幾個frame,“棒”是第幾個frame對應到第幾個frame。

要窮舉所有可能的alignment(隊列),然后全部訓練。

窮舉太多了,有沒有什么辦法減少一點,自己查資料了解。

image-20200607154919824

上圖是文獻上CTC得到的一個結果,在做英文語音識別的時候,RNN的output target就是character(英文字母)加上空白,當字母之間有邊界時,就自動使用空白間隔。

舉個例子:

第一個frame就是output H,第二個frame output null,第三個frame output null,第四個output I,第五個frame output s,接下來output _ 代表空白......。最后把null的部分拿掉,那語音識別的結果就是HIS FRIEND'S。你不需要告訴機器說HIS是一個詞匯,FRIEND'S是一個詞匯,機器通過訓練數據自己學會這件事情。

用CTC,就算訓練數據里沒有出現的詞匯,也有機會把它正確識別出來。

sequence to sequence

機器翻譯

image-20200608102043646

在sequence to sequence learning里面,RNN的input和output都是sequence,但是兩個sequence的長度是不一樣的。講CTC的時候,input比較長,output比較短。在sequence to sequence中,不確定input和output誰比較長。

現在要做的機器翻譯是,input英文word sequence,翻譯成中文的character sequence,並且不知道英文和中文誰比較長。

假設輸入的是“machine learning”,用RNN讀過去,在最后一個時間點memory存了所有input的整個sequence的信息。

image-20200608104404141

接下來讓機器output一個character(機),把機當做input,再把memory里的值讀進來,會output 器。機要怎么接,有很多細末的技巧。

在下一個時間點,器之后output 學,學之后output 習......,第一次看到model不知道什么時候停止。

image-20200608110252876

要怎么阻止機器不斷地產生詞匯呢?

要多加一個symbol叫做 斷,所以機器不只output所有可能的character,還有一個可能的output 斷。習后面是“===”(斷)的話,就停止。可能會疑惑這個東西怎么訓練,神奇的是可以訓練且有用的,也會用在語音識別上,直接inpout acoustic feature sequence,然后會output character sequence,但是這個方法沒有CTC強。在翻譯上,據說使用這個方法,可以達到state of the art(最高水平)。

image-20200608143309307

sequence to sequence learning 假設是做翻譯的話,input某種語言的文字,翻譯成另外一種語言的文字。有沒有可能直接input某種語言的聲音訊號,output另一種語言的文字,完全不做語音識別?

是可以行得通的

比如直接input法文的聲音訊號,然后model直接得到識別的結果。

假設要把台語轉成英文,台語的語言識別不好做,因為台語沒有一個標准的文字系統,要招人來label台語的文字也有點麻煩。使用上面的技術,只要收集台語的聲音訊號和對應的英文翻譯就可以了,就不需要台語語音識別的結果(不需要文字),就可以做翻譯了。

句法分析樹

image-20200608155244198

現在還可以用sequence to sequence 的技術,甚至可以做到beyond sequence,這個技術也被用在句法分析樹里。

什么是句法分析樹

讓機器看一個句子,然后得到句子語法的結構樹。

為什么可以把樹狀圖描述成一個sequence?

root是S,sequence為 \((S(NP\ NNP)_{NP}(VP\ VBZ(NP\ DT\ NN)_{NP})_{VP}\ .)_S\)

過去要用結構化學習的技術,現在有了sequence to sequence 的技術,只要把上圖的樹狀圖描述成一個sequence,那就只要學習一個sequence to sequence 的model,output就是句法分析樹。

如果的output sequence 不符合語法結構怎么辦?

如果只記得加左括號,忘了加右括號。不會這樣,LSTM有記憶力,不會忘記加上右括號。

image-20200608161300192

之前講過詞向量,如果把一篇文章表示成一個向量的話,往往會用bag-of-word(詞袋),會忽略掉詞序的信息。

舉例:

有一個詞語序列為white bloodcells destroying an infection,另一個詞語序列是an infection destroying white blood cells,這兩句話的意思是相反的,但是使用bag-of-word描述的話,它們的bag-of-word是完全一樣的,有6個一模一樣的詞匯,但是一句話是正面的,另一句話是負面的。

可以用sequence to sequence auto-encoder這種做法,在考慮詞語序列順序的情況下,把一篇文章變成一個向量。

image-20200608200310817

sequence to sequence auto-encoder怎么做?

input一個word sequence,通過一個RNN把它變成一個embedded的向量,再把這個embedded向量當成decoder的輸入,讓decoder長回一個一摸一樣的句子。

如果RNN可以做到這個事情,那encoding的這個向量,就代表這個input sequence里的重要信息,所以decoder才能根據encoder的向量,把信息decoder回來。

訓練sequence to sequence auto-encoder是不需要label data的,只需要收集大量的文章,直接訓練就好了。

sequence to sequence auto-encoder還有另外一個版本叫做skip-thought。如果是用Seq2Seq auto encoder,input和output都是同一個句子,得到的code比較容易表達語法的意思,如果用skip-thought,output target 是下一個句子,容易得到語義的意思。

image-20200608201808396

這個結構甚至可以是階層的

  • 可以每一個句子都先得到一個向量(變成sentence sequence)。比如Mary was hungry .得到一個向量,she didn't find any food得到一個向量。(Encode-Word)
  • 再把這些向量加起來,變成一個整個document high level的向量(Encode-Sentence)
  • 再用這個document high level的向量去產生一串sentence的向量(Decode-Sentence)
  • 再根據每一個sentence向量解回word sequence(Decode-Word)

所以這是一個4層的LSTM

  • 從word變成sentence sequence(Encode-Word)
  • 再變成document level的東西(Encode-Sentence)
  • 再解回sentence sequence(Decode-Sentence)
  • 再解回word sequence(Decode-Word)
語音處理

image-20200608204401857

Seq2Seq auto encoder也可以用在語音上,可以把一段音頻段變成一段固定長度的向量。

比如上圖有一堆聲音訊號,長長短短都不一樣,把它們變成向量的話,可能dog/dogs的向量比較接近,可能never/ever 的向量比較接近。

這個稱之為音頻的word to vector,word to vector是把一個word變成一個vector,這邊是把一段聲音訊號,變成一個向量。

image-20200608205457907

Seq2Seq auto encoder在語音上有什么用?

可以拿來做語音的搜尋,有一個聲音的database,然后你說美國白宮,不需要做語音識別,直接比對聲音訊號的相似度,機器就從database里找到有美國白宮的部分

這個怎么做?

  • 有一個audio的數據庫,把這個數據庫做分段,每一段用audio segment to vector的技術變成一個vector。

  • 現在使用者輸入一個Query(也是語音的),通過audio segment to vector的技術,把這段聲音訊號也變成向量。

  • 接下來計算它們的相似度,得到搜索的結果

image-20200608210524161

怎么把一個音頻段變成一個向量?

  • 先把音頻段抽成聲學特征序列
  • 把聲學特征序列丟到RNN里,RNN每個角色就是一個encoder,最后時間點存在memory里的值代表了整個input的聲音訊號的信息

存在memory里的值,是一個用來表示一整段聲音訊號的向量

image-20200608211152689

只有上圖左下的RNN encoder沒辦法訓練,同時還要訓練一個RNN的decoder,decoder的input是encoder存在memory里的值,然后產生一個聲學特征序列。

希望\(y_1\)\(x_1\)越近越好,然后根據\(y_1\)再產生\(y_2,y_3,y_4\) ,訓練的targe是\(y_1\)\(y_4\)\(x_1\)\(x_4\)越接近越好。

訓練的時候RNN的encoder和RNN的decoder共同學習的(一起訓練),只有單獨一個是沒法訓練的。

image-20200608211641495

上圖是實驗上一些有趣的結果。圖上每個點都是一段聲音訊號,聲音訊號用sequence to sequence encoder 技術變成平面上一個向量。

會發現fear的位置在左上角,near的位置在右下角,中間會有一段關系,fame的位置在左上角,name的位置在右下角,中間也會有一段關系。

把fear的f換成n,把fame的f換成n,它們word vector的變化方向是一樣的。不過這邊的vector還沒有辦法考慮分段語義的信息。

聊天機器人

image-20200608212055774

一個sequence to sequence learning (不是sequence to sequence auto-encoder)的demo,用來訓練一個聊天機器人。收集很多對話,比如說電影的台詞,如果電影台詞里面,有一個人說"how are you",另外一個人接"i am fine",那就告訴機器說,當這個sequence to sequence learning的input是"how are you"的時候,model的output就要是"i am fine",你可以收集這種數據,讓后讓機器去訓練。

我們收集了40000句的電視影集和美國總統大選辯論的句子,然后讓機器去學這個sequence to sequence的model。

Attention-based Model

image-20200629120308016

除了RNN之外,還有另外一種用到memory的神經網絡,叫做attention-base model,可以想成是RNN的一個進階版本。

我們知道人的大腦,有非常強的記憶力,可以記得非常多的東西,比如同時記得早餐吃了什么、10年前的夏天發生了什么、在這幾門課學到的東西。當有人問你什么是deep learning的時候,你的大腦就會提取重要的信息,然后把這些信息組織起來產生答案,但是你的大腦會自動忽略掉哪些無關的事情,比如10年前夏天發生的事情等等。

image-20200629120805502

其實機器也可以做到類似的事情,機器也可以有很大的記憶容量,可以有一個很大的database,在這個database里面,每一個向量代表某種信息,被存在機器的記憶里面。

當你輸入一個input的時候,這個input會被丟進一個中央處理器(可能是一個DNN/RNN),這個中央處理器,會操控一個讀頭控制器(reading head controller),去決定這個reading head放的位置。然后機器再從這個reading head放的位置,去讀取信息出來,產生最后的output。

image-20200629121331072

這個model還有2.0的版本,它回去操控一個writing head controller,決定writing head放的位置,然后機器會把它的信息通過這個writing head寫進它的database里面。所以它不只有讀的功能,還可以把資訊(discover出來的東西)寫進它的memory里去。這個就是大名鼎鼎的neural turing machine。

image-20200629130638593

現在attention-based model常常被用在閱讀理解上,讓機器讀一堆文章,文章里的每句話變成一個向量存起來,每個向量代表某一句話的語義。

接下來,你問機器一個問題,比如"玉山有多高"之類的,這個問題被丟進中央處理器里,中央處理器去控制一個reading head controller,決定database里哪些句子是跟中央處理器有關的。假設機器發現這個句子(上圖最下方第一個橙色箭頭所示的向量)與現在的問題有關,就把reading head放在這個地方,然后把信息讀到中央處理器里,這個讀取信息的過程可以是反復的(重復數次),也就是說機器並不只是從一個地方讀取信息,在某一個位置讀取信息后,還可以換個位置接着讀取信息,然后把所有讀到的信息收集起來,最終給一個答案。

image-20200629131323484

上圖是facebook AI research在QA question answer test上的一個實驗結果,這個test比較簡單,有很多臨時產生的文章和一些簡單的問題,我們需要回答這些問題。要做的事情就是讀過這5個句子,然后問它"what color is Greg?",它會得出一個正確的答案“yellow”。

你可以從機器attention的位置,也就是reading head的位置,看出機器的思路。上圖藍色代表機器reading head放置的位置。Hop1/2/3代表時間,在第一個時間點,機器先把它的reading head 放在Greg is a frog,提取Greg is a frog這個信息,接下來再提取Brian is a frog這個信息,接下來再提取Brian is a yellow的信息,最后得到結論說,Greg的顏色是yellow。這些事情是機器自動學習出來的,也就是機器要attend在哪一個位置,是通過神經網絡自己去學習的,不是寫程序去告訴機器先看哪個句子,在看哪個句子。

image-20200629132203016

那也可以做visual question answering(視覺問答),讓機器看一張圖,然后問它一個問題“這是什么?”,如果正確回答是香蕉的話,它就超越部分人類了。

image-20200629132339612

如何做視覺問答?

讓機器看一張圖,通過CNN,可以把圖的每一小塊區域用一個向量表示。接下來輸入一個Query,然后這個Query被丟到中央處理器里,中央處理器去操控reading head controller,然后這個reading head controller決定要讀取資訊的位置,看看這個圖片的什么位置是跟現在輸入的問題是有關的。然后把信息讀到中央處理器里面,這個讀取的過程可能有好幾個步驟,機器會分好幾次把信息讀到中央處理器里面,最后得到答案。

image-20200629134215160

也可以做語音的問答,比如說在語音處理實驗室,讓機器做托福的聽力測試。讓機器聽一段聲音,然后問他問題,然后從4個正確選項里面,機器選出正確答案。

image-20200629134423730

用的model architecture(模型架構)跟我們剛才看到的大同小異。讓機器先讀一下問題,然后對問題做語義分析得到問題的語義。聲音的部分先用語音識別轉成文字,再做文字語義分析,機器了解了問題的語義和音頻的語義之后,就可以做attention,決定這個音頻里面,哪些部分是和回答問題有關的。這個就好像是畫重點一樣,機器根據它畫的重點產生答案。甚至可以回過頭去修正它產生的答案,經過幾個過程之后,機器得到最終的答案,並計算和其他選項的相似度,然后選擇相似度最高的選項。

這整個task就是一個大的神經網絡,處理語音識別之外,問題語義的部分、音頻語義的部分都是神經網絡,所以它們都是共同訓練的,只要給機器一些托福的訓練資料。

image-20200629135115558

上圖是實驗的一些結果。讓random猜,正確率是25%,你會發現有兩個方法遠比25%強,這個是很重要的信息。這邊這5個方法,都是native的方法,就是完全不管文章的內容,直接看問題和選項猜答案。你發現說,如果選最短的那個選項,正確率就有35%。如果你分析四個選項的語義,做那個sequence to sequence auto encoder,去把每個選項的語義找出來,然后去看某一個選項跟另外三個選項在語義上的相似度,如果某個選項和另外三個選項在語義上的相似度比較高的話,把它選出來,這樣有35%的正確率。這跟你的直覺是相反的,直覺通常會覺得說,應該尋一個選項,語義與另外三個選項是不像的,不過人家早就知道你會這么做了,所以是個計中計,如果選擇最不像的那個選項反而正確和random差不多。

image-20200629142824315

你可以用memory network,可以得到39%的正確率。

image-20200629142924301

用我們剛才講的model,在有語音識別錯誤的情況下,最好可以做到50%的正確率。

image-20200629143118131

這部分參考結構化序列標注

我們將了deep learning,也講了structured learning,它們中間有什么樣的關系呢?

HMM,CRF,structured perceptron,SVM,它們可以做的事情,比如說做pos taking,input一個sequence,output一個sequence。RNN/LSTM也可以做到一樣的事情。

使用deep learning的技術和structured learning的技術有什么不同呢?

假如我們用的是單向RNN或者LSTM,當你在make decision的時候,你只看了sentence的一半,而如果你用structured learning的話,通過維特比算法,考慮的是整個句子。從這個角度看,也許HMM、CRF......還是占有一些優勢的,但是這個優勢並沒有很明顯,因為RNN/LSTM等等,可以做雙向的,也可以考慮整個句子的信息。在HMM/CRF里面,你可以很明確地去考慮label和label之間的關系。比如你今天再做推理的時候,在用維特比算法求解的時候,你可以直接把你要的約束加到維特比算法里去。你可以說,希望每一個label出現的時候,都要連續出現5次,這件事情你可以輕易地用維特比算法做到,因為你可以修改維特比算法,讓機器在選擇分數最高的句子的時候,排除掉不符合約束的結果。但是如果是RNN和LSTM的話,直接加入一個約束進去是比較難的,沒有辦法要求RNN說連續output某個label 5次,你可以讓它看這種訓練數據去學習,但這比較麻煩,維特比算法可以直接告訴機器做什么事。

HMM,CRF,結構化感知機/SVM都也可以是deep的,但是做deep的學習很困難。之前講過它們都是線性的,因為我們定的評估函數是線性的,如果不是線性的話再訓練會很麻煩,是線性的才能套用之前講過的方法來做推理和訓練。

deep非常重要,如果只用線性model,函數空間就那么大,就算你可以直接最小化一個error的上界也沒用,因為所有的函數都是壞的。

image-20200707180939154

這部分參考結構化序列標注

你可以說底部(input的特征)先通過RNN/LSTM,output再作為HMM、CRF......的input。如此就可以同時享有deep的好處和結構化學習的好處。

HMM/CRF可以用梯度下降學習,其實結構化感知機/SVM可以用梯度下降訓練。所以你可以把深度學習部分跟結構化學習的部分結合起來一起用梯度下降訓練。

image-20200707181337832

這部分參考結構化序列標注

在語音上常常把深度學習和結構化學習結合起來。常常見到的模型是深度學習的model:CNN/LSTM/DNN加上HMM的組合。

RNN做的事情是取代了發射部分,原來HMM里面發射概率就是簡單的統計。

怎么取代呢?

一般RNN input一個聲學特征,output聲學特征屬於每一個state的概率。對這個概率做一下轉換,如上圖右邊所示。

其實加上HMM,在語音識別里面是很有幫助的。就算是你用RNN做語音辨識的時候,常常會遇到一個問題,假設是一個一個frame丟到RNN,然后問frame屬於哪一個form。它往往會產生一些怪怪的結果,比如說因為一個form往往是蔓延好多個frame,所以理論上你應該看到說第一個frame是a,第二、第三、第四、第五個frame也是a,然后接下來換成b、b、b。但是如果你用RNN的時候,RNN每一個產生的label都是獨立的,所以可能突然改成b又改回成a,你會發現它很容易出現這個現象。

如果有這樣一個比賽的話,你就會發現RNN有點弱,如果手動改掉前后不一樣的output,你就可以得到大概2%的進步。

如果你加上HMM的話,就不會有這種情況,HMM會幫你把這種狀況修正掉,所以加上HMM是有用的。對RNN來說,訓練的時候是一個一個frame分開考慮的,所以今天假如不同的錯誤對語音識別的結果影響很大(如果我們把b改成錯在其他地方,對語音辨識的結果影響就很小),但RNN不知道這件事情,對它來說,在這邊放一個錯誤跟在另一邊放一個錯誤是一樣的。

image-20200707181818754

這部分參考結構化序列標注

現在也很流行用雙向LSTM+CRF/結構化SVM做槽填充。先用雙向LSTM抽出特征,再把這些特征定義為CRF或者結構化SVM里面用到的特征向量。CRF或者結構化SVM都是線性的model,要先抽\(\phi(x,y)\),然后學習一個weight \(w\)

有人會問說結構化學習到底是否practical,要解三個問題,其中Q2:推理那個問題往往是很困難的,要arg,窮舉所有的\(y\)看哪一個可以讓你的值最大,要解一個最優化的問題。這個最優化問題的解大部分情況都沒有好的solution,序列標注是少數有好的solution的狀況。所以會讓人覺得說結構化學習的用途沒有那么廣泛,但未來未必是這樣子。

image-20200707200037428

想想之前講過的GAN,我認為GAN就是一種結構化學習。如果你把discriminator看作是evaluation function(Q1),最困難的Q2要解一個推理的問題,要窮舉所有我們未知的東西,看誰可以讓我們的evaluation function最大,這一步往往很困難,因為\(x\)的可能性太多了,但事實上這個東西它就可以是generator,我們可以想generator不就是給一個從高斯取樣出現的noise,output一個\(x\)嗎?它output的這個object不是就是可以讓discriminator分辨不出來的那個object嗎?如果discriminator就是evaluation function的話,它output的那個object就是可以讓evaluation function的值很大的那個object。所以這個generator其實就是在解這個問題,generator的output就是這個argmax的output。所以你可以把generator當作是在解inference這個問題。Q3你已經知道了,怎么訓練GAN就是Q3的solution,實時上GAN的訓練跟結構化SVM那些方法的訓練不覺得有異曲同工之妙嗎?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM