推荐系统实践:基于数据集MovieLens构造简单推荐系统

2023-05-16

摘要

本文基于 MovieLens 数据集构造了用户-电影项目评价矩阵,并基于评价矩阵计算两用户间的相似度,取出相似度最高的 N 个用户作为候选用户序列。接着筛选出这 N 个候选用户的高分电影项目且当前用户尚未观看,并根据这高分候选电影项目集合的电影类型,与当前用户所观影的全部电影类型做一个标签共现,预测当前用户对这些高分电影项目的评分,把预测评分最高的 M 个电影项目推荐给当前用户。

关键词:协同过滤;标签共现;电影推荐;Demo 实战验证

MovieLens 是蛮经典的数据集,在验证推荐算法的初期经常会使用到。本文的数据集没有很大,是基于 ml-latest-small(size:1MB)这个超小的数据集来做微型验证的,反正就是验证思路对不对,管它数据集的 size 咋样,对叭!数据集可以去 MovieLens 官网下载,这里就不提供了嘤嘤嘤。

碎碎念

哦对了,本文是给纯小白入门用的,浅浅打代码确实菜的一批,这次的推荐系统算法验证没有用很花哨的程序实现,一行行带小白入门好了,顺带着我也做个总结,为毕业设计中的一个小模块贡献出自己绵薄的力量呜呜呜,这样子一说就感觉自己形象变高大了呢!什么?想了解浅浅的毕业设计是什么?哦,不告诉你,反正浅浅出品,必属精品嘿嘿嘿。好了废话不多说,就开始入门叭。

实战验证

导入第三方库与数据文件

首先是导入一些必备的第三方库:

import numpy as np
import pandas as pd
import csv
import math

NumPy、Pandas、CSV、Math 版本随意,这个没所谓。其实我压根就没觉得 NumPy 要放进去,只是图个方便,顺手就写了。万一有读者想说后续有个去重操作想用 NumPy 搞一搞,这不就方便了嘛。

接着是利用 pd.read_csv() 进行数据的导入,这里用 values.tolist() 就顺手把 dataframe 类型转换成 list 类型了,嗐,我果然是个转换类型小天才,低调低调:

movies=pd.read_csv("movies.csv").values.tolist()
links=pd.read_csv("links.csv").values.tolist()
ratings=pd.read_csv("ratings.csv").values.tolist()
tags=pd.read_csv("tags.csv").values.tolist()

嗷,你们可能对这四个文件很懵逼,来,浅浅让你们开开眼(虽然说可以自行官网下载数据,完了之后再自己看看,让文章更加充实些,我贴一下样本吧)。

数据变量名说明

movies.csv

links.csv

ratings.csv

tags.csv

我对里面表头做个说明:

变量名含义
movieId电影编号
title电影标题
genres电影类型
imdbId在 imdb 里的编号(反正我没用到这个)
tmdbId在 tmdb 里的编号(反正我没用到这个)
userId用户编号
rating评分(0.5~5)
timestamp时间戳(反正我没用到这个)
tags用户对电影的打标,但我更倾向于类似弹幕(反正我没用到这个)

转换为评价矩阵

但是有上面的数据,看着好像蛮好做的,但是我比较倾向于处理成用户-项目的评价矩阵进行相似性计算,所以,数据处理过程如下:

#产生评价矩阵:

movieId=[]#movieId 列表

for index in range(len(movies)):
    movieId.append(movies[index][0])

#print(len(movies))这里也是我输出打锚点的地方

Q=[]#评价矩阵

userRow=[0 for i in range(len(movies)+1)]

#userRow 列表是用户评价行,长度为电影数量加一

#print(movieId[len(movies)-1])你可以输出看看……

userId=[(i+1) for i in range(610)]

count = 0 #userId initial
userRow[0]=ratings[0][0]
for index in range(len(ratings)):
    if count == ratings[index][0]-1:
        userRow[(movieId.index(ratings[index][6])+1)]=ratings[index][7]
    elif count != ratings[index][0]-1:
        count=count+1
        Q.append(userRow)#添加到评价矩阵 Q 中
        userRow=[0 for i in range(len(movies)+1)]
        userRow[0]=ratings[index][0]
        userRow[(movieId.index(ratings[index][8])+1)]=ratings[index][9]
Q.append(userRow)

我们来分析一下,我当前这个矩阵的大小是 610*9742 那么如果每次打开这个程序都要进行这么一次数据处理,接近六百万次的数据处理能否避免呢?当然可以啦,我直接得到 Q 之后就把它写进一个 Q.csv 的文件里了:

#写入 Q.csv 文件中
with open ("Q.csv","w",newline="") as csvfile:
    writer = csv.writer(csvfile)
    writer.writerows(Q)

然后打开 Q.csv 看看,长这样子呢!

