推荐数据集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

下一篇,我们将介绍基于邻域的算法。

参考

推荐系统实战(一)--movieslens数据集简介

11-25 00:20