筆者:本文為英文論文的翻譯文章,供機器學習、深度學習相關學者參考,如有錯誤理解之處請指出,不勝感激!(如需轉載,請聯系本人:jtianwen2014,並注明出處)。
記憶網絡(譯)
Jason Weston, Sumit Chopra & Antoine Bordes.
Facebook AI Research, 770 Broadway, New York, USA.
{jase,spchopra,abordes}@fb.com
摘要
本文將介紹一種新的學習模型,稱為記憶網絡。記憶網絡利用結合了長期記憶模塊的推斷組件進行推理;並學習如何聯合地使用它們。長期記憶模塊被用作預測,可以讀出也可以寫入。我們將記憶網絡用於問答任務,長期記憶模塊扮演着知識庫的角色,記憶網絡的輸出是文本回復。我們在一個大規模的問答任務上,以及一個從仿真的世界里生成的小規模但是足夠復雜的玩具任務(toy task)上進行評測。在本文的末尾,我們通過鏈乘支持語句到需要理解動詞意圖的問答來展示這寫模型的推理能力。
1 概述
大多數機器學習模型缺乏一種簡單的方式從長期記憶模塊中讀取或寫入,並無縫地結合到推理中。所以,這些方法並沒有利用現代計算機的卓越的優勢之一。舉個例子,考慮一個任務,給定一些事實或者故事的集合,然后需要回答相關的問題。理論上這個任務可以通過語言模型來完成,比如循環神經網絡(RNN)(Mikolov et al., 2010; Hochreiter & Schmidhuber, 1997) ,因為這些模型被訓練得可以對於給定的單詞流預測出下一個(或多個)可能的單詞(或單詞集合)。然而,它們的內存(編碼在隱狀態和權值)一般很小,並不能准確地記住過去的事實(致使被壓縮到稠密的向量中)。眾所周知,RNNs很難執行記憶操作,比如簡單的拷貝任務即輸出剛剛讀到的輸入(Zaremba & Sutskever, 2014)。同樣的情形發生在其他的任務上,比如,在視頻和音頻領域,觀看影片需要長期記憶以回答關於這個影片的問題。
在本文的工作中,我們介紹一種叫做記憶網絡的模型,嘗試修復以上提到的問題。核心思想就是將在機器學習中用於推理的有效學習策略和可以讀寫的內存模塊相結合。然后訓練模型,使之可以高效的操作內存內存模塊。我們在第2部分介紹整體的框架,在第3部分相大家展示在文本問答領域的具體實現。我們在第4部分討論相關工作,然后再第5部分介紹實驗部分,最后在第6部分作出總結。
2 記憶網絡
一個記憶網絡由1個內存模塊\(\mathbf{m}\)(用\(m_i\)索引的數組)和如下的4個(通過學習得到的)模塊\(I,G,O,R\):
\(\mathbf{I}\):(輸入特征映射)—— 將輸入轉換為內部特征表示。
\(\mathbf{G}\):(泛化)—— 對於給定新的輸入更新舊的內存。我們稱之為泛化是因為在這個階段網絡有機會壓縮並泛化其內存以供未來某些需要。
\(\mathbf{O}\):(輸出特征映射)—— 給定新的輸入與當前的內存狀態,產生新的輸出(在特征空間中)。
\(\mathbf{R}\):(回復)—— 將輸出轉換為特定格式的回復。比如,文本回復或者一個動作。
給定輸入\(x\)(比如,一個輸入字符,單詞或者句子,這依賴於粒度的選擇,一幅圖片或者一段音頻信號),模型執行如下的流程:
- 將\(x\)轉換為內部特征表示\(I(x)\)。
- 對於給定的新的輸入,更新內存\(\mathbf{m}_i\):\(\mathbf{m}_i=G(\mathbf{m}_i,I(x),\mathbf{m}),\forall i\)。
- 對於給定的新的輸入和內存,計算輸出特征\(o\):\(o=O(I(x),\mathbf{m})\)。
- 最后,將輸出\(o\)解碼為最后的回復:\(r=R(o)\)。
訓練和測試階段都需要這個過程,這兩個階段的差別在於測試階段不更新\(I,G,O,R\)的參數。記憶網絡可以用於很多任務。其組件\(I,G,O,R\)可以使用很多目前存在的機器學習策略,如,SVMs、決策樹、等等。
\(I\)組件:組件\(I\)可以利用一些通用的預處理過程,如,為文本輸入進行句法分析、指代和實體消解。它也可以將輸入編碼到一個內部特征表示,比如,將文本轉換到稀疏或稠密的特征向量。
\(G\)組件:\(G\)最簡單的形式是將\(I(x)\)存儲在內存的‘槽’中:
其中\(H(.)\)是槽選擇函數。也就是,\(G\)只更新內存\(\mathbf{m}\)中索引為\(H(x)\)的部分,而不去觸碰其他部分。\(G\)的更復雜的變種可以基於當前輸入\(x\)所獲的的信息來回退並更新早期存儲的內存(或者全部內存)。如果輸入是字符級別或者可以詞級別,那么可以將其進行分組(也就是,將其分塊化)並將每塊存儲到一個內存槽中。
如果需要的內存巨大(比如,對於Freebase或者Wikidata),那么我們需要對其進行組織。這可以通過之前介紹的槽選擇函數來實現:比如,可以對其設計或者訓練使之可以按照實體或者主題存儲記憶。因此,為了提高擴展的效率,\(G\)(以及\(O\))不需要在所有內存上進行操作:可以只對檢索到的候選子集進行操作(只在相關主題的記憶上進行操作)。我們將在后續的實驗中介紹一個簡單的變種。
如果內存滿了,\(H\)可以通過選擇替換哪個內存來進行“忘記”處理,比如,\(H\)可以對每個記憶的價值進行打分,覆蓋掉最沒有價值的部分。我們還未開展這個實驗。
\(O\)和\(R\)組件:組件\(O\)通常負責從內存中讀取並執行推理,比如,計算哪個是可以獲得優質回復的相關內存。組件\(R\)對於給定的\(O\)產生最后的回復。舉個例子,在問答任務上,階段\(O\)找到相關的內存,然后由\(R\)產生實際的回答詞語,比如\(R\)可能是個以\(O\)為輸入的RNN。我們的假設是,如果沒有這些記憶作為條件,這樣的RNN無法很好執行。
3 為文本實現記憶網絡
有一種特別的記憶網絡,其組件都是神經網絡。我們稱其為記憶神經網絡。在本節中,我們描述具有文本輸入和輸出的記憶神經網絡的一個相對簡單實現。
3.1 基礎模型
在基礎架構中,\(I\)模塊以文本為輸入。我們首先假設這是一個句子:也可以是一個事實的陳述,或者需要系統回答的問題(稍后我們基於單詞的輸入序列)。這個文本以原始的形式存儲在下一個可用的內存槽中,也就是\(S(x)\)返回下一個空的內存槽\(N\):\(\mathbf{m}_N=x,N=N+1\)。\(G\)模塊只用來存儲這個新的記憶,舊的內存不被更新。更加復雜的模型將在后續的章節中敘述。
推理的核心模塊位於\(O\)和\(R\)模塊。對於給定\(x\),模塊\(O\)通過查找\(k\)個支持記憶來產生輸出特征。我們將\(k\)設為2,但是這個過程適用於更大的\(k\)。對於\(k=1\),通過如下方式檢索出得分最高的支持記憶:
其中,\(s_O\)對\(x\)和\(\mathbf{m}_i\)的匹配程度進行打分的函數。對於\(k=2\),我們可以利用迭代的方式發現第二個支持記憶:
其中候選支持記憶\(\mathbf{m}_i\)現在需要基於初始輸入和第一個支持記憶通過打分,方括號代表列表。最終的輸出\(o\)為\([x,\mathbf{m}_{o_1},\mathbf{m}_{o_2}]\),作為模塊\(R\)的輸入。
最后,\(R\)需要產生一個文本回復\(r\)。最簡單的回復就是返回\(\mathbf{m}_{o_k}\),也就是輸出剛剛檢索到的句子。為了進行真實語句的生成,可以利用RNN來代替。在我們的實驗中,我們也考慮使用一種簡單的方式來評估方法,即我們通過排序的方式將文本回復限定為一個單詞:
其中\(W\)是字典中所有單詞的集合,\(s_R\)是對匹配進行打分的函數。
圖1給出了一個任務的例子。未來回答問題\(x=\)“Where is the milk now?”,模塊\(O\)需要首先對所有內存進行打分,也就是所有之前見過的語句,以\(x\)為背景進行檢索最相關的事實,在這個例子中\(\mathbf{m}_{o_1}=\)“Joe left the milk”。然后在給定\([x,\mathbf{m}_{o_1}]\)的情況下,再一次搜索第二個相關事實,也就是\(\mathbf{m}_{o_2}=\)“Joe travelled to the office”(在Joe放下牛奶之前去過的最后一個地方)。最后,模塊\(R\)對給定的\([x,\mathbf{m}_{o_1},\mathbf{m}_{o_2}]\)利用公式(4)對單詞進行打分,輸出\(r=\)“office”。
圖 1:
在我們的實驗中,打分函數\(s_O\)和\(s_R\)具有相同的形式,一個嵌入表示模型:
其中,\(U\)是一個\(n\times D\)矩陣,\(D\)是特征的數量以及\(n\)是嵌入表示的維度。\(\Phi_x\)和\(\Phi_y\)是用於將原始文本映射到\(D\)維的特征空間里。特征空間最簡單的選擇是詞袋表示,對於\(s_O\)我們選擇\(D=3|W|\),也就是詞典中的每個單詞有三個不同的表示:一個用於\(\Phi_y(.)\),另外兩個用於\(\Phi_x(.)\),依賴於輸入的單詞來自於實際輸入\(x\)還是支持記憶,以使得它們可以不同建模。類似地,對於\(s_R\)也使用\(D=3|W|\)。這兩個打分函數使用不同的矩陣\(U_O\)和\(U_R\)。
訓練 我們在完全有監督的設置下訓練,在訓練數據中給定應有的輸入和回答,以及被標記的支持這個回答的句子(但在測試集中只有輸入)。也就是在訓練時我們知道eq.(2)和eq.(3)的最佳選擇。訓練使用一個邊際排序損失和隨機梯度下降(SGD)來進行。更確切點說,對於給定真實回復\(r\)的問題\(x\),以及支持的語句\(\mathbf{m}_{o_1},\mathbf{m}_{o_2}\)(當\(k=2\)時),我們在參數\(U_O\)和\(U_R\)之上優化模型:
其中\(\overline{f},\overline{f'}\)以及\(\overline{r}\)都是非正確的標簽選擇,是\(\gamma\)邊際。在SGD的每一步,我們采樣選取\(\overline{f},\overline{f'},\overline{r}\)而不是為每個訓練樣例計算所有的總和,這和Weston et al.(2011)的做法相同。
當我們使用RNN來實現記憶神經網絡的\(R\)模塊時(而不是像上面那樣用單詞回復),我們將最后一項替換為語言建模任務中使用的標准對數似然函數,其中RNN的輸入是序列\([x,o_1,o_2,r]\)。在測試的時候,在給定\([x,o_1,o_2]\)的情況下輸出\(r\)。對比最簡單的模型,即使用\(k=1\)並且輸出\(\mathbf{m}_{o_1}\)的記憶作為回復\(r\),將只使用第一項用來訓練。
接下來的部分,我們將考察一些基於基礎模型的擴展。
3.2 詞序列作為輸入
如果輸入是詞而非句子級別,即詞以流的形式到達(就像RNN經常處理的那樣)並且陳述和問題都沒有進行詞分割,我們需要修改下之前描述的方法。所以我們加入“分割”函數,將會通過學習得到,輸入單詞的最后沒有分割的序列以尋找分割點。當分割器觸發時(指示當前序列時分割段)我們將序列寫入內存,然后就可以像以前一樣處理。這個分割器的建模方式和我們其他的模塊類似,以嵌入表示模型的形式:
其中\(W_{seg}\)是一個向量(實際上是嵌入空間里的線性分類器的參數),\(c\)是用詞袋表示的詞序列。如果\(seg(c)>\gamma\),其中\(\gamma\)是邊際,那么這個序列被視為一個分割。通過這種方式,我們的記憶神經網絡在寫操作時擁有一個學習模塊。我們將這個分割器視為第一個概念證明:當然,可以設計得更加復雜。訓練時進一步的細節將在附錄B中展現。
3.3 利用散列表的高效記憶
如果存儲的記憶集合十分龐大,那么eq.2和eq.3中對所有記憶進行打分的代價將十分巨大。我們使用散列的技巧來加速查找:將輸入\(I(x)\)散列到一個或多個桶中,然后只對相同桶里的記憶\(\mathbf{m}_i\)進行打分。我們考察兩種散列的方式:(i)散列詞語;以及(ii)對詞嵌入表示進行聚類。對於方法(i)我們構造和詞典中詞語數量相同的桶,然后對於給定的語句我們將其散列到所包含詞語的對應的桶中。(i)的問題在於記憶\(\mathbf{m}_i\)只有當和\(I(x)\)至少一個相同的詞語時才被考慮。方法(ii)試圖通過聚類解決這個問題。在訓練嵌入式矩陣\(U_O\)之后,我們使用K-近鄰進行聚類詞向量\((U_O)_i\),所以給出了K個桶。然后我們將語句散列到所有包含詞語落入的桶中。因為詞向量會和其同義詞相接近從而彼此聚類到一起,所以我們將會對這些相似的記憶進行打分。輸入和記憶之間匹配的詞語都會按照定義被打分。選擇\(K\)控制速度准確權衡。
3.4 建模寫入時間
我們可以將何時一個內存被寫入加入到我們的模型中。這對於回答固定事實的問題(“What is the capital of France?”)並不重要,但當回答一個如圖1的故事相關的問題時卻是重要的。對於給定的\(\mathbf{m}_j\),實現這個的一種明顯方式就是向表示\(\Phi_x\)和\(\Phi_y\)中加入編碼\(j\)的額外特征,假設\(j\)遵循寫時間(也就是,沒有內存槽被重寫)。然而,需要處理的事絕對時間而非相對時間。我們對以下過程有着更多的成功經驗:代替打分輸入,候選對利用上述的\(s\)學習一個定義在三元組上的函數\(s_{O_t}(x,y,y')\):
\(\Phi_t(x,y,y')\)使用三個新的特征,取值0或1:是否\(x\)比\(y\)更加久,\(x\)比\(y‘\)更加久,\(y\)比\(y’\)更加久。(也就是,我們將所有的\(\Phi\)維度擴展3位,如果不適用的時候都設置位0)現在,如果\(\Phi_t(x,y,y')>0\),模型更偏於選擇\(y\),如果\(\Phi_t(x,y,y')<0\),模型更偏於選擇\(y'\)。eq.2和eq.3中的argmax替換為在\(i=1,\cdots,N\)的循環,在每步中持續贏取內存記憶(\(y\)或者\(y'\)),即總是比較當前贏得的內存和下一個內存\(\mathbf{m}_i\)。如果把時間特征移走,這個過程等價於之前的argmax。更多的細節將在附錄C中討論。
3.5 建模生詞
即使對於閱讀量很大的人類來說,生詞也是經常遇到。比如指環王中的單詞“Boromir”。一個機器學習模型如何來處理這個問題?一個可能的方式是使用語言模型:通過生詞周圍的詞語,來預測可能的單詞,並假設這個生詞和預測的單詞語義相似。我們提出的方法正是采用這個想法,但是我們將其融入到我們的網絡\(s_O\)和\(s_R\)而不是作為一個單獨的步驟。
具體地,對於我們看到的單詞,我們將其周圍詞保存在詞袋中,一個詞袋保存左側的詞語,另一個保存右側的詞語。任何未知的詞語都可以這樣表示。所以我們將特征表示\(D\)從\(3|W|\)擴展到\(5|W|\)來對這些上下文進行建模(每個詞袋有\(|W|\)個特征)。我們的模型在訓練階段使用一種“dropout”技術來處理新的單詞:\(d\%\)的時間我們裝作從未讀取過任何詞語,不使用\(n\)維嵌入表示這個詞語,而是用它的上下文來代替。
3.6 精准匹配和生詞
由於低維度\(n\)嵌入式模型無法進行精准的詞匯匹配。一個解決方案是對詞對\(x,y\)進行如下打分來替代之前的:
也就是,向學習到的嵌入式分數加入“詞袋”的匹配(使用一個混合參數\lambda)。另一個,相關的方法還是在這個\(n-\)維的嵌入式空間里,但是為特征表示\(D\)擴展更多的匹配特征,比如,一個詞匯。一個匹配的特征意味着這個詞在\(x\)和\(y\)中都有出現。也就是,我們使用\(\Phi_x(x)^{\top}U^{\top}U\Phi_y(y,x)\)進行打分,其中\(\Phi_y\)實際建立在\(x\)基礎上:如果\(y\)中的詞語與\(x\)中的一次匹配,我們就將這些匹配特征設置為1。未登錄詞可以使用相似的方法建模,在上下文詞匯中使用匹配特征。最后,\(D=8|W|\)。