1,概述網絡
任務型對話系統愈來愈多的被應用到實際的場景中,例如siri,阿里小密這類的產品。一般任務型對話系統都是基於pipline的方式實現的,具體的流程圖以下:框架
整個pipline由五個模塊組成:語音識別;天然語言理解;對話管理;天然語言生成;語音合成。如今愈來愈多的產品還融入了知識庫,主要是在對話管理模塊引入。在這裏除了語音識別和語音合成模塊不屬於天然語言處理範疇且屬於可選項以外,其餘的三個模塊都是必要的。異步
天然語言理解(NLU):主要做用是對用戶輸入的句子或者語音識別的結果進行處理,提取用戶的對話意圖以及用戶所傳遞的信息。函數
對話管理(DM):對話管理分爲兩個子模塊,對話狀態追蹤(DST)和對話策略學習(DPL),其主要做用是根據NLU的結果來更新系統的狀態,並生成相應的系統動做。性能
天然語言生成(NLG):將DM輸出的系統動做文本化,用文本的形式將系統的動做表達出來。學習
咱們接下來將會詳細討論這四個模塊(NLU,DST,DPL,NLG)。編碼
2 意圖識別和槽值填充spa
舉一個簡單的例子,以一個詢問天氣的任務型對話爲例,根據專家知識,咱們會預先定義該任務的意圖和相應的槽,這句話該怎麼理解呢?3d
好比用戶輸入:「今天深圳的天氣怎麼樣?」,此時用戶所表達的是查詢天氣,在這裏咱們能夠認爲查詢天氣就是一種意圖,那具體查詢哪裏的天氣,哪一天的天氣?在這裏用戶也傳遞出了這些信息,(地點=深圳,日期=今天),而在這裏地點和日期就是信息槽。code
在一個任務型對話系統中會含有多種意圖和槽值,對於意圖識別來講本質上就是一個文本分類的任務,而對於槽值填充來講本質上是一個序列標註的任務(採用BIO的形式來標註)。
仍是以「今天深圳的天氣怎麼樣?」爲例,在乎圖識別時用文本分類的方法將其分類到「詢問天氣」這個意圖,而在作槽值填充時採用序列標註的方法能夠將其標註爲:
今 天 深 圳 的 天 氣 怎 麼 樣
B_DATE I_DATA B_LOCATION I_LOCATION O O O O O O
除了上述兩個主要的內容,NLU中還會涉及到領域識別,語義消歧等。
3 相關技術方案
關於意圖識別和槽值填充既能夠做爲兩個單獨的任務處理,也能夠聯合處理。因爲兩個任務之間的存在較大的相關性(意圖和槽值之間有相關性),所以聯合建模的效果通常會更好。接下來咱們將介紹一些相關的論文:
論文一:A Joint Model of Intent Determination and Slot Filling for Spoken Language Understanding
先上論文的模型結構圖,具體以下:
1)模型結構
給定一個用戶輸入的句子$S = {w_1, w_2, ..., w_T}$,在這裏$w_i$表示句子中第$i$個詞,而$T$表示句子的長度。每一個詞使用詞向量表示爲$e(w_i)$,做者在這提出以前有相關工做代表使用上下文輸入的方式能夠提升槽值填充的表現,在這裏也引入了這種作法,具體的以下,將$t$時刻的輸入由$w_t$轉換成$x_t$,$x_t$的表達式以下所示:
在上面式子中$d$表示窗口的大小,除此以外,做者還認爲引入命名實體對槽值填充的結果也會有提高,所以對$x_t$進一步升級,其表達式以下:
上面式子中$e'(n_t)$表示$t$時刻下的詞對應的命名實體的向量嵌入,$c$表示命名實體的窗口大小,我的以爲這種作法在實際項目中並不實用,雖然說做者證實了在ATIS數據集(一個航班查詢的對話集,主要用於意圖識別和槽值填充的實驗中)上確實有提高,但現實中可能命名實體的準確率就很難有保障,這種狀況會不會反而致使槽值填充的結果降低呢?
輸入定義好了以後,再來看看網絡結構,文中的網絡結構是用了Bi-GRU,對前向後向的輸出採用拼接的方式。所以輸入$x_t$,對應隱層的輸出$h_t$的表達式以下:
在兩個子任務的輸出以下:
上面式子中,$y_t^s$ 表示槽值填充的輸出,$y^u$表示意圖識別的輸出,其中$h^u$是對隱層輸出最大池化的結果。其表達式以下:
2)定義損失
採用兩個子任務的損失來創建統一的聯合損失,首先來看下意圖識別的損失表達式:
意圖識別是一個多分類問題,採用交叉熵做爲損失函數,在這裏$l^u$表示句子的真實意圖。
槽值填充的損失定義的比較複雜,在這裏引入了一個矩陣$A$來表示各槽值之間的機率轉換狀況,這個矩陣是能夠被訓練的。做者給出了一個衡量每條序列的分數表達式,具體以下:
在上面式子中,$A_{l_{t-1}l_t}$表示從$l_{t-1}$轉移到$l_t$的機率,由於$l_t$是未知的,所以這裏應該是一個長度爲$T$的機率分佈,這個其實相似於RNN的原理,從$h_{t-1}$到$h_t$的作法。$y_t^s(l_t)$是在$t$時刻softmax的結果,也是一個長度爲$L$的機率分佈向量。可是對於全部時間步的輸出直接相加,這一操做徹底沒看懂,這裏講道理是否是也應該對$A_{l_{t-1}l_t} + y_t^s(l_t)$求交叉熵再相加呢?
定義完上面的表達式以後,槽值填充的損失函數爲:
其中:
最終整個模型的損失函數以下:
參數$\alpha$是用來調節意圖識別和槽值填充的損失的權重的。
論文二:Attention-Based Recurrent Neural Network Models for Joint Intent Detection and Slot Filling
這篇論文引入了encoder-decoder框架和attention機制來聯合建模意圖識別和槽值填充兩個子問題,一樣首先先來一張圖:
上面三幅圖分別表示在decoder時不一樣的處理方式:
a) 沒有線性輸入,只有attention輸入,線性輸入這個怎麼理解呢?在序列標註中是線性解碼的,也就是說在$t$時刻decoder和$t$時刻encoder的相關性最大,其實拋開encoder-decoder框架就是序列標註的框架,如圖a中解碼時的輸入只有$c_i$(attention的結果),沒有$h_i$(encoder的隱層輸出)。
b) 只有線性輸入,沒有attention輸入。
c) 既有線性輸入又有attention輸入。
這篇論文總體上沒有什麼新奇的結構,都是咱們熟悉的結構,所以不在對模型的結構展開講。在這裏引入的attention對槽值填充的結果並無明顯提高,這也證實了一點序列標註問題是個線性解碼問題,attention這種機制並沒什麼用,可是在乎圖識別任務上引入attention仍是有一些提高的。
論文三:A Bi-model based RNN Semantic Frame Parsing Model for Intent Detection and Slot Filling
1)模型結構
這篇論文仍是比較有特色的,在這裏的聯合建模並無對兩個任務共享模型參數,並且訓練時也不是把兩個任務的損失合併成一個統一的損失來同步訓練,而是採用了異步訓練的方式。此外論文在普通框架和encoder-decoder框架上試驗。這兩種框架的性能差別不大,encoder-decoder會稍微高一點點。具體來看下模型結構,結構圖以下:
上圖中a是採用了decoder解碼,而b是沒有采用decoder解碼。
給定一個句子序列${x_1, x_2, x_3, ......, x_n}$,每一個詞都用詞向量表示,給定兩個Bi-LSTM模型,模型的隱層神經元個數相同。首先來看圖a中的表達式。
a ) with decoder
意圖識別表達式:
上面式子中第一個式子有一個錯誤,式子中的$n-1$應該是$t-1$。第一個式子中$s_t^1$表示$t$時刻decoder的隱層輸出,其中1表示意圖識別。$h_{t-1}^1$表示意圖識別encoder模型在$t-1$時刻的隱層輸出,$h_{t-1}^2$表示槽值填充encoder模型在$t-1$時刻的隱層輸出。第二個式子就是利用最後時刻的輸出來分類。
槽值填充表達式:
上面式子中各參數的含義和意圖識別中的同樣,但槽值填充每一個時刻都會decoder一個結果。
b) without decoder
不含decoder的表達式相對來更簡單,就不作過多的解釋了,具體以下:
意圖識別表達式:
槽值填充表達式:
2)損失函數
在這裏採用異步訓練的方式分別訓練兩個子任務,首先意圖識別的損失函數以下:
這裏就是一個交叉熵損失函數。
槽值填充的損失函數:
一樣也是一個交叉熵損失函數。
具體的異步訓練過程也很簡單,給定一個batch數據集$X_i$,先將$X_i$和$h^2$(槽值填充的隱層輸出)輸入到意圖識別模型中,經過$L_1$損失函數來訓練意圖識別模型,而後再將$X_i$和$h^1$輸入到槽值填充模型中,經過$L_2$損失函數訓練槽值填充模型。做者認爲這種異步訓練的方式能夠減少兩個任務之間共享模型的負做用,之引入了隱層的信息,且用兩個損失函數來分別訓練模型。
論文四:A Model of Zero-Shot Learning of Spoken Language Understanding
在實際任務中,咱們可能沒這麼多的對話數據,所以遷移學習在任務型對話系統中的研究也不少,不管是NLU仍是DST,DPL中。
其實上面對意圖識別和槽值填充兩個子任務聯合建模也是一種遷移學習,但本文提出了一種更極端的環境下的遷移學習——zero-shot。
zero-shot的定義是:利用標籤在語義空間的類似性,利用已有的標註數據對在標註數據中不存在的類別進行分類。
首先定義下論文中的輸入輸出,論文的輸入是一個句子$S$,輸出是一個用戶的對話動做,能夠表示爲:
$ act type(attribute type = attribute value) $
舉個例子$inform(food=chinese)$,其實這個對話動做能夠理解爲意圖和槽值的組合。像這樣的對話動做在訓練集中有限的,所以對於訓練集來講能夠看做是一個多類別分類的問題,可是隨着在現實中可能存在不少的對話狀態並不在訓練集中,這樣用傳統的方法就沒法很好的泛化到實際的環境中,例如對於food這個槽,其對應的值有不少個,而訓練集只能覆蓋一部分。要解決該問題就須要用到zero-shot方法。
1)模型結構
首先給出模型結構圖:
首先對模型的輸入和標籤分別編碼用向量表示:
輸入編碼:
上面式子中$\phi(U_i)$表示句子中第$i$個位置的編碼結果,$w_i$表示當前詞,$w_j$表示前一個詞,$w_k$表示後一個詞,而$w_h$表示經過依存分析獲得的和$w_i$相關的中心詞。
標籤編碼:
在標籤編碼時對act-type,attribute-type,attribute-value分別用詞向量表示,而後利用上面的式子將三者融合在一塊兒做爲標籤的編碼結果。
2)損失函數
在這裏將多分類問題轉換成對每一個標籤的二分類問題,其損失函數以下:
這個損失函數是否是很熟悉,像極了SVM,在上面的模型結構圖中也代表了這一點,在對每一個標籤作二分類時不只要分開還要間隔最大化。在上面的式子中$y = {1, -1}$若是時正類則爲1,負類則爲-1。咱們再來看看這個式子:
實際上就是計算句子和標籤的類似度。所以問題的本質上相似於訓練一個計算類似度的模型,以後在預測時根據句子和標籤的類似度來進行分類,這樣就不須要訓練集中包含該標籤了。
除了這些論文以外,還有不少不錯的論文都值得去讀,尤爲是在遷移學習這一塊,感受其應用價值很高,畢竟在工業界少樣本是廣泛存在的現象。