篇幅有限,我就不放出整个数据表了,也放不下,反正代码给了,你们自个儿跑就行。

既然已经做了写入,那么每次只需要读取取用即可:

Q=pd.read_csv("Q.csv",header=None).values.tolist()

为了防止发生读取错误吼,可以试着打个锚点输出一下瞅瞅是不是你想要的数据值即可,这个问题很好解决。值得一提的是,这里写入的是一个无表头的 csv 文件,所以要用 header=None

相似度计算

然后就是利用评价矩阵计算相似度了:

def similar(i,j):
    sum_ij = 0 #求和分子
    mul_i = 0 #i 项的平方和
    mul_j = 0 #j 项的平方和
    for index in range(1,len(i)):
        #if i[index]!=-1 and j[index]!=-1:
        sum_ij=sum_ij+i[index]*j[index]
        mul_i=mul_i+i[index]*i[index]
        mul_j=mul_j+j[index]*j[index]
         #print("i:",i[index],",j:",j[index])
    if mul_i==0 or mul_j==0:
        sim=0
    else:
        sim=sum_ij/(math.sqrt(mul_i)*(math.sqrt(mul_j)))#余弦相似度
    return sim

想看 sim 是啥的可以自己输出一下,反正也就是 print(sim(i,j)) 这里要注意哈,i,j 都是向量,换句话说都是一个 list。

实现标签共现

然后是获取用户的观影类型频数:

def co_tags(userId):
    userGenres=[]#观影矩阵(二维)
    userWatchs=[]#观影类型(一维)
    frequency=[]#类型频率
    userList=[]#定义用户行向量(存放电影编号)
    ListIndex=[]#定义用户电影编号下标
    
    for index in range(1,len(Q[userId-1])):
        if Q[userId-1][index]!=0:
            userList.append(movies[index-1][0])
            ListIndex.append(index-1)#下标默认从 0 开始,所以减一
    #print(len(userList))
    userMovies=[]#二维
    #MovieTags=[]#一维
    #得到用户所有观影的电影类型矩阵
    for item in range(len(ListIndex)):
        MovieGenres=movies[ListIndex[item]][11].split("|")
        userGenres.append(MovieGenres)
        MovieGenres=[]
    #for index in range(len(userGenres)):
        #print(userGenres[index])
    for i in range(len(userGenres)):
        for j in range(len(userGenres[i])):
            if userGenres[i][j] in userWatchs:
                frequency[userWatchs.index(userGenres[i][j])]+=1#自增
            else:
                userWatchs.append(userGenres[i][j])
                frequency.append(1)
    #print(userWatchs)
    #print(frequency)
	...

点击这里阅读全文

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

