一、前言

从0构建AI推荐系统好久没继续深入研究了,一方面因为工作较忙,另一方面在准备task任务系列,从0开始一步步完成简单框架的搭建与应用。最近看到一篇文件介绍电影推荐系统,感觉非常有意思,抽半天的时间动手实践了一下,本文记录学习电影推荐系统的全过程。

本文完整代码已经上传至GitHub:简单的电影推荐系统

二、相关环境介绍

编程语言:python

编辑器:pycharm

第三方库:pandas、numpy、sklearn

数据集:https://grouplens.org/datasets/movielens/     ml-100k.zip (size: 5 MB, checksum)

注:

1.  Scikit-learn,简称sklearn,一个用于Python编程语言的免费软件机器学习库,支持分类、回归、降维和聚类四大机器学习算法,包含特征提取、数据处理和模型评估三大模块,支持k均值、支持向量机、随机森林、梯度增强等常见算法。

     另外,由于sklearn建立在NumPy、Scipy和matplotlib库基础上,利用这几大模块的优势,可以大大提高机器学习的效率。sklearn拥有着完善的文档,上手容易,具有着丰富的API,在学术界颇受欢迎。同时sklearn内置了大量数据集,节省了获取和整理数据集的时间。

2. 本文使用的数据集较少且时间较早,但可以用来学习与练手,换作别的数据集后,实现的推荐方式大同小异。

三、构建电影推荐系统

3.1 推荐系统简介

简介:使用推荐算法进行数据挖掘,发现用户可能需要的商品。

推荐系统一般由以下三部分构成:

1. 基础数据部分(数据的质量决定推荐系统的上限,各种推荐算法无限逼近这个上限)

2. 推荐算法系统(一般由多个算法组成的推荐模型)

3. 前端展示(直观、高效的展示效果往往更能引人入胜、说明问题)

常见的推荐算法包括以下:

1. 基于流行度的推荐算法(按热门推荐)

2. 协同过滤算法

         基于用户的协同过滤算法(推荐和你类似的人喜欢的商品)

         基于商品的协同过滤算法(推荐喜欢这个商品的人也喜欢的商品)

3. 基于内容的过滤算法(词权、word2vec、聚类)

4. 基于模型的推荐算法(多种机器学习算法)

5. 基于矩阵分解的推荐算法(LFM隐语义模型)

6. 混合算法(结合多种推荐算法)

3.2 数据预处理

在数据集中,主要用到三种数据:

u.user:用户信息表(包括用户ID,年龄,性别,职业,邮编)

u.data:电影评分表(包括用户ID,电影ID,评分值,评分时间戳)

u.item:电影信息表(包括电影ID,电影名,上映时间,网址,电影类型)

采用pandas.read_csv()方法读取三种数据,并对应别设定每列的名称。

def init():
    '''
    初始化,读入文件
    :return: 用户表,评分表,电影明细表
    '''
    user_file = "E:\\ZX_relatedResources\\recommendation_movie_ml-100k\\u.user"
    data_file = "E:\\ZX_relatedResources\\recommendation_movie_ml-100k\\u.data"
    item_file = "E:\\ZX_relatedResources\\recommendation_movie_ml-100k\\u.item"

    u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
    users = pd.read_csv(user_file, sep="|", names=u_cols, encoding='latin-1')

    r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp']
    ratings = pd.read_csv(data_file, sep='\t', names=r_cols,encoding='latin-1')

    i_cols = ['movie_id', 'movie_title' ,'release date','video release date', 'IMDb URL', 'unknown',
              'Action', 'Adventure', 'Animation', 'Children\'s', 'Comedy', 'Crime', 'Documentary',
              'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi',
              'Thriller', 'War', 'Western']
    items = pd.read_csv(item_file, sep='|', names=i_cols, encoding='latin-1')
    return users, ratings, items

3.3 构造用户电影矩阵

这一步主要是构造一个矩阵,每一行代表一个用户,每一列代表一部电影,用户与电影对应的矩阵元素则是用户对该电影的评分。

def constructUserMovieMatrix(users, ratings):
    '''
    构造用户-电影矩阵
    :param users: 用户表
    :param ratings: 打分表
    :return: 用户对电影评分的矩阵
    '''
    num_users = users.user_id.unique().shape[0]   #用户数
    num_items = ratings.movie_id.unique().shape[0]   #电影总数
    data_matrix = np.zeros((num_users, num_items))
    for line in ratings.itertuples():
        data_matrix[line[1]-1, line[2]-1] = line[3]
    return data_matrix

执行结果:

注:

  1. unique()方法去重;
  2. Shape[0] 返回表示DataFrame维度的元组;
  3. line 的内容示例如下:  Pandas(Index=0, user_id=196, movie_id=242, rating=3, unix_timestamp=881250949)

         由于每行数据从1开始,存入下标为0的矩阵时要 -1。

3.4 构建电影之间相似度矩阵

采用计算余弦相似度的方式,计算电影之间的相似度矩阵。

def calculationSimilarity(data_matrix):
    '''
    转置计算电影之间相似度矩阵,不转置计算用户之间相似度矩阵
    :param data_matrix: 评分矩阵
    :return: 电影之间的相似度矩阵
    '''
    user_similarity = cosine_similarity(data_matrix, dense_output=True)
    item_similarity = cosine_similarity(data_matrix.T, dense_output=True)
    return item_similarity

注:转置是计算电影之间的相似度矩阵,不转置则计算用户之间的相似度矩阵!!

执行结果:

3.5 计算推荐电影

利用电影数据集中电影的相似程度,输入一部电影名或部分电影名(主要利用contains()方法),可以返回相似电影的电影名、相似度、平均评分、评分数。

def rec_sys(items,ratings, item_similarity, keywords, k):
    '''
    推荐系统
    :param items: 电影明细表
    :param ratings: 评分表
    :param item_similarity: 电影相似度矩阵
    :param keywords: 输入的电影名称或关键字
    :param k: 推荐个数
    :return: 推荐电影结果列表
    '''
    movie_list = []     # 存储推荐电影结果列表
    movie_id = list(items[items['movie_title'].str.contains(keywords)].movie_id)[0]   # 获得电影的id
    movie_similarity = item_similarity[movie_id - 1]    # 计算该电影的余弦相似度数组
    movie_similarity_index = np.argsort(-movie_similarity)[1:k + 1]     # 返回前k+1个最高相似度的索引位置

    for index in movie_similarity_index:
        rec_movie = list(items[items['movie_id'] == index + 1].movie_title)     # 电影名
        rec_movie.append(movie_similarity[index])    # 相似度
        rec_movie.append(ratings[ratings['movie_id'] == index+1].rating.mean()) # 平均评分
        rec_movie.append(len(ratings[ratings['movie_id'] == index+1]))    # 评分用户数
        movie_list.append(rec_movie)
    return movie_list

执行结果:

四、总结

此电影推荐系统相对来说较为简单,过程比较清晰,处理的数据也不是很复杂,重点在于理解基于内容的协同过滤算法。

当然,数据集中涵盖电影的分类信息,可以尝试采用聚类算法将相似的电影聚类,换一个新的角度提高推荐算法的准确性。

五、参考链接

https://www.cnblogs.com/lianyingteng/p/7811126.html

https://blog.csdn.net/u014248127/article/details/78885180

https://mp.weixin.qq.com/s/b-BD0glGpTglqsJzkj8ecA

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