內容來源:《推薦系統實踐》
前面介紹了各種各樣的數據和基於這些數據的推薦算法。在實際系統中,前面幾章提到 的數據大都存在,因此如何設計一個真實的推薦系統處理不同的數據,根據不同的數據設計算法, 並將這些算法融合到一個系統當中是本章討論的主要問題。本章將首先介紹推薦系統的外圍架 構,然後介紹推薦系統的架構,並對架構中每個模塊的設計進行深入討論。
下圖表示了推薦系統和網站其 他系統的關係。一般來說,每個網站都會有一個UI系統,UI系統負責給用戶展示網頁並和用戶交 互。網站會通過日誌系統將用戶在UI上的各種各樣的行爲記錄到用戶行爲日誌中。日誌可能存儲 在內存緩存裏,也可能存儲在數據庫中,也可能存儲在文件系統中。而推薦系統通過分析用戶的 行爲日誌,給用戶生成推薦列表,最終展示到網站的界面上。
上面的結構可以看到,推薦系統要發揮強大的作用,除了推薦系統本身,主要還依賴於兩 個條件——界面展示和用戶行爲數據。如果我們看看目前流行的推薦系統界面,可以看到這些界面都有一些共性。
通過一定方式展示物品,主要包括物品的標題、縮略圖和介紹等。
很多推薦界面都提供了推薦理由,理由可以增加用戶對推薦結果的信任度。
推薦界面還需要提供一些按鈕讓用戶對推薦結果進行反饋,這樣才能讓推薦算法不斷改 善用戶的個性化推薦體驗
數據收集和存儲
個性化推薦算法依賴於用戶行爲數據,而在任何一個網站中都存在着各種各樣的用戶行爲數 據。那麼如何存取這些數據就是推薦系統需要解決的首要問題。下圖展示了一個假想的電子商 務網站上的典型用戶行爲數據。如表所示,從產生行爲的用戶角度看,有些行爲是隻有註冊用戶 才能產生的,而有些行爲是所有用戶都可以產生的。從規模上看,瀏覽網頁、搜索記錄的規模都 很大,因爲這種行爲所有用戶都能產生,而且平均每個用戶都會產生很多這些行爲。購買、收藏 行爲規模中等,因爲只有註冊用戶才能產生這種行爲,但購買行爲又是電商網站的主要行爲,所 以它們相對於評論來說規模更大,但相對於網頁瀏覽行爲來說規模要小得多,最後剩下的行爲是 註冊用戶裏的一小部分人才有的,所以規模不會很大。從實時存取的角度上看,購買、收藏、評 論、評分、分享等行爲都是需要實時存取的,因爲只要用戶有了這些行爲,界面上就需要體現出 來,比如用戶購買了商品後,用戶的個人購買列表中就應立即顯示用戶購買的商品。而有些行爲, 比如瀏覽網頁的行爲和搜索行爲並不需要實時存取。
按照前面數據的規模和是否需要實時存取,不同的行爲數據將被存儲在不同的媒介中。一般 來說,需要實時存取的數據存儲在數據庫和緩存中,而大規模的非實時地存取數據存儲在分佈式 文件系統(如HDFS)中。 數據能否實時存取在推薦系統中非常重要,因爲推薦系統的實時性主要依賴於能否實時拿到 用戶的新行爲。只有快速拿到大量用戶的新行爲,推薦系統才能夠實時地適應用戶當前的需求, 給用戶進行實時推薦。
推薦系統架構
根據上面的抽象,可以設計一種基於特徵的推薦系統架構。如下圖所示,當用戶到來之後, 推薦系統需要爲用戶生成特徵,然後對每個特徵找到和特徵相關的物品,從而最終生成用戶的推 薦列表。因而,推薦系統的核心任務就被拆解成兩部分,一個是如何爲給定用戶生成特徵,另一 個是如何根據特徵找到物品
用戶的特徵種類非常多,主要包括如下幾類:
人口統計學特徵 包括用戶的年齡、性別、國籍和民族等用戶在註冊時提供的信息。
用戶的行爲特徵 包括用戶瀏覽過什麼物品、收藏過什麼物品、給什麼物品打過什麼樣 的分數等用戶行爲相關的特徵。同時,用戶行爲從時間上也可以分爲用戶近期的行爲和 長期的行爲。
用戶的話題特徵 可以根據用戶的歷史行爲利用話題模型(topic model)將電視劇和電 影聚合成不同的話題,並且計算出每個用戶對什麼話題感興趣。比如用戶如果看了《葉 問》、《新龍門客棧》和《醉拳》,那麼可以認爲用戶對“香港武俠電影”這個話題感興趣。 推薦系統的推薦任務也有很多種,如下所示。
將最新加入的物品推薦給用戶。
將商業上需要宣傳的物品推薦給用戶。
給用戶推薦不同種類的物品,比如亞馬遜會推薦圖書、音像、電子產品和服裝等
給用戶混合推薦,有時需要將圖書和音像製品放到一個推薦列表中展示給用戶(如圖7-5 所示)。
對於不同的產品推薦不同新穎度的物品。比如在首頁給用戶展示比較熱門的推薦結果, 在推薦系統頁面給用戶展示長尾中的物品(如圖7-6所示)。
考慮到用戶訪問推薦系統的上下文,比如當你在豆瓣音樂找到“李宗盛”時,右側會有 一個鏈接告訴你可以在豆瓣電臺收聽“李宗盛”。單擊了這個鏈接後,豆瓣電臺給你推薦 的音樂就考慮了“李宗盛”這個上下文
如果要在一個系統中把上面提到的各種特徵和任務都統籌考慮,那麼系統將會非常複雜,而 且很難通過配置文件方便地配置不同特徵和任務的權重。因此,推薦系統需要由多個推薦引擎組 成,每個推薦引擎負責一類特徵和一種任務,而推薦系統的任務只是將推薦引擎的結果按照一定 權重或者優先級合併、排序然後返回。
這樣做還有兩個好處
可以方便地增加/刪除引擎,控制不同引擎對推薦結果的影響。對於絕大多數需求,只需 要通過不同的引擎組合實現。
可以實現推薦引擎級別的用戶反饋。每一個推薦引擎其實代表了一種推薦策略,而不同 的用戶可能喜歡不同的推薦策略。有些用戶可能喜歡利用他的年齡性別作出的推薦,有 些用戶可能比較喜歡看到新加入的和他興趣相關的視頻,有些用戶喜歡比較新穎的推薦, 有些用戶喜歡專注於一個鄰域的推薦,有些用戶喜歡多樣的推薦。我們可以將每一種策 略都設計成一個推薦引擎,然後通過分析用戶對推薦結果的反饋瞭解用戶比較喜歡哪些 引擎推薦出來的結果,從而對不同的用戶給出不同的引擎組合權重。 將推薦系統拆分成不同推薦引擎。
推薦引擎的架構
推薦引擎架構主要包括3部分:
該部分負責從數據庫或者緩存中拿到用戶行爲數據,通過分析不同行爲,生成當前用戶 的特徵向量。不過如果是使用非行爲特徵,就不需要使用行爲提取和分析模塊了。該模 塊的輸出是用戶特徵向量。
該部分負責將用戶的特徵向量通過特徵-物品相關矩陣轉化爲初始推薦物品列表。
該部分負責對初始的推薦列表進行過濾、排名等處理,從而生成最終的推薦結果
生成用戶特徵向量
一般來說,用戶的特徵包括兩種,一種是用戶的註冊信息中可以提取出來的,主要包括用戶 的人口統計學特徵。對於使用這種特徵的推薦引擎,如果內存夠,可以將存儲這些特徵的信息直 接緩存在內存中,在推薦時直接拿到用戶的特徵數據並生成特徵向量。除了這種特徵,另一種特 徵主要是從用戶的行爲中計算出來的,本節着重討論如何生成特徵。 一個特徵向量由特徵以及特徵的權重組成,在利用用戶行爲計算特徵向量時需要考慮以下 因素。
用戶行爲的種類 在一個網站中,用戶可以對物品產生很多不同種類的行爲。用戶可以 瀏覽物品、單擊物品的鏈接、收藏物品、給物品打分、購買物品、評論物品、給物品打 上不同的標籤、和好友分享物品、搜索不同的關鍵詞等。這些行爲都會對物品特徵的權 重產生影響,但不同行爲的影響不同,大多時候很難確定什麼行爲更加重要,一般的標 準就是用戶付出代價越大的行爲權重越高。比如,購買物品需要用戶掏錢,所以用戶一 定會三思而後行,因此購買行爲最爲重要。相反,瀏覽物品的網頁代價很小,所以這種 行爲對反映用戶的真實興趣的影響很小。
用戶行爲產生的時間 一般來說,用戶近期的行爲比較重要,而用戶很久之前的行爲相 對比較次要。因此,如果用戶最近購買過某一個物品,那麼這個物品對應的特徵將會具 有比較高的權重
用戶行爲的次數 有時用戶對一個物品會產生很多次行爲。比如用戶會聽一首歌很多次, 看一部電視劇的很多集等。因此用戶對同一個物品的同一種行爲發生的次數也反映了用 戶對物品的興趣,行爲次數多的物品對應的特徵權重越高。
物品的熱門程度 如果用戶對一個很熱門的物品產生了行爲,往往不能代表用戶的個性, 因爲用戶可能是在跟風,可能對該物品並沒有太大興趣,特別是在用戶對一個熱門物品 產生了偶爾幾次不重要的行爲(比如瀏覽行爲)時,就更說明用戶對這個物品可能沒有 什麼興趣,可能只是因爲這個物品的鏈接到處都是,很容易點到而已。反之,如果用戶 對一個不熱門的物品產生了行爲,就說明了用戶的個性需求。因此,推薦引擎在生成用 戶特徵時會加重不熱門物品對應的特徵的權重
特徵—物品相關推薦
在得到用戶的特徵向量後,我們可以根據離線的相關表得到初始的物品推薦列表。離線相關 表可以存儲在MySQL中:
對於每個特徵,我們可以在相關表中存儲和它最相關的N個物品的ID。 在線使用的特徵物品相關表一般都不止一張。以論文之間的相關表爲例,計算論文之間的 相關性既可以使用第3章提出的協同過濾算法(即如果兩篇論文的讀者重合度很大說明兩部電視 劇相似),也可以通過內容計算(比如有相同的作者、關鍵詞、相似的標題等)。即使是協同過濾, 也可以根據不同的用戶行爲數據得到不同的相關表。比如可以根據用戶的打分行爲計算論文之間 的相關性,也可以根據用戶的瀏覽行爲計算論文之間的相關性。總之,對於一個推薦引擎可以在 配置文件中配置很多相關表以及它們的權重,而在線服務在啓動時會將這些相關表按照配置的權 重相加,然後將最終的相關表保存在內存中,而在給用戶進行推薦時,用的已經是加權後的相關 表了。
從上面的架構圖可以看到,特徵—物品相關推薦模塊還可以接受一個候選物品集合。候選物 品集合的目的是保證推薦結果只包含候選物品集合中的物品。它的應用場合一般是產品需求希望 將某些類型的電視劇推薦給用戶。比如有些產品要求給用戶推薦最近一週加入的新物品,那麼候 選物品集合就包括最近一週新加的物品。
也許有讀者會奇怪,爲什麼不在過濾模塊中將候選集合外的電視劇過濾掉,而要在相關推薦 模塊中處理候選物品列表?這裏舉一個簡單的例子說明原因。首先,一般來說對於協同過濾算法 計算出的相關表,每個物品都會傾向於和比較熱門的物品具有較高的相似度。那麼假設用戶購買 過物品A,候選列表中包含了物品B,A和B相關,但A比B熱門。那麼,一般情況下,B在A的相 關物品列表中會排在靠後的位置(假設排在第10名),而A在B的相關物品列表中會排在靠前的位置(假設排在第1名)。那麼,如果推薦算法是給用戶推薦和A最相關的5部電視劇,那麼B就不會 出現在用戶的推薦列表中。但是,如果算法在給定候選列表時會用一種不同的方式進行推薦,比 如如果用戶看過和B最相關的5部電視劇中的某一部,就將B推薦給用戶,那麼這種情況下B就出 現在推薦列表中了。
一般來說,如果需要在一個小的候選物品集合中給用戶推薦物品,那麼可以考慮上述方法。 但如果是要在一個很大的候選物品集合中給用戶推薦物品,那麼可以考慮直接在初始推薦列表中 過濾掉不在候選物品集合中物品的方法。 特徵—物品相關推薦模塊除了給用戶返回物品推薦列表,還需要給推薦列表中的每個推薦結 果產生一個解釋列表,表明這個物品是因爲哪些特徵推薦出來的。下面的代碼給出了相關推薦模 塊的大體工作流程:
def RecommendationCore(features, related_table):
ret = dict()
for fid, fweight in features.items()
for item, sim in related_table[fid].items():
ret[item].weight += sim * fweight
ret[item].reason[fid] = sim * fweight
return ret
過濾模塊
在得到初步的推薦列表後,還不能把這個列表展現給用戶,首先需要按照產品需求對結果進 行過濾,過濾掉那些不符合要求的物品。一般來說,過濾模塊會過濾掉以下物品。
用戶已經產生過行爲物品 因爲推薦系統的目的是幫助用戶發現物品,因此沒必要給用 戶推薦他已經知道的物品,這樣可以保證推薦結果的新穎性。
候選物品以外的物品 候選物品集合一般有兩個來源,一個是產品需求。比如在首頁可 能要求將新加入的物品推薦給用戶,因此需要在過濾模塊中過濾掉不滿足這一條件的物 品。另一個來源是用戶自己的選擇,比如用戶選擇了某一個價格區間,只希望看到這個 價格區間內的物品,那麼過濾模塊需要過濾掉不滿足用戶需求的物品。
某些質量很差的物品 爲了提高用戶的體驗,推薦系統需要給用戶推薦質量好的物品, 那麼對於一些絕大多數用戶評論都很差的物品,推薦系統需要過濾掉。這種過濾一般以 用戶的歷史評分爲依據,比如過濾掉平均分在2分以下的物品。
排名模塊
經過過濾後的推薦結果直接展示給用戶一般也沒有問題,但如果對它們進行一些排名,則可 以更好地提升用戶滿意度,一般排名模塊需要包括很多不同的子模塊,下面將對不同的模塊分別 加以介紹。
1. 新穎性排名
新穎性排名模塊的目的是給用戶儘量推薦他們不知道的、長尾中的物品。雖然前面的過濾模塊已經過濾掉了用戶曾經有過行爲的物品,保證了一定程度的新穎性,但是用戶在當前網站對某 個物品沒有行爲並不代表用戶不知道這個物品,比如用戶可能已經在別的途徑知道這個物品了。 要準確瞭解用戶是否已經知道某個物品是非常困難的,因此我們只能通過某種近似的方式知 道,比如對推薦結果中熱門的物品進行降權,比如使用如下公式:
不過,要實現推薦結果的新穎性,僅僅在最後對熱門物品進行降權是不夠的,而應在推薦引 擎的各個部分考慮新穎性問題。 本章提到的推薦系統架構主要是基於物品的推薦算法的,因此可以回顧一下基於物品的推薦 算法的基本公式:
此外,也可以引入內容相似度矩陣,因爲內容相似度矩陣中和每個物品相似的物品都不是很 熱門,所以引入內容相似度矩陣也能夠提高最終推薦結果的新穎度
多樣性
多樣性也是推薦系統的重要指標之一。增加多樣性可以讓推薦結果覆蓋儘可能多的用戶興 趣。當然,這裏需要指出的是提高多樣性並不是時時刻刻都很好。比如在個性化網絡電臺中,因爲用戶某一固定時刻的興趣是固定的,所以不希望聽到不同曲風的歌曲,儘管這些曲風可能都是 用戶之前表示喜歡的。
不過,本節主要討論如果要提高多樣性,應該怎麼提高第一種提高多樣性的方法是將推薦結果按照某種物品的內容屬性分成幾類,然後在每個類中 都選擇該類中排名最高的物品組合成最終的推薦列表。比如,如果是電影,可以按照電影的類別 (愛情片、動作片、科幻片等)對推薦結果中的電影分類,然後每種類別都選出幾部電影組成最 終的推薦結果。 這種方法的好處是比較簡單直觀,但這種方法也有嚴重的缺點。首先,選擇什麼樣的內容屬 性進行分類對結果的影響很大。其次,就算選擇了某種類別,但物品是否屬於某個類別是編輯確 定的,並不一定能夠得到用戶的公認。比如成龍的電影,有人認爲是功夫片,有人認爲是喜劇片, 不同人看法不一。
因此,第二種提高推薦結果多樣性的方法是控制不同推薦結果的推薦理由出現的次數。本章 提出的推薦系統對於每個推薦出來的物品都有一個推薦理由,這個推薦理由一般是產生推薦結果 的重要特徵。那麼,要提高推薦結果的多樣性,就需要讓推薦結果儘量來自不同的特徵,具有不 同的推薦理由,而不是所有的推薦結果都對應一個理由。 下面的代碼根據推薦理由增加推薦結果的多樣性,這裏輸入的recommendations是按照權 重從大到小排序的,程序中每次拿出一個推薦結果,如果這個結果已經被用過了,就會對推薦結 果的權重除以2降權(這裏具體除以幾可以在實際應用中自己調整),最終將推薦結果重新按照權 重從大到小排序。
def ReasonDiversity(recommendations):
reasons = set()
for i in recommendations:
if i.reason in reasons:
i.weight /= 2
reasons.add(i.reason)
recommendations = sortByWeight(recommendations)
時間多樣性
時間多樣性主要是爲了保證用戶不要每天來推薦系統都看到同樣的推薦結果。提高推薦系統的時間多樣性要從兩個地方着手。首先要保證推薦系統的實時性,在用戶有 新行爲時實時調整推薦結果以滿足用戶最近的需求。這一點,在本章的推薦系統設計中已經考慮 到了。如果用戶有實時行爲發生,那麼行爲提取和分析模塊就能實時拿到行爲數據並轉化爲新的 特徵,然後經過特徵-物品相關模塊轉換成和新特徵最相關的物品,因而推薦列表中就立即反應 了用戶最新行爲的影響。
提高推薦結果多樣性的第二個方面是要在用戶沒有新的行爲時,也要保 證推薦結果每天都有變化。要實現這一點,只能通過如下方式。
記錄用戶每次登陸推薦系統看到的推薦結果。
將這些結果發回日誌系統。這種數據不需要實時存儲,只要能保證小於一天的延時就足 夠了。
在用戶登錄時拿到用戶昨天及之前看過的推薦結果列表,從當前推薦結果中將用戶已經 看到的推薦結果降權。
用戶反饋
排名模塊最重要的部分就是用戶反饋模塊。用戶反饋模塊主要通過分析用戶之前和推薦結果 的交互日誌,預測用戶會對什麼樣的推薦結果比較感興趣。 如果推薦系統的目標是提高用戶對推薦結果的點擊率,那麼可以利用點擊模型(click model) 預測用戶是否會點擊推薦結果。點擊模型在很多領域得到了廣泛應用,比如搜索結果的點擊預測
① 、 搜索廣告的點擊預測
② 、上下文廣告的點擊預測
③ 、點擊預測的主要問題是預測用戶看到某個推薦 結果時是否會點擊。
那麼要進行點擊率預測,首先需要提取特徵。在推薦系統的點擊率預測中可 以用如下特徵預測用戶u會不會點擊物品i:
用戶u相關的特徵,比如年齡、性別、活躍程度、之前有沒有點擊行爲;
物品i相關的特徵,比如流行度,平均分,內容屬性;
物品i在推薦列表中的位置。用戶的點擊和用戶界面的設計有很高的相關性,因此物品i在 推薦列表中的位置對預測用戶是否點擊很重要;
用戶之前是否點擊過和推薦物品i具有同樣推薦解釋的其他推薦結果;
用戶之前是否點擊過和推薦物品i來自同樣推薦引擎的其他推薦結果。 點擊模型需要離線計算好,在線將模型加載到內存中。爲了提高在線預測的效率,一般只可以使用線性模型。