推荐系统实践:基于数据集MovieLens构造简单推荐系统 的相关文章

  • Linux编译C文件

    熟悉了Windows平台下编译一个C 43 43 工程后 xff0c 你是否会提出这样一个问题 xff1a 在Linux平台下又如何编译一个C 43 43 工程呢 xff1f 希望本文能给正在学习或想学习Linux C 43 43 开发的你
  • 学习笔记——atoi函数的用法及用C语言实现atoi

    学习笔记 atoi函数的用法及用C语言实现atoi from csdn 库函数原型 xff1a inclue lt stdlib h gt int atoi const char nptr 用法 xff1a 将字符串里的数字字符转化为整形数
  • 互斥信号量和二进制信号量的区别

    互斥信号量和二进制信号量的区别 互斥型信号量必须是同一个任务申请 xff0c 同一个任务释放 xff0c 其他任务释放无效 同一个任务可以递归申请 二进制信号量 xff0c 一个任务申请成功后 xff0c 可以由另一个任务释放 二进制信号量
  • 堆栈区别

    堆和栈的区别 一 预备知识 程序的内存分配 一个由c C 43 43 编译的程序占用的内存分为以下几个部分 1 栈区 xff08 stack xff09 由编译器自动分配释放 xff0c 存放函数的参数值 xff0c 局部变量的值等 其操作
  • 用四个砝码称出1—40克所有重量,四个砝码分别为多少? 梅氏砝码问题

    这个在数学上叫做梅氏砝码问题 xff0c 其叙述如下 xff1a 若有n个砝码 xff0c 重量分别为M1 M2 xff0c Mn 且能称出从1到 xff08 M1 43 M2 43 43 Mn 的所有重量 xff0c 则再加一个砝码 xf
  • Linux 文件夹 压缩 命令

    from http hi baidu com no fear no hope blog item 8182155aec16a7c59d82046d html Linux 文件夹 压缩 命令 2011年08月28日 星期日 22 02 Lin
  • mysql 分库分表

    分表是分散数据库压力的好方法 分表 xff0c 最直白的意思 xff0c 就是将一个表结构分为多个表 xff0c 然后 xff0c 可以再同一个库里 xff0c 也可以放到不同的库 当然 xff0c 首先要知道什么情况下 xff0c 才需要
  • MySQL的数据库引擎的类型

    你能用的数据库引擎取决于mysql在安装的时候是如何被编译的 要添加一个新的引擎 xff0c 就必须重新编译MYSQL 在缺省情况下 xff0c MYSQL支持三个引擎 xff1a ISAM MYISAM和HEAP 另外两种类型INNODB
  • Fast-Planner安装、环境配置以及问题解决

    Fast Planner是香港科技大学沈劭劼老师团队开源的项目 旨在复杂的未知环境中实现四旋翼快速飞行 Fast Planner的github网址为 https github com HKUST Aerial Robotics Fast P
  • 安装双系统出现的一些问题(显卡和无法连接WIFI)

    显卡 问题1 xff1a 安装双系统之后开机黑屏 xff0c 由于显卡引起 xff0c 显卡不支持 解决办法 xff1a 禁用独立显卡或者更改显卡设置 xff0c 进入文件 boot grub grub cfg xff0c 按下图加入标亮字
  • ros没装全,gazebo模型加载不出来

    ros没装全 xff0c gazebo模型加载不出来 安装ros 关于rosdep update 首先换热点试一下 xff0c 在来回切换wifi 按照https blog csdn net yufeng1108 article detai
  • catkin_make遇到 gazebo_ros_controlConfig.cmake相关的问题

    现象 xff1a Could not find a package configuration file provided by gazebo ros control with any of the following names 解决方法
  • 一些vscode自动提示报错

    Pointer to incomplete class type is not allowed 通常是由于类声明了但是没有定义造成的 xff0c 需要做的是在错误文件里面引用下这个类 xff1a class Test xff1b a poi
  • bazel一些用法

    1 编译东西 要在根目录下 xff0c 和WORKSPACE在同一级 例如 xff0c 对于bazelbuild examples 而BUILD文件一般与源文件并列 examples cpp tutorial stage1 main BUI
  • 第十一节std::atomic原子操作

    一 原子操作 1 1原子操作概念例子 互斥量 xff1a 多线程编程中保护共享数据 xff1a 锁 xff0c 操作共享数据 xff0c 开锁 有两个线程 xff0c 对一个变量进行操作 xff0c 这个线程读 xff0c 另一个线程往变量
  • 用Ceres实现PnP

    在ceres中实现PnP优化 xff08 仅优化位姿 xff09 视觉SLAM十四讲 课后习题 ch7 xff08 更新中 xff09
  • deque insert()函数几种用法

    C 43 43 deque insert 用法及代码示例
  • Matplotlib error: No such file or directory: ‘latex‘: ‘latex‘

    Matplotlib error No such file or directory latex latex span class token function sudo span apt span class token function
  • 在ROS下Intel RealSense D435i 驱动的安装,避免踩坑,避免缺少imu话题等各种问题(适用于D400系列、SR300和T265跟踪模块等)

    版权声明 本文为博主原创文章 未经博主允许不得转载 https blog csdn net AnChenliang 1002 article details 109454465 目录 背景 方法1 使用apt安装 不建议使用此方法 了解一下
  • wsl作为开发主机与开发板联调

    linux开发经历记录 wsl作为开发主机与开发板联调 uboot使用nfs网络挂载时使用hanewin搭建win10的nfs servers 背景介绍 小白学习linux开学 xff0c 不想用VM虚拟机作为开发平台 xff0c 恰好了解

