最近在看《推薦系統(tǒng)實(shí)踐》這本書,對于其中 2.4.1 基于用戶的協(xié)同過濾算法和 2.4.2 基于物品的協(xié)同過濾算法進(jìn)行了簡易實(shí)現(xiàn)。
本文列舉了在算法實(shí)現(xiàn)過程中遇到的一些情況并做了猜想與解釋。
數(shù)據(jù)準(zhǔn)備
本實(shí)驗(yàn)采用的數(shù)據(jù)集來自于MovieLens。
基本原理
本實(shí)驗(yàn)將分別采用UserCF算法和ItemCF算法,目的是為了給用戶推薦電影,而不是預(yù)測用戶會給某部電影打多少分。因此,ratings.csv中的打分信息可以忽略。
先讀取ratings.csv中的數(shù)據(jù),再隨機(jī)將數(shù)據(jù)分為訓(xùn)練集Train與測試集Test。在訓(xùn)練集中獲取訓(xùn)練User之間的關(guān)聯(lián)信息UserSimilarity或者訓(xùn)練Item之間的關(guān)聯(lián)信息ItemSimilarity,并根據(jù)Similarity給測試用戶推薦新的電影。
Code
代碼已放在對應(yīng)Github上。
實(shí)驗(yàn)結(jié)果
UserCF
當(dāng)采用不同數(shù)量的相關(guān)用戶(K取值不同)的時候,推薦算法產(chǎn)生的precision、recall、coverage、popularity有著一定相關(guān)關(guān)系。時間花費(fèi)也相差較大。如下所示:
K precision recall coverage popularity time
10 16.00% 9.38% 6.79% 4.83 19.60
10 15.81% 9.31% 6.61% 4.83 19.38
10 15.64% 9.26% 6.76% 4.84 21.02
10 15.99% 9.42% 6.62% 4.84 21.14
10 16.26% 9.92% 6.51% 4.83 20.23
10 15.31% 9.10% 6.67% 4.84 20.06
10 15.04% 9.05% 6.58% 4.85 20.29
10 16.11% 9.52% 6.69% 4.84 20.50
average:
10 15.77% 9.37% 6.65% 4.84
K precision recall coverage popularity time
50 17.80% 10.44% 2.78% 5.12 73.39
50 17.23% 10.15% 2.82% 5.12 78.35
50 16.60% 9.83% 2.83% 5.13 80.17
50 17.89% 10.54% 2.75% 5.13 79.42
50 17.18% 10.48% 2.82% 5.12 80.98
50 17.03% 10.13% 2.87% 5.12 80.02
50 16.84% 10.14% 2.85% 5.12 85.77
50 17.43% 10.30% 2.97% 5.12 80.01
average:
50 17.25% 10.25% 2.84% 5.12
若K相同,使用User-IIF算法,則從實(shí)驗(yàn)結(jié)果中可以看到,在coverage上有了一定提升。K=10時,結(jié)果如下:
K precision recall coverage popularity time
10 16.21% 9.51% 7.70% 4.75 26.20
10 15.35% 9.04% 7.72% 4.77 25.82
10 15.56% 9.21% 7.92% 4.77 25.59
10 15.81% 9.31% 7.55% 4.77 25.51
10 16.27% 9.93% 7.56% 4.76 26.16
10 15.37% 9.14% 7.62% 4.77 25.66
10 14.66% 8.83% 7.66% 4.77 25.62
10 16.05% 9.49% 7.45% 4.77 27.94
average:
10 15.66% 9.31% 7.65% 4.77
ItemCF
在運(yùn)行ItemCF過程中,意外的發(fā)現(xiàn)程序耗時特別久,如下所示:
K precision recall coverage popularity time
10 15.42% 9.04% 7.28% 4.67 1587.82
與UserCF相比,除了time之外的數(shù)據(jù)相差都不大,而time則相差了60倍左右。
從數(shù)據(jù)集中分析,本數(shù)據(jù)集包含671個User,9125 個Item,Item / User = 13.60。
從代碼層面分析,在某同一數(shù)據(jù)集下,UserCF和ItemCF分別能得到以下結(jié)果(Similarity函數(shù)和Recommend函數(shù)均在只執(zhí)行一次的條件下測得數(shù)據(jù)):
| CF | Similarity函數(shù)中循環(huán)次數(shù) | Similarity函數(shù)運(yùn)行時間 | Recommend函數(shù)中循環(huán)次數(shù) | Recommend函數(shù)運(yùn)行時間 |
|---|---|---|---|---|
| UserCF | 5491318 | 1.721613 | 945 | 0.011548 |
| ItemCF | 58900317 | 35.749465 | 200 | 1.021870 |
| ItemCF/UserCF | 10.73 | 20.77 | 0.21 | 88.49 |
可以發(fā)現(xiàn),Similarity函數(shù)和Recommend函數(shù)的運(yùn)行時間和內(nèi)部循環(huán)次數(shù)并不十分相關(guān),尤其當(dāng)ItemCF的Recommend循環(huán)遠(yuǎn)小于UserCF的Recommend循環(huán)時,運(yùn)行時間卻要來的更大。
注意到這兩個函數(shù)內(nèi)部都額外構(gòu)建了dict,分別代表User_Items關(guān)系與Item_Users關(guān)系,且都實(shí)現(xiàn)了相關(guān)的find、sort操作,故函數(shù)運(yùn)行時間差異主要與不同Size的Dict的find、sort性能相關(guān)。