任務型對話(一)—— NLU/SLU(意圖識別和槽值填充)


 1,概述

  任務型對話系統越來越多的被應用到實際的場景中,例如siri,阿里小密這類的產品。通常任務型對話系統都是基於pipline的方式實現的,具體的流程圖如下:

    

  整個pipline由五個模塊組成:語音識別;自然語言理解;對話管理;自然語言生成;語音合成。現在越來越多的產品還融入了知識庫,主要是在對話管理模塊引入。在這里除了語音識別和語音合成模塊不屬於自然語言處理范疇且屬於可選項之外,其他的三個模塊都是必要的。

  自然語言理解(NLU):主要作用是對用戶輸入的句子或者語音識別的結果進行處理,提取用戶的對話意圖以及用戶所傳遞的信息。

  對話管理(DM):對話管理分為兩個子模塊,對話狀態追蹤(DST)和對話策略學習(DPL),其主要作用是根據NLU的結果來更新系統的狀態,並生成相應的系統動作。

  自然語言生成(NLG):將DM輸出的系統動作文本化,用文本的形式將系統的動作表達出來。

  我們接下來將會詳細討論這四個模塊(NLU,DST,DPL,NLG)。

2 意圖識別和槽值填充

  舉一個簡單的例子,以一個詢問天氣的任務型對話為例,根據專家知識,我們會預先定義該任務的意圖和相應的槽,這句話該怎么理解呢?

  比如用戶輸入:“今天深圳的天氣怎么樣?”,此時用戶所表達的是查詢天氣,在這里我們可以認為查詢天氣就是一種意圖,那具體查詢哪里的天氣,哪一天的天氣?在這里用戶也傳遞出了這些信息,(地點=深圳,日期=今天),而在這里地點和日期就是信息槽。

  在一個任務型對話系統中會含有多種意圖和槽值,對於意圖識別來說本質上就是一個文本分類的任務,而對於槽值填充來說本質上是一個序列標注的任務(采用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。我們再來看看這個式子:

      

    實際上就是計算句子和標簽的相似度。因此問題的本質上類似於訓練一個計算相似度的模型,之后在預測時根據句子和標簽的相似度來進行分類,這樣就不需要訓練集中包含該標簽了。

  除了這些論文之外,還有很多不錯的論文都值得去讀,尤其是在遷移學習這一塊,感覺其應用價值很高,畢竟在工業界少樣本是普遍存在的現象。


免責聲明!

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



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