推薦系統最早在亞馬遜的網站上應用,根據以往使用者的購買行為,推薦出購買某種產品同時可能購買的其他產品,國內做的不錯的噹噹網,有時候買書,它總能給我推薦出我感興趣的其他書來,也算是技術極大的促進了銷售。
一般的協同過濾演算法,首先是收集使用者對事物(產品)的評分情況,一種直接對某本書,或者某個歌曲打分,另種是隱性的打分,比如商務系統中,購買了表
示打2分,瀏覽了打1分,其他的0分。我比較看好隱性打分,因為直接打分需要使用者的參與程度比較高,很多網站都在內容頁中留一個打分的按鈕,從1~5選一
個,我可能喜歡這篇文章,可我哪裡知道我喜歡的程度是幾分啊,還要我去思考,而網站設計中一條很重要的原則是:Do not let me
think!,於是我就胡打一個分數或者不打,而隱性的打分則不同,只有你喜歡的圖書你才會購買,只有你喜歡的歌曲才會聽多次。
收集好使用者的打分之後,通過最近鄰搜尋到和某個事物或者某個人特徵或者興趣相近的其他事物或者人,最近鄰搜尋演算法一般是皮爾森相關係數(Person Correlation Coefficient)、餘弦相似性(Cosine-based Similarity)以及調整餘弦相似性(Adjusted Cosine Similarity)。關於餘弦定理在資料採礦中的應用,google黑白報有過介紹,可以參考數學之美 系列 12 - 餘弦定理和新聞的分類。
剩下的工作就是根據最近鄰集進行推薦了。
最近鄰集的運算相對來說成本比較高,尤其是大量資料的時候,今天和大家分享的是一種簡單高效的協同過濾演算法:Slope one
基本原理
| 使用者 |
對事物A打分 |
對事物B打分 |
| X |
3 |
4 |
| Y |
2 |
4 |
| Z |
4 |
? |
使用者Z對事物B的打分可能是多少呢?股票上有個說法是平均值可以掩蓋一切異常波動,所以股票上的各個技術指標收拾不同時間段的平均值的曲線圖或者柱
狀圖等。同樣的,Slope one演算法也認為:平均值也可以代替某兩個未知個體之間的打分差異,事物A對事物B的平均很差是:((3 - 4) +
(2 - 4)) / 2 = -1.5,也就是說人們對事物B的打分一般比事物A的打分要高1.5,於是Slope
one演算法就猜測Z對事物B的打分是4 + 1.5 = 5.5
是不是非常的簡單?
加權演算法
有n個人對事物A和事物B打分了,R(A->B)表示這n個人對A和對B打分的平均差(A-B),有m個人對事物B和事物C打分
了,R(C->B)表示這m個人對C和對B打分的平均差(C-B),注意都是平均差而不是平方差,現在某個使用者對A的打分是ra,對C的打分是
rc,那麼A對B的打分可能是:
rb = (n * (ra - R(A->B)) + m * (rc - R(C->B)))/(m+n)
開源的Slope one的程式包
- Python
http://www.serpentine.com/blog/2006/12/12/collaborative-filtering-made-easy/
- Java
http://taste.sourceforge.net/
http://www.daniel-lemire.com/fr/documents/publications/SlopeOne.java
http://www.nongnu.org/cofi/
- PHP
http://sourceforge.net/projects/vogoo
http://www.drupal.org/project/cre
http://www.daniel-lemire.com/fr/documents/publications/webpaper.txt Slope one演算法作者寫的,簡單明了,強烈推薦。
- Erlang
http://chlorophil.blogspot.com/2007/06/collaborative-filtering-weighted-slope.html
- C#
http://www.cnblogs.com/kuber/articles/SlopeOne_CSharp.html 國人寫的C#版本
- T-SQL
http://blog.charliezhu.com/2008/07/21/implementing-slope-one-in-t-sql/
還有一些其他語言的版本,請參考http://en.wikipedia.org/wiki/Slope_One,即將面世的,居於PHP & Mysql的Slope one演算法實現將會在http://code.google.com/p/openslopeone/開
源出來,主要最佳化的是海量資料以及分散式處理,目前在我的筆記本上(迅馳+1.5G記憶體),對440W打分記錄進行測試,單一線程,3小時47分處理完。
速度還算是不錯了,最近工作實在太忙了,等我整理好會開源出來放在上面的地址。過幾天會有一篇我的演算法的詳細介紹,盼諸位批評指正,共同學習,共同進步。