一文系統搞懂協同推薦算法(二)

筆者是一個癡迷於挖掘數據中的價值的學習人,希望在平日的工作學習中,挖掘數據的價值,找尋數據的祕密,筆者認爲,數據的價值不僅僅只體現在企業中,個人也可以體會到數據的魅力,用技術力量探索行爲密碼,讓大數據助跑每一個人,歡迎直筒們關注我的公衆號,大家一起討論數據中的那些有趣的事情。

我的公衆號爲:livandata

不知大家對推薦算法有沒有一個系統的瞭解,推薦本身的邏輯很簡單,就是需要找到用戶喜歡的物品,然後呈現到用戶的面前,這其實像是一個算法與用戶的博弈,當用戶到APP上的時候,留下一串足印,算法根據用戶的足印和基本信息推斷用戶來這裏想要做什麼?或者說想要去什麼地方?然後給他推薦他需要的東西。

推薦的基本結構基本上可以分成兩類:

1)基於協同理論的推薦算法:

如上文,協同理論就是找到相似的用戶/物品或者相似的標籤,然後根據交易歷史中用戶和物品的交互情況進行推薦。算法在進行過程中遇到各種問題,程序員用各種方法來解決這些問題,久而久之,延伸出了現在各種複雜的協同推薦模式。

常見的問題有:

    1.1)人工進行特徵工程的問題:

    1.2)運算量龐大的問題:

    1.3)特徵挖掘層次不足的問題:

    1.4)如何使用社交鏈的問題:

2)基於模型分類的推薦算法:

推薦從模型的角度理解可以看作是對用戶喜好的預測,即爲一個二分類的預測模型,根據用戶的行爲預測用戶對某個商品喜歡不喜歡,進而根據喜好進行推薦。

基於模型的推薦比較多的應用於點擊率預測,用戶是否會購買某個商品的預測,在主流思路中依然是以協同爲主。

下面我們延續上文的討論,在上面常見問題的基礎上深化我們對協同推薦的理解:

1、運算量龐大的問題:

協同推薦的一個常見問題就是運算量的問題,每一次的迭代需要對全部的用戶行爲和商品信息進行復盤,計算出最新的相似係數。用戶和商品量少的情況下還好說,可如果用戶超過一億,商品有上百萬個呢?這一情況下UV矩陣就會非常大,每運算一次都需要耗費很大的資源,而且數據存在較多的稀疏的問題,幾百萬的商品,大部分用戶點擊的只有十幾個,剩下的部分全都是零,極大的浪費運算資源。

所以,需要找尋一些方法來降低數據的運算,即常說的降維。

一提到降維這個詞,有沒有很熟悉,對:很多人想到PCA、SVD等等常規的降維方法,在推薦算法中也有對應的基於降維的推薦方式:

——基於矩陣分解的系統推薦:

基於矩陣的推薦算法是以SVD奇異值分解爲基礎進行的。

假設上圖爲用戶的評分矩陣,經過上文的講解,這個矩陣已經非常熟悉了吧,我們假設他現在有一億行一億列,那該如何降維呢?

我們在學習奇異值的時候,經常會聽到一句話:前10%的奇異值之和佔了全部奇異值之和的80%以上的比例。所以,我們只需要通過奇異值計算的方式找到前10%的奇異值k個,計算他對應的k個特徵向量,即可大規模的降低上面UV矩陣的計算資源。

經過SVD的運算得到m*k的新的矩陣,我們就可以用這一矩陣替代UV矩陣進行相似度計算了。

基於新的低階矩陣我們計算出用戶的相似度/物品相似度,然後再對相似用戶進行推薦,計算效率大大的提升。

這樣運算有兩個好處:

其一:減輕了線上存儲和計算的壓力;

其二:解決了矩陣稀疏的問題;

也有一個壞處:

SVD是減輕了UV矩陣的運算量,但是SVD自身的運算呢?

從一個矩陣拆分成三個矩陣,這本身就意味着巨大的運算量,所以,在平時工作中很少使用SVD,而是使用隱語義模型,隱語義模型與SVD不同,他把矩陣拆分成了兩個矩陣。

——ALS模式下隱語義推薦算法:

ALS是交替最小二乘法,主要是用來優化最小損失函數的。

即根據用戶評分矩陣A,用求最小損失函數的方法求解出兩個分解的參數矩陣:

K即爲隱含的因子個數。

對應的損失函數爲:

Cij即爲用戶偏愛某個商品的置信程度,交互次數多的權重就會增加。

這裏,協同過濾就成功轉化成了一個優化問題。

通過ALS計算出用戶因子矩陣P和物品因子矩陣Q。

雖然降低了運算量,但是對於大數據集,還是推薦使用spark進行計算。

