點擊上方「樂視IUEI」可以訂閱哦!
說起推薦方面的技術,大家首先提到的往往是回歸、Learning to rank這些數據挖掘或者說機器學習方面的名詞,連協同過濾都少提了,可能是因為它太基礎。然而基礎的才是最重要的,實際上給推薦效果帶來巨大差異的,往往不是模型的複雜度,而是對數據的處理是否足夠完善。
本文就簡單探討一下在推薦系統中,在運用各種模型之前,要對數據進行哪些處理工作,以及這些處理工作中的常用方法。首先,被推薦的內容我們稱為Item,用大寫字母I來表示,比如在線視頻中的電影、閱讀App裡的圖書、電商網站裡的商品等等,都叫Item;第二呢,我們用U來表示用戶(User);第三,我們用T,也就是Tag(標籤),來描述I的屬性和U的喜好。
在實際應用中,I和U往往會有不同的標籤集合,比如用戶會有年齡、性別、籍貫、教育程度等標籤,視頻類的Item會有內容長度等信息,它們無法直接匹配。另外標籤之間也是會有層次關係的。本文不討論有層次關係的標籤,也不討論不能直接匹配的標籤如何使用的問題,這些問題等有機會再談。本應先說數據收集的工作,但由於在實踐中預處理環節往往會被忽視,這裡先說一下預處理要做的事情。第一是處理多義問題。比如「蘋果」這一個標籤,它可以是一種水果,也可以是手機的品牌。可以通過給標籤添加領域詞作為前綴的辦法來解決多義的問題。第二是同義問題,比如「C羅」和「克裡斯蒂亞諾·羅納爾多」就是指同一個人。對於同義詞,可以將它們映射到同一個ID上面,或者映射到一個最常用詞上面。第三要說的是過濾,在真實的數據裡面,髒數據的佔比往往會超乎想像,錯誤的或者無效的標籤會有很多。
可以使用詞表(也就是黑名單)、DF(Document Frequency)的方式實現標籤的過濾工作。DF的方法很簡單,就是統計一下每一個標籤在多少個內容裡面出現過,這個值就是DF值,把DF值過大或者過小的標籤過濾掉。最大和最小值要根據內容總數量和具體的應用場景來確定。
以上所說主要是數據的清理、規整化工作。實際上數據的集成、變換、歸約等操作也是預處理階段要做的事情,這些工作我們在下文中需要它們的地方再做介紹。
下面說一下數據收集的工作。
首先是內容本身的屬性數據,包括內容的生產時間、長度、質量度(比如視頻的清晰度、流暢度、畫面精美度等等);第二是內容的meta信息,這裡簡化一下,認為它們是標籤(T)的集合;第三是用戶的描述信息,比如年齡、性別、生活地域、教育程度、家庭組成等等;第四是用戶在內容上的行為數據,包括消費行為數據(購買商品、閱讀圖書、觀看視頻等等)、尋找行為數據(搜索、分類瀏覽、推薦結果的曝光和點擊等)、以及主動的興趣表達行為(收藏內容、分享內容、評分、評論、頂/踩等等);第五,還有一些其它數據,比如標籤的流行度等等,可以從搜尋引擎等站外數據源獲取到。
我們這裡做一下簡化,在數據收集階段,目標是獲得以下幾組數據。
1、<U, I, Score>,也就是用戶U對內容I的喜好程度(Score)。Score的取值根據用戶U對內容I的行為而定,這個跟業務有密切的關係,這裡不作細述。
2、<I, Score>,就是每一條Item本身的得分,一般用來體現Item的流行度、新鮮度、本身質量等指標的綜合得分。
3、<I, T, Weight>,就是對於一條內容I,它每一個標籤T的重要程度。
4、<U, T, Preference>,表示用戶U對標籤T的喜好程度。
本文的一下部分分別介紹上面的score、weight、preference都如何計算。本文建議這些Score、weight、或者preference的取值都歸一化到(0, 1)區間內,這樣能為各種計算提供方便。
重要的事情再說一遍,收集好數據之後別忘了做一下前面介紹過的預處理。在介紹各種權重或者得分的方法之前,先介紹一下sigmoid函數。這個函數是最常用的數值變換函數,同時會將結果值歸一化,將分布區間很大的數字映射到(0, 1)的區間之內。Sigmoid函數的表達式如下:結合下表可以看到,當x的取值小於-5或者大於5的時候,sigmoid(x)的值已經非常接近0或者1了,這意味著當x的取值在(-5, 5)區間之外的時候,x值的差異所帶來的函數值的差異將會非常微小。在使用sigmoid函數之前,一般會把要處理的值變換到(-N, N)這樣一個對稱的區間裡。結合不同的應用場景,一般我們取整數N值在5~10之間。變換的操作一般是這樣的:假設x的取值在集合A裡面,那麼我們取A的中值Me,那麼x到x』的變換這樣操作即可:其中MAX的取值一般是所有|(x-Me)|裡面最大的那個(絕對值)。不過真正操作的時候,要注意x裡面是不是存在個別特別大的值,根據個別特別大的x計算得來MAX是不合適的,一般會把它們去掉之後再算MAX。去掉奇異值之後,會導致最終的x』的取值有個別不在(-N, N)之內的情況,不過它們帶來的影響很小,可以忽略掉。
<U, I, Score>裡面的Score是對「用戶U對內容I的喜好程度」的一個客觀描述,可以通過直接的計算來獲取。舉個例子,假如U是一個視頻用戶,I是一部電影,那麼Score可以是用戶U對電影I的觀看時長t的sigmoid值。
說到這裡,要引入一個「空間」的概念。假如我們要用sigmoid(t)來計算用戶對視頻的喜好Score,那麼把電影和電視劇放一起就不是一個明智的做法。因為一部電影的時長一般在90~120分鐘之間,而一部20集的電視劇,假設一集就30分鐘,那麼也有600分鐘的總時長。這時候我們要分「空間」分別計算Score的取值,將同類內容放到同一個空間裡,不同內容放在不同的空間裡。
在實踐中,也有直接把<U, I, Score>裡的Score直接處理成0/1值的,用戶對內容喜歡就是1,不喜歡就是0,這時候可以抹去Score為0的記錄,剩下的<U, I, 1>元組裡面的1也可以省略,這樣每條記錄就剩下一個用戶ID和一個內容ID。<U, I, Score>的結果是推薦系統中多個後續操作步驟的基礎,包括協同過濾的計算、用戶建模等等。假如新來一位用戶,對其我們一無所知,那麼該給她推薦哪些內容?當然最熱門的內容是不錯的選擇,同時我們不能忽略了新內容,尤其對於新聞這樣的時效性非常強的應用領域來說。我們這裡介紹<I, Score>裡面Score的計算,它是內容Item本身流行度/質量分和時效性得分的綜合。我們這裡用P_Score表示流行度得分(可以認為流行度也包含了對內容質量的評價),用F_Score表示時效性得分(Freshness Score)。
對流行度得分P_Score的計算比較容易,在應用領域裡面收集最能代表用戶對內容喜好的指標值,再使用上面介紹過的sigmoid函數對該指標值進行處理即可。比如在視頻領域,用戶對視頻的觀看次數(Video View)就很有代表性。在新聞應用裡面,可以使用閱讀新聞的用戶數。這
裡還有兩個要點需要說明,其一是,在每個應用領域裡面都有多個指標能夠代表用戶對內容的喜好程度,比如視頻領域裡除了觀看次數,還可以用觀看時長、觀看人數、用戶評分、評論次數/人數等等,我們選擇最有代表性的一個即可。如果有興趣,可以研究一下把它們綜合使用(可以引入一些數據挖掘的手段),看是否比單一使用有更好的效果。要說明的第二點是,在收集用戶喜好的時候一定要注意數據的清洗。比如計算視頻的觀看次數的時候,會把觀看時長小於一定值的觀看給過濾掉,因為這說明用戶並不是真的要去觀看該視頻。
對F_Score的計算需要引入一些技巧。在介紹F_Score的計算方法之前,我們先看看為什麼要計算F_Score,以及應該如何用它。
首先,F_Score應該能夠一定程度上解決「新內容」的問題,也就是冷啟動問題的一種。新內容的問題就是我們對它們的流行度一無所知,也就是它們的P_Score還都是0。那麼這時候F_Score就要為其作出補償。其次,而當積累一定用戶流量之後,對於優質內容來說,它們的P_Score就會快速提升,這時候F_Score的值應該相應地下降。
對於那些P_Score沒有及時提升的內容來說,它們的整體得分就應該下降,從而在推薦排序中不斷下降,減少被曝光的機會。P_Score的取值是sigmoid的結果,分布在(0, 1)區間裡,對於新內容來說其值是0,這時候其F_Score的值應該是最大的,接近1。隨著時間的推移,F_Score的值應該下降,其下降速度應該與多數內容的P_Score值的上升速度相當。
基於互補的思路,我們使用加權求和的方式結合P_Score和F_Score來得到<I, Score>中的Score的取值:在實際應用中,時效性的過期是非常快的,熱門內容的流行度提升也非常快。因此常用指數函數來描述時效性,如下:其中w是我們給的一個權重,多數時候取1即可,a是底數,取值在(0, 1)區間,t是內容上線到目前為止過去的時間,根據不同場合以天或者小時為單位,取值範圍是[0,+∞)。其函數曲線如下圖所示。底數a的選擇比較關鍵。這我們定義一個半衰期T,來表示經過多長時間內容的時效性得分就減半,取a為T的倒數即可,即:a=1/T
其中T>1。可以結合主流內容的流行度得分隨著時間的上升速度來確定T,使得P_Score和F_Score結合之後的得分對於主流內容來說比較平穩的T就是好的選擇。
最後再解釋一下使用加法來結合P_Score和F_Score的思路,那就是把二者看做是互補的兩個值,在P_Score很小的時候F_Score取值較大,反之F_Score衰減到較小值的時候,優質內容的P_Score值已經得到了相應的提升。當然劣質內容在我們不知道真相時也會得到曝光機會,但是會隨著用戶的反饋而迅速衰減。
這裡P_Score和F_Score的結合不適宜用乘法。試想,一條內容在沒有流行度信息的時候和新鮮度衰減一定時間之後,二者的乘積都接近於0,那麼新內容和熱門老內容都得不到足夠的曝光機會。在這裡,加法更接近於邏輯運算裡的「或」操作,乘法更接近於邏輯運算裡的「與」操作。關於內容上面標籤的得分,也就是<I, T, Weight>裡面的Weight,分兩種情況簡單介紹。其一是對於文本內容來說,T的含義不是Tag,而是信息檢索領域裡的Term,有一種成熟的計算方式,就是tf-idf,請參考tf-idf的百科解釋。其二就是像音樂、視頻、商品等領域的標籤信息,這些標籤都是人工添加的,認為其權重都是1是最常見的做法。
關於用戶-標籤權重的計算,也就是<U, T, Preference>裡面的Preference,基本是基於用戶在內容上的行為來進行統計。統計方式很直接,如下面的公式所示:其中用戶在標籤t上的〖Preference〗_(u,t),就是對於用戶看過的每一個視頻上的Tag,將其Score進行求和。不過還是要將〖Preference〗_(u,t)的取值歸一化到(0, 1)區間內,這裡一般使用max-min標準化的方式,其函數表達式如下:假如推薦系統不再考慮其它模型,僅僅基於上文中介紹過的各種Score、Weight、Preference來進行個性化的內容推薦,我們需要設計一個公式,來計算對用戶U來說每一條候選推薦內容I的得分。
我們掌握的用戶興趣體現在用戶對標籤的喜好上面,即<U, T, Preference>,對於候選集裡每一條內容,可以用標籤匹配的方式計算用戶對該條內容的喜好程度:如果標籤在內容上的分布並不均勻,那麼這個計算方式總是會偏向於標籤豐富的內容。為了加強公平性可以適當地懲罰一下標籤豐富的內容的得分,這裡不再介紹具體的計算方法,有興趣的讀者可以參考信息檢索類的教材,比如《現代信息檢索》,裡面會介紹許多種文本匹配的算法及模型。
在計算得到〖Score〗_(U,i)之後,並不適合拿這個分數直接對候選對象進行排序,我們還需要解決一個問題,那就是將內容本身的得分體現在排序裡面。就好比你去在搜尋引擎上進行檢索,候選網頁裡可能存在跟檢索詞匹配度很高的網頁,但是它們的質量卻很差,作為排序最靠前的搜索結果並不合適。再比如我們要在一個電商網站裡做推薦,知道用戶近期在考慮買一部手機,但是手機有許多種,到底哪些該推薦到最前面呢?
將內容本身的得分與用戶對內容的偏好合適地結合起來能夠解決這個問題,這時候我們選擇乘法。這裡的乘法更接近邏輯運算裡的「與」操作,它能把用戶匹配度低的內容和質量分偏低的內容都從推薦結果裡去掉,留下用戶既喜歡、本身質量也比較好的內容。這個公式如下:其中0≤α,β≤1,且α+β=1。一般取α>β,更強調用戶喜好的重要性,比如α=2/3,β=1/3。[1]數據預處理,http://baike.baidu.com/view/2947416.htm[2] sigmoid函數,http://baike.baidu.com/view/1176976.htm[3] tf-idf,http://baike.baidu.com/view/1228847.htm樂視IUEI是一個技術交流平臺,將第一時間向行業展現樂視最新的技術成果、項目經驗與工作感悟。了解更多,請留下您的指紋。