協同過濾(collaborative filtering)是推薦系統中經典的一類方法。協同過濾中比較經典的解法有基于鄰域方法、矩陣分解等,這些方法都有各自的優點和缺點,本文介紹的方法-協同記憶網絡(Collaborative Memory Network,簡稱CMN)融合了不同協同過濾方法的優點。我們來一探究竟!
協同記憶網絡CMN論文:https://arxiv.org/pdf/1804.10862.pdf
代碼地址:https://github.com/tebesu/CollaborativeMemoryNetwork
1、協同過濾介紹
在信息過載的時代,推薦系統顯得十分重要。而在推薦系統中,協同過濾是一種非常受歡迎且有效的方法。協同過濾基于用戶和物品的過去交互行為,同時認為相似的用戶會消費相似的物品,從而進行推薦。
協同過濾是一類推薦方法,大體上可以分為三個分支:
基于鄰域的方法。這也是我們常說的基于物品的協同過濾和基于用戶的協同過濾方法。我們首先需要計算用戶之間、物品之間的相似度,隨后基于計算的相似度進行推薦。這種方法的一個主要缺陷就是只使用了局部的結構,而忽略了很多全局的信息,因為我們只使用K個相似用戶或者相似物品進行相關的推薦。
基于隱向量的方法。這一分支中最具代表性的是矩陣分解及后面的各種改進方法。通常的做法是將每一個用戶和物品表示稱一個n維的向量,通過用戶矩陣和物品矩陣的相乘,希望能夠盡可能還原評分矩陣。這種做法雖然考慮了全局的信息,但是忽略了一些比較強的局部聯系。
基于混合模型的方法。由于上述兩種方法都有各自的缺陷,因此混合方法開始出現。最具代表性的是因子分解機和SVD++方法。
也就是說,在使用協同過濾這些方法時,我們通常需要關注兩點:
1、需要考慮全局的信息,充分利用整個評分矩陣。
2、需要考慮局部的信息,考慮用戶或者物品之間的相似性。相似性高的用戶或者物品給予更高的權重。
本文將要介紹的協同記憶網絡,便是充分利用了上述兩方面的信息。協同過濾我們已經介紹了,那么什么是記憶網絡呢?我們接下來進行介紹。
2、記憶網絡Memory Network簡介
Memory Network是深度學習的一個小分支,從2014年被提出到現在也逐漸發展出了幾個成熟的模型。我們這里只介紹其中兩個比較基礎的模型。一個是 Basic Memory Network,另一個是End to End Memory Network。
我們首先要搞清楚的是,為什么要有記憶網絡?在翻譯、問答等領域的任務中,我們通常使用的是Seq2Seq結構,由兩個循環神經網絡組成。循環神經網絡(RNN,LSTM,GRU等)使用hidden states或者Attention機制作為他們的記憶功能,但是這種方法產生的記憶太小了,無法精確記錄一段話中所表達的全部內容,也就是在將輸入編碼成dense vectors的時候丟失了很多信息。因此,在模型中加入一系列的記憶單元,增強模型的記憶能力,便有了Memory Network。
2.1 Basic Memory Network
基本的Memory Network由Facebook在2014年的“Memory Networks”一文中提出。該模型主要由一個記憶數組m和I,G,O,R四個模塊。結構圖如下所示:
簡單來說,就是輸入的文本經過Input模塊編碼成向量,然后將其作為Generalization模塊的輸入,該模塊根據輸入的向量對memory進行讀寫操作,即對記憶進行更新。然后Output模塊會根據Question(也會進過Input模塊進行編碼)對memory的內容進行權重處理,將記憶按照與Question的相關程度進行組合得到輸出向量,最終Response模塊根據輸出向量編碼生成一個自然語言的答案出來。各模塊作用如下:
有關記憶網絡的詳細原理,參考文章:https://zhuanlan.zhihu.com/p/29590286或者原論文:https://arxiv.org/pdf/1410.3916.pdf。
2.2 End to End Memory Network
End to End Memory Network是Memory Network的一個改進版本,可以進行端對端的學習。原文中介紹的網絡模型應用于QA任務。單層網絡的結構如下圖所示:
模型主要的參數包括A,B,C,W四個矩陣,其中A,B,C三個矩陣就是embedding矩陣,主要是將輸入文本和Question編碼成詞向量,W是最終的輸出矩陣。從上圖可以看出,對于輸入的句子s分別會使用A和C進行編碼得到Input和Output的記憶模塊,Input用來跟Question編碼得到的向量相乘得到每句話跟q的相關性,Output則與該相關性進行加權求和得到輸出向量。然后再加上q并傳入最終的輸出層。
進一步,我們可以使用多層的結構:
有關End2End Memory Network的詳細原理,可以參考文章:https://zhuanlan.zhihu.com/p/29679742和原論文:http://10.3.200.202/cache/11/03/papers.nips.cc/82b8c2ad3e5cde7cad659be2d37c251e/5846-end-to-end-memory-networks.pdf。
當然,也可以動手實現一個網絡結構,參考代碼:https://github.com/princewen/tensorflow_practice/tree/master/nlp/Basic-EEMN-Demo
3、協同記憶網絡原理
我們的協同記憶網絡CMN其實借鑒了End2End Memory Network的思路,我們先來看一下完整的網絡結構,隨后一步步進行介紹:
這里明確一點,我們的任務是預測用戶u對于物品i的評分。
3.1 User Embedding
首先,我們會有兩組用戶的Memory(其實就是Embedding),分別是M和C,M用于計算用戶之間關于某件物品i的相關性,C用于最終的輸出向量。我們還有一組物品的Memory(其實就是Embedding),我們稱作E。
對于預測用戶u對于物品i的評分。我們首先會得到歷史上所有跟物品i有反饋的用戶集合,我們稱作N(i)。接下來,我們要計算目標用戶u和N(i)中每個用戶的相關性,基于下面的公式:
其中,mu,mv分別是用戶u和用戶v在M中的相關記憶。ei代表物品i在E中的相關記憶。
3.2 Neighborhood Attention
對于上一步計算出的相關性,我們需要通過一個softmax操作轉換為和為1的權重向量:
同時,根據得到的權重向量,我們根據下面的式子得到輸出向量:
其中,cv代表用戶v在C中的相關記憶。
3.3 Output Module
最終的預測輸出為:
可以看到,在上面的式子中,括號中的第一項是用戶的記憶mu和物品的記憶ei進行的element-wise 相乘操作,這相當于矩陣分解的思想,即考慮了全局的信息。第二項相當于是按照基于鄰域的思路得到的一個輸出向量,即考慮了局部的相關用戶的信息。最終經過激活函數φ和輸出層得到最終的預測評分。因此,CMN不僅考慮了全局的結構信息,還考慮了局部的相關用戶的信息。
3.4 Multiple Hops
CMN模型可以擴展為多層。在每一層,我們的記憶是不變的,變化的主要是權重向量。每一層的權重向量計算公式如下:
這里冒出了一個zhui,初始的z為:
那么這就跟我們單層的CMN網絡中的計算方式是一樣的,因為內積的計算是符合乘法分配律的。
接下來每一層的z,計算公式如下:
3.5 Parameter Estimation
論文中CMN網絡采取的是一個pair-wise的方式,訓練時每次輸入一個正樣本得到一個評分,輸入一個負樣本得到一個評分,我們希望正樣本的得分遠大于負樣本的得分。這種形式我們稱為Bayesian Personalized Ranking (BPR) optimization criterion:
好了,模型的原理我們就介紹到這里了,接下來我們看一下代碼實現吧。
4、CMN模型的tensorflow實現
本文的代碼參考地址為:https://github.com/tebesu/CollaborativeMemoryNetwork
代碼文件結構為:
該Demo中的部分神經網絡結構由dm-sonnet進行了封裝,可以通過 pip install dm-sonnet進行安裝,默認進行安裝的話,tensorflow的版本應該至少在1.8以上。
有關代碼的實現細節,本文就不再介紹了,感興趣的話,大家可以看一下這個Demo。
參考文獻
1、《End-To-End Memory Networks》:http://10.3.200.202/cache/11/03/papers.nips.cc/82b8c2ad3e5cde7cad659be2d37c251e/5846-end-to-end-memory-networks.pdf )
2、《MEMORY NETWORKS》:https://arxiv.org/pdf/1410.3916.pdf
3、https://zhuanlan.zhihu.com/c_129532277