ALS模式的優點在於能夠有效的解決過擬合的問題,同時對算法的可擴展性也有所提高。

2、特徵挖掘層次不足的問題:

雖然說矩陣分解的方法進行相似性計算已經非常成熟,但是,聰明的讀者也已經發現,矩陣分解只是針對矩陣進行的一次運算,對特徵的挖掘層次明顯不足,而且,矩陣也沒有用到用戶和物品本身的特性。

而深度學習中的稀疏自編碼模式可以有效的解決這兩個問題:

——稀疏自編碼模式下的推薦算法:

稀疏自編碼是用神經網絡的方式來壓縮原始物品的特徵向量,使物品的相似度運算能在較低緯度下進行。

如圖所示即爲稀疏自編碼的網絡結構,簡單來講,稀疏自編碼就是一個hw,b(x) = x的函數,設定神經網絡的輸入值和輸出值都是x,中間多個隱含層的節點數量小於輸入和輸出層的節點數量(輸入和輸出層的節點數量一樣多),對網絡進行訓練,輸出層使用softmax進行訓練,得到最後的隱含層爲輸出矩陣V,這一矩陣V即爲經過稀疏自編碼之後得到的物品的低維矩陣。

通常情況下,隱含層會有多層,以保證輸入層的數據得到充分的運算,也就解決了上面講的特徵挖掘層次不足的情況,同時網絡輸入的是物品的屬性信息,所以,第二個問題也得以解決。

假設一個物品的特性爲v1=(x1,x2,x3,x4,x5,x6),經過上面的模型運算之後,向量就會變成v1=(k1, k2, k3)。

在使用稀疏自編碼進行運算時有兩個比較常用的延伸思路,是在使用稀疏自編碼進行數據降維時頻繁使用的方法,如下:

1)添加隨機因子:

如果直接將輸入值看做輸出層,有可能使輸入層的數據直接穿透隱含層到達輸出層,起不到準確訓練的效果,此時可以在輸入層中加入一些混淆因子,使輸入和輸出層不完全一致,即避免了數據穿透的問題。

隨機因子應該是遠遠小於x的值,以保證攪亂一致性的同時不會引發x值變化。

2)用已知的X、Y值:

在多層隱含層的自編碼模式中有一種典型的方法是:棧式自編碼。

即已知X和Y的值,通過輸入X,輸出Y訓練多層隱含層,然後得到最後一個隱含層,作爲X的壓縮向量。

 

還是剛纔的假設:v1=(x1,x2,x3,x4,x5,x6),輸出層的標籤爲Y=(y1、y2、y3),經過兩層隱含層的計算得到v1 = (k1, k2, k3, k4),這一特徵向量涵蓋了輸入端的物品的用戶評分屬性和輸出端的物品分類標籤屬性,是一個綜合性的向量。基於這樣的數據進行物品相似度計算能獲得較好的效果。

寫到這裏,大家有沒有發現,稀疏自編碼並沒有用上面的評分表,而是使用了基於內容的一些思路,推薦的協同邏輯發生了變化。所以,推薦本身不是基於一個固定不變的思路進行優化的,有時會不停的跳躍,直到找到較好的方法。

3、如何使用社交鏈的問題:

不管什麼樣的APP都希望能夠使用到社交網絡的信息,因爲社交網絡本身就是一個計算良好的U-U矩陣,能夠更準確的表示出用戶的相似度。

社交網絡主要有兩種模式:興趣圖譜和社交圖譜。

導致網絡中會有三種常見的社交數據:

1)雙向確認的社交數據,比如微信,A<——>B;

2)單向關注的社交數據,比如微博,A——>B;

3)基於社區的社交數據,比如知乎,A——>社區<——B;

在推薦算法中,社交網絡最常用的用法還是與協同推薦結合使用,我們先看一個社交網絡的圖片:

從圖中可以看出,B有兩人關注(A,E),有一人是好友(F),B購買了兩個物品(i1,i4)。上圖爲社交網絡的一個完整的圖形,我們的推薦也是基於這一圖形進行的。

在社交網絡下,計算好友相似度的幾種方法:

1)對於用戶u和v,可以使用共同好友比例計算相似度:

Out(u)是用戶u指向其他好友的數量,|out(u)∩out(v)|是用戶u和v共同指向好友的數量。

2)使用共同被關注的用戶數量計算用戶相似度:

In(u)是指用戶被其他用戶指向的數量。

3)用戶u關注的用戶中,有多大比例也關注了用戶v:

這一公式含有了熱門懲罰因子。

有了基於網絡的數據,我們再結合前面提到的協同理論,會得到一個綜合的用戶相似度的分數:

