推薦數據集MovieLens及評測
數據集簡介
MoiveLens是GroupLens Research收集並發布的關於電影評分的數據集,規模也比較大,為了讓我們的實驗快速有效的進行,我們選取了發布於2003年2月的 MovieLens 1M,這個數據集包含6000個用戶對4000個電影的一百萬個評分。這個數據集經常用來做推薦系統,機器學習算法的測試數據集。尤其在推薦系統領域,很多著名論文都是基於這個數據集的。數據集下載地址。
數據集格式
評分數據
在rating.dat文件當中,里面主要保存了每個用戶與對每一部電影的評分,數據的格式為:用戶標識::MovieID::評級::時間戳。
- 用戶id范圍在1到6040之間
- 電影id在1到3952之間
- 評分以五星為標准(只有全星)
- 時間戳以秒為單位表示,從epoch返回到time(2)
- 每個用戶至少有20個評分
我們簡單看一下是不是這樣
import pandas as pd
ratings = pd.read_csv('./MovieLens/ml-1m/ratings.dat', delimiter="::",header=None)
ratings.head(5)
輸出結果
0 1 2 3
0 1 1193 5 978300760
1 1 661 3 978302109
2 1 914 3 978301968
3 1 3408 4 978300275
4 1 2355 5 978824291
電影數據
我們再看一下電影數據movies.dat,看一下里面的內容, 數據格式為MovieID::電影名稱::電影分類
movies = pd.read_csv('./MovieLens/ml-1m/movies.dat', delimiter="::", header=None)
movies.head(5)
輸出結果:
0 1 2
0 1 Toy Story (1995) Animation|Children's|Comedy
1 2 Jumanji (1995) Adventure|Children's|Fantasy
2 3 Grumpier Old Men (1995) Comedy|Romance
3 4 Waiting to Exhale (1995) Comedy|Drama
4 5 Father of the Bride Part II (1995) Comedy
用戶數據
我們再看一下用戶數據users.dat,看一下里面的內容, 數據格式為用戶標識::性別::年齡::職業::郵編
users = pd.read_csv('./MovieLens/ml-1m/users.dat', delimiter="::", header=None)
users.head(5)
輸出結果:
0 1 2 3 4
0 1 F 1 10 48067
1 2 M 56 16 70072
2 3 M 25 15 55117
3 4 M 45 7 02460
4 5 M 25 20 55455
實驗設置
以上就是這個數據集所有包含的內容以及相應的含義了,相信通過上面的數據呈現也會對這個數據集大概有個印象。由於后面的算法主要介紹的是隱反饋數據集MoiveLens的TopN的推薦問題,因此忽略了評分記錄。
訓練設置
我們采用了N折交叉驗證的方式進行訓練,也就是將數據划分成M份,選取其中M-1份作為訓練集,選取其中的1份作為測試集。將M次實驗的評測指標的平均值作為算法測試結果。主要是為了防止算法發生過擬合。
import random
def SplitData(data, M, k, seed):
test = []
train = []
random.seed(seed)
for user, item in data:
if random.randint(0,M) == k:
test.append([user,item])
else:
train.append([user,item])
return train, test
評測設置
我們采用了召回率,精准率、覆蓋率以及新穎度作為主要的評測指標。之前評測指標的文章已經詳細介紹了這四種指標的含義以及推導,這里就給出詳細的實現的代碼。
召回率
def Recall(train, test, N):
hit = 0
all = 0
for user in train.keys():
tu = test[user]
rank = GetRecommendation(user, N)
for item, pui in rank:
if item in tu:
hit += 1
all += len(tu)
return hit / (all * 1.0)
精准率
def Precision(train, test, N):
hit = 0
all = 0
for user in train.keys():
tu = test[user]
rank = GetRecommendation(user, N)
for item, pui in rank:
if item in tu:
hit += 1
all += N
return hit / (all * 1.0)
覆蓋率
def Coverage(train, test, N):
recommend_items = set()
all_items = set()
for user in train.keys():
for item in train[user].keys():
all_items.add(item)
rank = GetRecommendation(user, N)
for item, pui in rank:
recommend_items.add(item)
return len(recommend_items) / (len(all_items) * 1.0)
新穎度
計算平均流行度時對每個物品的流行度取對數,這是因為物品的流行度分布滿足長尾分布,在取對數后,流行度的平均值更加穩定。
def Popularity(train, test, N):
item_popularity = dict()
for user, items in train.items():
for item in items.keys():
if item not in item_popularity:
item_popularity[item] = 0
item_popularity[item] += 1
ret = 0
n = 0
for user in train.keys():
rank = GetRecommendation(user, N)
for item, pui in rank:
ret += math.log(1 + item_popularity[item])
n += 1
ret /= n * 1.0
return ret
下一篇,我們將介紹基於鄰域的算法。