随机推荐

  • weka中文乱码解决办法

    由于weka的默认字符集编码是Cp1252 xff0c 所以如果你导入的数据中有中文字符 xff0c 就会出现乱码的情况 xff0c 所以需要weka的RunWeka ini文件 将cp1252替换成你的数据对应的字符集编码 xff0c 比
  • 动态库和静态库的区别

    静态库 xff1a 这类库的名字一般是libxxx a xff1b 1 利用静态函数库编译成的文件比较大 xff0c 因为整个函数库的所有数据都会被整合进目标代码中 xff0c 他的优点就显而易见了 xff0c 2 即编译后的执行程序不需要
  • 重复数据删除技术(Data Deduplication)

    我相信所有人都会同意 xff0c 数据存储正在以飞快地 xff0c 甚至是令人震惊的速度在增长 这意味着为了不影响普通用户的正常使用 xff0c 存储管理员们不得不加班加点地在幕后 工作着 他们的鲜为人知的工作包括 xff1a 配额管理 x
  • TCP/IP协议

    TCP IP 协议栈是一系列网络协议的总和 xff0c 是构成网络通信的核心骨架 xff0c 它定义了电子设备如何连入因特网 xff0c 以及数据如何在它们之间进行传输 TCP IP 协议采用4层结构 xff0c 即应用层 传输层 网络层和
  • 趣谈网络协议-云计算中的协议

  • ros里Catkin的CMakelists/package.xml

    Catkin是基于CMake的编译构建系统 xff0c 具有以下特点 xff1a Catkin沿用了包管理的传统像 find package 基础结构 pkg config扩展了CMake xff0c 例如 软件包编译后无需安装就可使用 自
  • js根据坐标进行图片截图,获取图片上指定位置的截图

    根据坐标截取图片上指定的区域 xff0c 坐标可以是规则的图片截取 xff0c 也可以是不规则的图片截取 实现思路 xff1a 规则裁剪自然不用多说 xff0c 我们使用画布的getImageData x y width height 方法
  • 浅谈APM系列-----update_flight_mode(ModeAltHold)

    update flight mode xff08 ModeAltHold xff09 这里只看ModeAltHold 位置 xff1a X ardupilot ArduCopter mode cpp update flight mode c
  • 多态的总结

    对于多态 xff0c 可以总结以下几点 xff1a 一 使用父类类型的引用指向子类的对象 xff1b 二 该引用只能调用父类中定义的方法和变量 xff1b 三 如果子类中重写了父类中的一个方法 xff0c 那么在调用这个方法的时候 xff0
  • android 深度图

    在 Android开发中自定义控件是一个范围很广的话题 xff0c 讲起自定义控件 xff0c 从广度上来划分的话 xff0c 大体上可以划分为 xff1a View ViewGroup的绘制事件分发各种动画效果滚动嵌套机制还有涉及到相关的
  • 在配置Intel realsense (D435i)时遇到的问题

    1 第一次配置相机时 配置完成后 运行相机报以下错误 02 11 20 50 18 674 WARNING 140196725126912 messenger libusb cpp 42 control transfer returned
  • Robosense M1/速腾半固态激光雷达M1 保姆级教程1-如何连接雷达?

    引言 当我们拿到M1雷达时 xff0c 可能会因为激光雷达是一个新的设备 xff0c 没有用过 xff0c 而感到紧张和局促 没有关系 xff0c 通过阅读文本 xff0c 可以让你轻而易举的上手使用激光雷达 1认识M1接口 图中较粗的接口
  • PMP(一):知识要点汇总

    开篇 首先恭喜自己成为 项目管理专业人士 的一员 xff0c 本专题旨在帮助自己重新梳理整个的知识体系以及后续对于项目管理的理解与尝试 系列一 xff1a 知识要点汇总 以下内容是我在备考和考完后对于部分知识要点的一个汇总和总结 xff0c
  • git在vscode中的使用

    git在vscode中的使用 vscode 作为前端使用较多的软件 xff0c 平时的git操作不可避免 xff0c 但是利用vscode自带的功能和插件 xff0c 可以让我们的工作效率提高不少 项目准备 直接clone span cla
  • 获利空间看刘嘉玲理论来看;乐扣乐扣尽量靠近k

    i tiboo cn 1768805 i tiboo cn 1768806 i tiboo cn 1768807 i tiboo cn 1768810 i tiboo cn 1768813
  • 我见过最清晰的--理解梯度,散度,旋度

    作者 xff1a FRANK WANG 链接 xff1a https www zhihu com question 24074028 answer 26657334 来源 xff1a 知乎 梯度 运算的对像是纯量 运算出来的结果会是向量在一
  • 视觉应用工程师-环境安装教学视频-Mac系统其他操作

    立即学习 https edu csdn net course play 29993 432706 utm source 61 blogtoedu Mac系统安装miniconda搭建深度学习环境 安装 Conda是一个开源的包 环境管理器
  • Windows 环境下安装Redis 5.0.x 服务图文教程

    Windows 环境下安装Redis 5 0 x 服务图文教程 Redis官网并没有提供windows的安装包 xff0c github有第三方制作的windows安装包 下载地址 xff1a https github com tporad
  • Python 爬虫+可视化,手把手教你使用 Python 爬取 JD 网站并且可视化展示

    当你看到别人使用 Python 网络爬虫做出一些高大上的项目你是否也有那么一点点的心动 xff1f 羡慕别人用几行简单的代码就能获取到自己想要的数据 xff1f 羡慕别人用几行代码就能做出优美的可视化图案 xff1f 我将使用最新 Pyth
  • 推荐系统实践:基于数据集MovieLens构造简单推荐系统

    摘要 本文基于 MovieLens 数据集构造了用户 电影项目评价矩阵 xff0c 并基于评价矩阵计算两用户间的相似度 xff0c 取出相似度最高的 N 个用户作为候选用户序列 接着筛选出这 N 个候选用户的高分电影项目且当前用户尚未观看