基於上面的數據,我們可以再使用基於用戶協同的推薦方法,計算得到推薦結果。

上面是基於社交網絡最直接的計算方法,通過1、2兩部分的描述,聰明的讀者是不是會有一個疑問呢?

對的

運算量的問題、特徵挖掘層次的問題。

基於社交網絡的推薦自然也會遇到這兩個問題,那麼,該如何解決呢?

我們基於深度學習的思路,對這個問題進行了解答,主要是使用了network embedding的方法,計算出每個用戶的一個座標,用這個座標表示用戶在這個圖中的位置,當進行用戶相似度計算時,只需要通過這些座標進行計算就可以了。

這個套路有沒有很熟悉,沒錯,就是前面的降維,同樣的思維又在社交網絡的場景下重演了,不過依然有效,node2vec是network embedding中的一個常用方法,下面我們簡單介紹一下,如有興趣,可以百度一些論文,深度瞭解:

——node2vec在社交網絡推薦中的應用:

這一方法主要分兩個步驟:

1)對網絡進行隨機遊走採樣,將採到的節點和上下文形成組合(random walk),推薦場景下隨機遊走添加了p和q兩個參數,以調節遊走過程中是深度優先還是廣度優先:

第一步:先選擇t作爲初始步,從t->v,在v的基礎上確定下一步的節點;

第二步:計算t與v之間的距離d,並以這個距離來計算遊走的概率a;

d=0,表示點往回走了,遊走概率爲1/p;

d>distincev-x的距離時,即接下來的點距離比上一步的距離近一點,則遊走概率爲1;

d<distincev-x的距離時,即接下來的點距離相對較遠,遊走概率爲1/q;

如果p>max(1,q),則1/p最小,則往回遊走的概率最小,則深度優先;

如果p<min(1,q),則1/p最大,則往回遊走的概率最大,則廣度優先;

第三步:遊走步數達到N步時,遊走停止,則結合上下文得出的序列便形成了。

如圖:

上面圖中,遊走的路徑爲:A-a-B-c。

2)用詞向量(word2vec)對上面的組合進行建模,得到網絡節點表達向量,即用戶向量:

將上面遊走產生的用戶序列添加到word2vec中,生成一個低維的用戶向量,以此來確定用戶的座標。

word2vec有兩種計算方式,主要是:Skip-gram和CBOW,如圖可知兩種的區別:

具體細節可以百度一下,展開的話估計又是一篇大文章了。

其實只要瞭解,這兩種方法都是用神經網絡的方式降維就可以了就是一個高級的PCA而已。

比如:輸入的是100維,輸出的是20維。

4、人工進行特徵推薦的問題:

上面我麼詳細講解了推薦系統中常見的一些問題,以及對應的解決方案,但是,有沒有人想更進一步呢?

必然是有的~

特徵工程一直被稱作是建模的基礎,這一基礎一直作爲數據從業人員的水平衡量儀,肚子裏有多少貨,從特徵工程中就可以知道了。

凡人都會有偏差,有沒有方法能夠儘可能的減少對人工特徵工程的依賴呢?

~有~

通過對數據的深度瞭解,我們可以根據用戶的特性採用一些模型組合的方式,儘量降低數據的人工特徵工程過程,輸入原始數據,比如: LR+DNN模型、DeepFM模型等,綜合深度學習在特徵方面的優勢,採用模型融合方式儘可能的降低了對人工特徵工程的依賴,但是在這裏要說一點,這裏只是減少了人工特徵工程,工作中人工部分是必不可少的。

下面我們介紹一下基於深度學習的推薦算法思路:

——LR+DNN模型:

LR模型的優點:簡單、可擴展、可解釋性強,在低階維度上效果比較明顯;

LR模型的不足:對不在訓練集中的特徵不具備泛化能力;

DNN模型的優點:對未出現的特徵存在一定的泛化能力,減輕特徵工程的壓力;

DNN模型的不足:很難學習低維的特徵,另外,客戶如果有明顯的偏好,對其他項都不感興趣時,模擬出來的效果不好,因爲DNN會對0項的特徵模擬出一些特徵值,進行相應的推薦(這個是DNN泛化能力的體現);

爲了解決特徵工程時組合深度不夠、人工特徵工程過多的問題,大家研究出了將兩個模型融合的方法:LR+DNN

一方面LR模型對低維度的特徵有較好的擬合效果,另一方面DNN模型對高維度的特徵有較好的擬合效果,同時兼顧了模型的廣度和深度,結構如圖:

https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581833789881&di=b8c09a4ba46936bb886a38a55fb34ed4&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180411%2F638eb97c9ac84108a5f0f2be412c8050.jpeg

