其中的第二章《Making Recommendations》討論了協(xié)作性過(guò)濾技術(shù)(Collaborative Filtering),通過(guò)搜尋一個(gè)很大的群體,從中找出與你趣味相似的人,然后把這些人喜愛(ài)的其他東西,聚合起來(lái),創(chuàng )建一個(gè)推薦的排行榜(譬如電影推薦,產(chǎn)品推薦等等)。書(shū)中使用了del.icio.us的數據和API,可惜他們最近更改了API,所以無(wú)法使用書(shū)中的代碼做練習。但想起了CSDN的網(wǎng)摘功能,花了點(diǎn)時(shí)間把大部分的網(wǎng)摘記錄爬了下來(lái)(感謝CSDN的曾登高提供其中幾個(gè)人的數據)。我把記錄都放在一個(gè)名叫Post的表里了,它包含URL(用戶(hù)保存的文章的地址),Title(用戶(hù)保存使用的標題),UserName(用戶(hù)名),PostDate(保存網(wǎng)址的日期)這些字段。
得到的數據集中包括3753個(gè)用戶(hù),不同的鏈接數為68304,最多的一個(gè)人保存了7519個(gè)鏈接,平均每個(gè)人保存了23個(gè)鏈接。保存人數最多的是這篇貼子,
鏈接的來(lái)源是這樣的,
| 網(wǎng)站 | 鏈接數 |
|---|---|
| community.csdn.net | 21770 |
| blog.csdn.net | 12260 |
| blog.donews.com | 1865 |
| topic.csdn.net | 1836 |
| news.csdn.net | 1526 |
| www.cnblogs.com | 1237 |
| book.csdn.net | 831 |
| dev.csdn.net | 810 |
| download.csdn.net | 773 |
| spaces.msn.com | 758 |
| tech.sina.com.cn | 719 |
| www.donews.net | 491 |
| blog.sina.com.cn | 438 |
| club.book.csdn.net | 378 |
| www.infoq.com | 336 |
前十位CSDN網(wǎng)站占了7個(gè),好像不是很健康啊,
言歸正傳,那么針對CSDN網(wǎng)摘記錄怎么來(lái)定義用戶(hù)間的相似性?作者在這一章里討論了歐幾里德距離和Pearson相似性公式,其他的公式可以參考《數據挖掘導論》一書(shū)2.4節中的討論(CSDN免費提供了幾個(gè)章節)。在這個(gè)練習中,我將采用Tanimoto系數來(lái)定義相似性(圖片來(lái)自原書(shū)網(wǎng)站),
在這里Na代表用戶(hù)a保存的所有鏈接數,Nb代表用戶(hù)b保存的所有鏈接數,Nc則代表用戶(hù)Na和Nb間共同擁有的鏈接數。譬如,如果我保存了10個(gè)鏈接,你保存了20個(gè)鏈接,我們共有的鏈接為5個(gè),那么我們間的相似性為5/(10+20-5)=0.2。
使用Tanimoto系數的的原因是對鏈接這樣要么有,要么無(wú)的二元性的數據感覺(jué)很直觀(guān),而且容易計算(用數據庫操作即可)。
先生成一個(gè)表,
create table RelatedUser (username1 nvarchar(50), username2 nvarchar(50), urlcount1 int, urlcount2 int, commoncount int, coeff decimal(18,16))
然后填充其中的數據,針對用戶(hù)做個(gè)cross product,然后更新共有的鏈接數以及各自的鏈接數,
insert into relateduser (username1, username2, commoncount)
select username1, username2, count(url)
from
(
select p1.username as username1, p2.username as username2, p1.url
from post p1, post p2
where p1.url=p2.url
and p1.username <> p2.username
) t
group by username1, username2
go
update relateduser set urlcount1 = ps.urlcount
from relateduser u
inner join (select count(*) urlcount, username from post group by username) ps
on u.username1 = ps.username
go
update relateduser set urlcount2 = ps.urlcount
from relateduser u
inner join (select count(*) urlcount, username from post group by username) ps
on u.username2 = ps.username
go
生成Tanimoto系數,
update relateduser set coeff = convert(decimal,commoncount)/(urlcount1+urlcount2-commoncount)
go
讓我們來(lái)看一下與用戶(hù)jiangtao相似的用戶(hù),
select username2, commoncount, coeff from relateduser where username1 = 'jiangtao' order by coeff desc
go
其中前十個(gè)為
| 用戶(hù)名 | 共有的鏈接數 | Tanimoto系數 |
|---|---|---|
| zdg | 78 | 0.017165493 |
| 94smart | 80 | 0.009725261 |
| rjchen | 14 | 0.009504413 |
| hcat1999 | 4 | 0.004561003 |
| waynehuge | 4 | 0.003910068 |
| grhunter | 4 | 0.003710575 |
| tq85 | 10 | 0.002983294 |
| tonywjd | 3 | 0.002811621 |
| flyfish10000 | 2 | 0.002538071 |
| bluebubble | 2 | 0.002427184 |
假如我們指定只有共有的鏈接數超過(guò)10個(gè)才算相似,那么很明顯,與jiangtao趣味相似的用戶(hù)依次為(難怪啊,恐怕生活中他們就是jiangtao的朋友),
zdg
94smart
rjchen
tq85
據此,我們可以向jiangtao推薦他還沒(méi)有讀過(guò)的文章,
select title,url from post where username in (
select top 10 username2 from relateduser
where username1 = 'jiangtao' and commoncount >=10
order by coeff desc
) and url not in (
select url from post where username = 'jiangtao')
order by postdate desc, title, url
其中前十篇為
“正略一品”系列之六:在美國研究草原上的狗尾巴??趙民 - 新浪BLOG
The Podium ''08 - Election Guide 2008 - MSN
卓越亞馬遜:WIKINOMICS維基經(jīng)濟:Management:Business & Investing 經(jīng)管與理財:進(jìn)口原版:圖書(shū):Don Tapscott
理念隨筆之八:換位思考,假如咱是莊家
微軟的.NET源代碼:可遠觀(guān)而不可褻玩也
TechMeme:聚合的力量
傳統媒體和新媒體的對決:Techmeme Leaderboard上線(xiàn)
Facebook開(kāi)放平臺完全解析
Google為何收購Jaiku而非Twitter?
Google首頁(yè)的CSS Sprite
這是基于用戶(hù)的過(guò)濾,還可以做基于item(這里是URL)的過(guò)濾??上?,因為URL數太多,在數據庫里對URL做cross product需要非常大的內存/硬盤(pán),可惜這個(gè)機器上的容量很小,所以只好放棄。
聯(lián)系客服