协同过滤算法
今天要講的主要內容是協同過濾,即Collaborative Filtering,簡稱CF。
Contents
1. 協同過濾的簡介
2. 協同過濾的核心
3. 協同過濾的實現
4. 協同過濾的應用
1. 協同過濾的簡介
關于協同過濾的一個最經典的例子就是看電影,有時候不知道哪一部電影是我們喜歡的或者評分比較高的,那
么通常的做法就是問問周圍的朋友,看看最近有什么好的電影推薦。在問的時候,都習慣于問跟自己口味差不
多的朋友,這就是協同過濾的核心思想。
協同過濾是在海量數據中挖掘出小部分與你品味類似的用戶,在協同過濾中,這些用戶成為鄰居,然后根據他
們喜歡的東西組織成一個排序的目錄推薦給你。所以就有如下兩個核心問題
(1)如何確定一個用戶是否與你有相似的品味?
(2)如何將鄰居們的喜好組織成一個排序目錄?
協同過濾算法的出現標志著推薦系統的產生,協同過濾算法包括基于用戶和基于物品的協同過濾算法。
2. 協同過濾的核心
要實現協同過濾,需要進行如下幾個步驟
(1)收集用戶偏好
(2)找到相似的用戶或者物品
(3)計算并推薦
收集用戶偏好
從用戶的行為和偏好中發現規律,并基于此進行推薦,所以如何收集用戶的偏好信息成為系統推薦效果最基礎
的決定因素。用戶有很多種方式向系統提供自己的偏好信息,比如:評分,投票,轉發,保存書簽,購買,點
擊流,頁面停留時間等等。
以上的用戶行為都是通用的,在實際推薦引擎設計中可以自己多添加一些特定的用戶行為,并用它們表示用戶
對物品的喜好程度。通常情況下,在一個推薦系統中,用戶行為都會多于一種,那么如何組合這些不同的用戶
行為呢 ?基本上有如下兩種方式
(1)將不同的行為分組
一般可以分為查看和購買,然后基于不同的用戶行為,計算不同用戶或者物品的相似度。類似與當當網或者
亞馬遜給出的“購買了該書的人還購買了”,“查看了該書的人還查看了”等等。
(2)不同行為產生的用戶喜好對它們進行加權
對不同行為產生的用戶喜好進行加權,然后求出用戶對物品的總體喜好。
好了,當我們收集好用戶的行為數據后,還要對數據進行預處理,最核心的工作就是減噪和歸一化。
減噪: 因為用戶數據在使用過程中可能存在大量噪音和誤操作,所以需要過濾掉這些噪音。
歸一化:不同行為數據的取值相差可能很好,例如用戶的查看數據肯定比購買數據大得多。通過歸一化,才能
使數據更加準確。
通過上述步驟的處理,就得到了一張二維表,其中一維是用戶列表,另一維是商品列表,值是用戶對商品的喜
好。還是以電影推薦為例,如下表
找到相似的用戶或物品
對用戶的行為分析得到用戶的喜好后,可以根據用戶的喜好計算相似用戶和物品,然后可以基于相似用戶或物
品進行推薦。這就是協同過濾中的兩個分支了,基于用戶的和基于物品的協同過濾。
關于相似度的計算有很多種方法,比如常用的余弦夾角,歐幾里德距離度量,皮爾遜相關系數等等。而如果采
用歐幾里德度量,那么可以用如下公式來表示相似度
在計算用戶之間的相似度時,是將一個用戶對所有物品的偏好作為一個向量,而在計算物品之間的相似度時,
是將所有用戶對某個物品的偏好作為一個向量。求出相似度后,接下來可以求相似鄰居了。
計算并推薦
在上面,我們求出了相鄰用戶和相鄰物品,接下來就應該進行推薦了。當然從這一步開始,分為兩方面,分別
是基于用戶的協同過濾和基于物品的協同過濾。我會分別介紹它們的原理
(1)基于用戶的協同過濾算法
在上面求相似鄰居的時候,通常是求出TOP K鄰居,然后根據鄰居的相似度權重以及它們對物品的偏好,
預測當前用戶沒有偏好的未涉及物品,計算得到一個排序的物品列表進行推薦。
(2)基于物品的協同過濾算法
跟上述的基于用戶的協同過濾算法類似,但它從物品本身,而不是用戶角度。比如喜歡物品A的用戶都喜
歡物品C,那么可以知道物品A與物品C的相似度很高,而用戶C喜歡物品A,那么可以推斷出用戶C也可能
喜歡物品C。如下圖
上面的相似度權重有時候需要加入懲罰因子,舉個例子,在日常生活中,我們每個人購買衛生紙的的頻率比
較高,但是不能說明這些用戶的興趣點相似,但是如果它們都買了照相機,那么就可以大致推出它們都是攝
影愛好者。所以像衛生紙這樣的物品在計算時,相似度權重需要加上懲罰因子或者干脆直接去掉這類數據。
適用場景
對于一個在線網站,用戶的數量往往超過物品的數量,同時物品數據相對穩定,因此計算物品的相似度不但
計算量小,同時不必頻繁更新。但是這種情況只適用于電子商務類型的網站,像新聞類,博客等這類網站的
系統推薦,情況往往是相反的,物品數量是海量的,而且頻繁更新。所以從算法復雜度角度來說,兩種算法
各有優勢。關于協同過濾的文章,可以參考這里:http://www.tuicool.com/articles/6vqyYfR
3. 協同過濾的實現
上面已經介紹了協同過濾的核心思想,現在就來實戰一下吧! 采用數據集如下
鏈接:http://grouplens.org/datasets/movielens/
這個數據集是很多用戶對各種電影的評分。接下來先采用Python實現基于用戶的協同過濾算法。
首先,我們需要以表格形式讀取數據,需要用到Texttable第三方包。安裝包如下鏈接
鏈接:https://pypi.python.org/pypi/texttable/
大致用法如下
更多方法的使用需要參考Textdtable的源文件texttable.py。接下來可以實現協同過濾算法了。
代碼:
[python] view plain copy
#-*-coding=utf-8-*-
importsys
importmath
fromtexttableimportTexttable
#計算余弦距離
defgetCosDist(user1,user2):
sum_x=0.0
sum_y=0.0
sum_xy=0.0
forkey1inuser1:
forkey2inuser2:
ifkey1[0]==key2[0]:
sum_x+=key1[1]*key1[1]
sum_y+=key2[1]*key2[1]
sum_xy+=key1[1]*key2[1]
ifsum_xy==0.0:
return0
demo=math.sqrt(sum_x*sum_y)
returnsum_xy/demo
#讀取文件,讀取以行為單位,每一行是列表里的一個元素
defreadFile(filename):
contents=[]
f=open(filename,"r")
contents=f.readlines()
f.close()
returncontents
#數據格式化為二維數組
defgetRatingInfo(ratings):
rates=[]
forlineinratings:
rate=line.split(" ")
rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
returnrates
#生成用戶評分數據結構
defgetUserScoreDataStructure(rates):
#userDict[2]=[(1,5),(4,2)]....表示用戶2對電影1的評分是5,對電影4的評分是2
userDict={}
itemUser={}
forkinrates:
user_rank=(k[1],k[2])
ifk[0]inuserDict:
userDict[k[0]].append(user_rank)
else:
userDict[k[0]]=[user_rank]
ifk[1]initemUser:
itemUser[k[1]].append(k[0])
else:
itemUser[k[1]]=[k[0]]
returnuserDict,itemUser
#計算與指定用戶最相近的鄰居
defgetNearestNeighbor(userId,userDict,itemUser):
neighbors=[]
foriteminuserDict[userId]:
forneighborinitemUser[item[0]]:
ifneighbor!=userIdandneighbornotinneighbors:
neighbors.append(neighbor)
neighbors_dist=[]
forneighborinneighbors:
dist=getCosDist(userDict[userId],userDict[neighbor])
neighbors_dist.append([dist,neighbor])
neighbors_dist.sort(reverse=True)
returnneighbors_dist
#使用UserFC進行推薦,輸入:文件名,用戶ID,鄰居數量
defrecommendByUserFC(filename,userId,k=5):
#讀取文件
contents=readFile(filename)
#文件格式數據轉化為二維數組
rates=getRatingInfo(contents)
#格式化成字典數據
userDict,itemUser=getUserScoreDataStructure(rates)
#找鄰居
neighbors=getNearestNeighbor(userId,userDict,itemUser)[:5]
#建立推薦字典
recommand_dict={}
forneighborinneighbors:
neighbor_user_id=neighbor[1]
movies=userDict[neighbor_user_id]
formovieinmovies:
ifmovie[0]notinrecommand_dict:
recommand_dict[movie[0]]=neighbor[0]
else:
recommand_dict[movie[0]]+=neighbor[0]
#建立推薦列表
recommand_list=[]
forkeyinrecommand_dict:
recommand_list.append([recommand_dict[key],key])
recommand_list.sort(reverse=True)
user_movies=[k[0]forkinuserDict[userId]]
return[k[1]forkinrecommand_list],user_movies,itemUser,neighbors
#獲取電影的列表
defgetMovieList(filename):
contents=readFile(filename)
movies_info={}
formovieincontents:
single_info=movie.split("|")
movies_info[int(single_info[0])]=single_info[1:]
returnmovies_info
#從這里開始運行
if__name__=='__main__':
reload(sys)
sys.setdefaultencoding('utf-8')
#獲取所有電影的列表
movies=getMovieList("u.item")
recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("u.data",50,80)
neighbors_id=[i[1]foriinneighbors]
table=Texttable()
table.set_deco(Texttable.HEADER)
table.set_cols_dtype(['t','t','t'])
table.set_cols_align(["l","l","l"])
rows=[]
rows.append([u"moviename",u"release",u"fromuserid"])
formovie_idinrecommend_list[:20]:
from_user=[]
foruser_idinitems_movie[movie_id]:
ifuser_idinneighbors_id:
from_user.append(user_id)
rows.append([movies[movie_id][0],movies[movie_id][1],""])
table.add_rows(rows)
printtable.draw()
推薦結果如下
接下來再來看一個題目,這個題目是2014年阿里的大數據競賽題目,描述可以參考如下鏈接
題目:http://102.alibaba.com/competition/addDiscovery/gameIntroduce.htm
題意:根據用戶在天貓的4個月的行為日志,建立用戶的品牌偏好,并預測他們在接下來的一個月內對品牌商品的
購買行為。開放的字段類型如下
解析:http://www.tuicool.com/articles/AN7Rf2
上面的是建立的簡單的模型,實際上在天貓,有基于行為簇的用戶偏好分析。
協同過濾資料
1. 推薦引擎算法
2. 開源推薦引擎框架
3. 協調過濾介紹
4. Slop one
5. 基于Map Reduce的協同過濾推薦算法的并行實現
6. 并行協同過濾推薦模型的研究
總結
- 上一篇: 汇编 shr 逻辑右移指令,shl
- 下一篇: 日产奇骏e-POWER将发:配备1.5T