從圖片我們可以看出,左側爲LR模型,右側爲DNN模型,將這兩個結構融合在一起,然後用統一的softmax函數進行輸出,就能形成一個同時具有記憶能力和泛化能力的模型。

——DeepFM模型:

除了上面的LR+DNN模型,DeepFM模型也是一個被廣泛應用的深度學習模型,這一模型的特點就是在學習user behavior背後的特徵組合,從而最大化優化推薦效果。

DeepFM是用FM和DNN融合而成的模型,其特性與上面模型有一定的相似之處,我們先介紹一下FM:

FM是對LR的一次升級,通常情況下,我們使用LR模型是假設LR中各個元素都是獨立的,比如x1和x2是相互獨立的,然後再進行運算,但是實際上x1和x2有可能存在交叉影響,即x1*x2對y值是有影響的,因此需要將x1*x2考慮在模型中。爲了解決特徵交叉的問題,大家發明了FM+DNN的結構,也就是DeepFM模型:

感覺這張圖已經被無數人引用,都已經不清楚了,不過這也說明了這個模型的重要性,左側是FM模型,右側是DNN模型,其對應的預測結果爲:

這個模型的特點有兩個:

其一:添加了Dense Embedding層,即兩個模型共享同一套輸入數據,這樣保證了數據的統一,提高了訓練效率,不需要額外的特徵工程,進一步減少了人工干預;

其二:模型將輸入數據分成多個field,在field的基礎上進行模型訓練,減少了訓練的運算量。

我們介紹一下field思想:

對於離散的特徵,我們通常的做法是採用全連接的方式輸入,但是,問題在於如果特徵過多,神經網絡中的參數會指數級上升,導致模型運算量過大,甚至訓練不成功。

如圖:

One-hot輸入:

50億個參數,是不是有些恐怖?

所以,大家想到了用field的方式,將輸入層進行一定程度上的組合隔離,組建一個個field,並將field輸入到Dense層,使維度壓縮到稠密向量中,如圖:

       這樣就減少了輸入數據的數量,避免全連接輸入。

       我們對模型進行一個細分了解:

       其一:FM部分:

輸入層的數據是one-hot之後的變量,每個x都會被分解成(0,0,0,0,1,0)樣式的向量,將這些向量concat成一個向量,即可完成輸入層輸入。

Dense層中的數據是Vij,每個field中的向量(Vi*j-1,Vi*j……Vi*j+n)即爲FM公式中的Vi。將輸入層中每個x轉化的one-hot向量分割成一個field,則每個field中都含有一個1,其他的元素都是0,x經過各個權重進入Dense層的過程,得到的是x*權重之和,而x此時只有一個1,其他都爲0,所以,Dense中實際上是保留了1的權重,即爲Vij。

       FM層中,一階求和的部分即爲one-hot向量中1的求和,因此,可以看到圖中輸入層的數據直接輸入到了FM部分,二階部分是對<Vi*Vj>xi*xj的計算,由於x都是1,所以這一公式實際上是對權重向量<Vi*Vj>的運算,所以看到圖中每兩個field輸入到一個乘運算節點中。

       經過上面一階和二階的運算,我們可以確定出FM的模型了,然後將FM的運算結果輸入到sigmoid函數中。

       上面即爲FM部分的講解,下面我們瞭解一下深度部分。

其二:深度部分:

輸入層的變化就不做描述了,和FM層是一致的,這也是這個模型的優勢——共享輸入。

經過Dense embedding之後,輸入數據變成了Vij表示的稠密向量,將這個稠密向量輸入到DNN的隱含層即可獲取高維度融合的特徵模型。

上面的描述大家是否清楚了呢?

經過上面的描述,大家是不是對推薦系統有一個深入的瞭解呢?

筆者在學習這部分內容的時候瞭解到,模型的構建過程中,如何建模用戶時序行爲並將這些行爲和要排序的item相關聯,是建模過程中的難點,用戶的每一次操作都是有目的的,多次的操作行爲會產生一定的時序,這個時序信息會不會給模型帶來正向的影響呢?我想這是肯定的。

在通過深度學習進行推薦時,形成embedding的過程需要將用戶操作的上下文作爲特徵信息填入其中,就是這個目的,比如用戶的觀看歷史數據、用戶搜索歷史數據等,這樣的思路就是添加上下文信息到用戶向量中,以完善用戶的向量信息。

u=f_DNN(user_info, context_info)

訓練中常用的模式有:

從圖中我們可以看出,模型的訓練需要融合儘量多的特徵數據。

好了,就寫到這裏吧~

算法本身還是有很多值得挖掘的東西的,筆者會盡力的將自己的思考結論逐步的分享出來,希望有機會與大家一起討論。

發佈了139 篇原創文章 · 獲贊 96 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章