基于Python实现电影推荐系统【100010052】

news2024/11/24 19:56:27

电影推荐系统

标签:Tensorflow、矩阵分解、Surprise、PySpark

1、用Tensorflow实现矩阵分解

1.1、定义one_batch模块

import numpy as np
import pandas as pd

def read_and_process(filename, sep = '::'):
    col_names = ['user', 'item', 'rate', 'timestamp']
    df = pd.read_csv(filename, sep = sep, header = None, names = col_names, 
                     engine = 'python')
    df['user'] -= 1
    df['item'] -= 1
    for col in ('user', 'item'):
        df[col] = df[col].astype(np.float32)
    df['rate'] = df['rate'].astype(np.float32)
    return df

def get_data():
    df = read_and_process("./movielens/ml-1m/ratings.dat", sep = '::')
    rows = len(df)
    df = df.iloc[np.random.permutation(rows)].reset_index(drop = True)##打乱数据
    split_index = int(rows * 0.9)
    df_train = df[0: split_index]
    df_test = df[split_index:].reset_index(drop = True)
    print(df_train.shape, df_test.shape)
    return df_train, df_test
    
class ShuffleDataIterator(object):
    def __init__(self, inputs, batch_size = 10):
        ##注意这里的输入
        self.inputs = inputs
        self.batch_size = batch_size
        self.num_cols = len(self.inputs)
        self.len = len(self.inputs[0])
        self.inputs = np.transpose(np.vstack([np.array(self.inputs[i]) for i in range(self.num_cols)]))
        
    def __iter__(self):
        return self
    
    def __len__(self):
        return self.len
    
    def __next__(self):
        return self.next()
    
    def next(self):
        ids = np.random.randint(0, self.len, (self.batch_size,))
        out = self.inputs[ids, :]
        return [out[:, i] for i in range(self.num_cols)]
       
class OneEpochDataIterator(ShuffleDataIterator):
    def __init__(self, inputs, batch_size=10):
        super(OneEpochDataIterator, self).__init__(inputs, batch_size=batch_size)
        if batch_size > 0:
            self.idx_group = np.array_split(np.arange(self.len), 
                                            np.ceil(self.len / batch_size))
        else:
            self.idx_group = [np.arange(self.len)]
        self.group_id = 0
    ##next函数不能写在__init__下面
    def next(self):
        if self.group_id >= len(self.idx_group):
            self.group_id = 0
            raise StopIteration
        out = self.inputs[self.idx_group[self.group_id], :]
        self.group_id += 1
        return [out[:, i] for i in range(self.num_cols)]

1.2、构建优化部分

def inference_svd(user_batch, item_batch, user_num, item_num, dim = 5, 
                  device = '/cpu:0'):
    with tf.device('/cpu:0'):
        global_bias = tf.get_variable('global_bias', shape = [])
        w_bias_user = tf.get_variable('embd_bias_user', shape = [user_num])
        w_bias_item = tf.get_variable('embd_bias_item', shape = [item_num])
        
        bias_user = tf.nn.embedding_lookup(w_bias_user, user_batch, name = 'bias_user')
        bias_item = tf.nn.embedding_lookup(w_bias_item, item_batch, name = 'bias_item')
        
        w_user = tf.get_variable('embd_user', shape = [user_num, dim], initializer = tf.truncated_normal_initializer(stddev = 0.02))
        w_item = tf.get_variable('embd_item', shape = [item_num, dim], initializer = tf.truncated_normal_initializer(stddev = 0.02))
        
        embd_user = tf.nn.embedding_lookup(w_user, user_batch, name = 'embedding_user')
        embd_item = tf.nn.embedding_lookup(w_item, item_batch, name = 'embedding_item')
    
    with tf.device(device):
        infer = tf.reduce_sum(tf.multiply(embd_user, embd_item), 1)##tf.multiply是元素点乘
        infer = tf.add(infer, global_bias)
        infer = tf.add(infer, bias_user)
        infer = tf.add(infer, bias_item, name = 'svd_inference')
        
        regularizer = tf.add(tf.nn.l2_loss(embd_user), tf.nn.l2_loss(embd_item), 
                             name = 'svd_regularization')
    return infer, regularizer

def optimizer(infer, regularizer, rate_batch, learning_rate = 0.001, reg = 0.1, 
              device = '/cpu:0'):
    global_step = tf.train.get_global_step()
    assert global_step is not None
    with tf.device(device):
        cost_l2 = tf.nn.l2_loss(tf.subtract(infer, rate_batch))
        penalty = tf.constant(reg, dtype = tf.float32, shape = [], name = 'l2')
        cost = tf.add(cost_l2, tf.multiply(regularizer, penalty))
        train_op = tf.train.AdamOptimizer(
            learning_rate).minimize(cost, global_step = global_step)
    return cost, train_op

1.3、定义训练函数

import time 
from collections import deque
import numpy as np
import pandas as pd
from six import next
import tensorflow as tf
from tensorflow.core.framework import summary_pb2

np.random.seed(12321)

batch_size = 2000
user_num = 6040
item_num = 3952
dim = 15
epoch_max = 200
device = '/cpu:0'

def make_scalar_summary(name, val):
    return summary_pb2.Summary(
        value = [summary_pb2.Summary.Value(tag = name, simple_value = val)])

def svd(train, test):
    samples_per_batch = len(train) // batch_size
    
    iter_train = ShuffleDataIterator(
        [train['user'], train['item'], train['rate']], 
        batch_size = batch_size)##注意iuputs
    iter_test = OneEpochDataIterator(
        [test['user'], test['item'], test['rate']], batch_size = -1)
    user_batch = tf.placeholder(tf.int32, shape = [None], name = 'id_user')
    item_batch = tf.placeholder(tf.int32, shape = [None], name = 'id_item')
    rate_batch = tf.placeholder(tf.float32, shape = [None])
    
    infer, regularizer = inference_svd(
        user_batch, item_batch, user_num = user_num, 
        item_num = item_num, dim = dim, device = device)
    global_step = tf.train.get_or_create_global_step()
    cost, train_op = optimizer(
        infer, regularizer, rate_batch, 
        learning_rate = 0.001, reg = 0.05, device = device)
    
    init_op = tf.global_variables_initializer()
    
    with tf.Session() as sess:
        sess.run(init_op)
        summary_writer = tf.summary.FileWriter(logdir = './data', graph = sess.graph)
        print('{} {} {} {}'.format('epoch', 'train_error', 'val_error', 'elapsed_time'))
        errors = deque(maxlen = samples_per_batch)
        start = time.time()
        for i in range(epoch_max * samples_per_batch):
            users, items, rates = next(iter_train)
            _, pred_batch = sess.run(
                [train_op, infer], feed_dict = {user_batch: users, 
                                                item_batch: items, rate_batch: rates})
            pred_batch = np.clip(pred_batch, 1.0, 5.0)
            errors.append(np.power(pred_batch - rates, 2))
            if i % samples_per_batch == 0:
                train_err = np.sqrt(np.mean(errors))
                test_err2 = np.array([])
                for users, items, rates in iter_test:
                    pred_batch = sess.run(
                        infer, feed_dict = {user_batch: users, item_batch: items})
                    pred_batch = np.clip(pred_batch, 1.0, 5.0)
                    test_err2 = np.append(test_err2, np.power((pred_batch - rates), 2))
                end = time.time()
                test_err = np.sqrt(np.mean(test_err2))
                print('{:3d} {:f} {:f} {:f}(s)'.format(
                    i // samples_per_batch, train_err, test_err, end - start))
                train_err_summary = make_scalar_summary('training_error', train_err)
                test_err_summary = make_scalar_summary('testing_error', test_err)
                summary_writer.add_summary(train_err_summary, i)
                summary_writer.add_summary(test_err_summary, i)
                start = end

2、使用surprise库实现电影推荐

from surprise import KNNBaseline
from surprise import Dataset, Reader
from surprise.model_selection import cross_validate

reader = Reader(line_format = 'user item rating timestamp', sep = '::')
data = Dataset.load_from_file('./movielens/ml-1m/ratings.dat', reader = reader)
algo = KNNBaseline()
perf = cross_validate(algo, data, measures = ['RMSE', 'MAE'], cv = 3, verbose = True)

with open('./movielens/ml-1m/movies.dat', 'r', encoding = 'ISO-8859-1') as f:
    movies_id_dic = {}
    id_movies_dic = {}
    for line in f.readlines():
        movies = line.strip().split('::')
        id_movies_dic[int(movies[0]) - 1] = movies[1]
        movies_id_dic[movies[1]] = int(movies[0]) - 1
     
toy_story_neighbors = algo.get_neighbors(movie_id, k = 5)
print('最接近《Toy Story (1995)》的5部电影是:')
for i in toy_story_neighbors:
    print(id_movies_dic[i])

3、用pyspark实现矩阵分解与预测

3.1、配置spark的运行环境

from pyspark import SparkConf, SparkContext
from pyspark.mllib.recommendation import ALS, MatrixFactorizationModel

conf = SparkConf().setMaster('local').setAppName('movielenALS').set('spark.excutor.memory', '2g')
sc = SparkContext.getOrCreate(conf)

3.2、将数据转换为RDD格式

from pyspark.mllib.recommendation import Rating

ratings_data = sc.textFile('./movielens/ml-1m/ratings.dat')
ratings_int = ratings_data.map(lambda x: x.split('::')[0:3])
rates_data = ratings_int.map(lambda x: Rating(int(x[0]), int(x[1]), int(x[2])))

3.3、预测

sc.setCheckpointDir('checkpoint/')
ALS.checkpointInterval = 2
model = ALS.train(ratings = rates_data, rank = 20, iterations = 5, lambda_ = 0.02)

预测user14对item25的评分

print(model.predict(14, 25))

预测item25的最值得推荐的10个user

print(model.recommendUsers(25, 10))

预测user14的最值得推荐的10个item

print(model.recommendProducts(14, 10))

预测出每个user最值得被推荐的3个item

print(model.recommendProductsForUsers(3).collect())

使用方式说明:由于原始数据过大,将代码和数据分成两个文件夹,“代码”文件夹中包含的是代码和小部分小文件,“数据”文件夹下包含的是使用到的数据

其使用方式如下:

将文件夹“数据”解压,得到三个文件夹和一个文件,如下:

data 目录移动到“代码”目录下,如下:

5-chapter/data 目录下的两个 JSON 文件移动到“代码”目录下的 5-chapter/data 下:

7-chapter/data 目录下的两个 JSON 文件移动到“代码”目录下的 7-chapter/data 下

5-chapter 和 7-chapter 目录下的 data 目录中的 JSON 文件,是代码 5-6/5-7 和代码 7-2/7-3 中生成的中间代码,由于生成该份数据花费时间较长,所以可直接将该文件移至对应目录下

♻️ 资源

在这里插入图片描述

大小: 1.71MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87248934

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/116520.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IP判断.库函数复习.数组.C

strtok(在string.h库里)函数以"."为分隔符对IP字符串进行切分. atoi函数(在stdlib.h里)将切分的一部分字符串转换为十进制数字. 描述 C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串&#xf…

LeetCode题目笔记——1759. 统计同构子字符串的数目

文章目录题目描述题目难度——中等方法一:数学代码/C代码/Python总结题目描述 给你一个字符串 s ,返回 s 中 同构子字符串 的数目。由于答案可能很大,只需返回对 109 7 取余 后的结果。 同构字符串 的定义为:如果一个字符串中的…

300道网络安全工程师面试题(附答案解析)冲刺金三银四

2022年马上就要过去了,先来灵魂三连问,年初定的目标完成多少了?薪资涨了吗?女朋友找到了吗? 好了,不扎大家的心了,接下来进入正文。 由于我之前写了不少网络安全技术相关的文章和回答&#xff…

nginx 报400_nginx 400 Bad request

记录一次自己写出来的bug. 首先自己在gateway中做了filter,操作了header 操作中返回的报错400 nginx, 所以一直将矛头指向了nginx配置,但是各种查询和修改后,错误依旧. 静下心来一步步的看,发现请求实际上已经通过nginx发送到了gateway中,并且gateway日志中也清楚的记录了lo…

[普及练习场]失踪的7

本专辑上篇: [普及练习场] 生活大爆炸版石头剪刀布 看得都爽,对吧!感谢hydro的页面和浴谷的搬运。 目录 一.读题 失踪的7 题意 二 .做题 算法原理 算法实现 全篇代码分解讲解 输入 中心 一.读题 失踪的7 题目描述 远古的 Pascal 人也…

FIT2CLOUD飞致云荣膺“2022年度OSCHINA优秀开源技术团队”奖项

2022年12月,知名开源技术社区OSCHINA(开源中国)公布了“2022年度OSCHINA优秀开源技术团队”入选名单。凭借在开源软件研发和开源社区运营方面的优秀表现,FIT2CLOUD飞致云获得了OSCHINA社区的认可,荣膺“2022年度优秀开…

基于人脸关键点检测的驾驶员睡意检测系统

摘要 驾驶员注意力不集中或者分心是道路交通事故的主要原因。 为了减少道路交通事故,设计开发驾驶员疲劳检测系统至关重要。 本研究利用人脸关键点检测方法提出了驾驶员睡意检测系统,目的是使驾驶更安全。 一.人类检测方法 人脸关键点检测是人脸识别任…

B. Array Walk(贪心)

Problem - 1389B - Codeforces 给你一个数组a1,a2,...,an&#xff0c;由n个正整数组成。 最初&#xff0c;你站在索引1处&#xff0c;分数等于a1。你可以进行两种移动。 向右移动--从你当前的索引x走到x1&#xff0c;并将ax1加入你的分数。这个动作只有在x<n时才能进行。 …

黑客窃取 4 亿 Twitter 用户记录,勒索马斯克破财消灾

整理 | 何苗 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 上周五&#xff0c;一个用户名为 Ryushi 的用户在黑客论坛 Breached 上发布了一个帖子声称&#xff0c;已成功利用漏洞抓取了超 4 亿 Twitter 用户数据并在线出售。 为了证明数据的真实性&am…

spring cloud gateway网关转发websocket请求

springcloud gateway网关是所有微服务的统一入口。 1、springcloud gateway关键术语 Route&#xff1a;路由&#xff0c;网关配置的基本组成模块。一个Route模块由一个 ID&#xff0c;一个目标 URI&#xff0c;一组断言和一组过滤器定义。如果断言为真&#xff0c;则路由匹配…

经营报表-FineReport配置Oracle外接数据库(2)

1. 配置外接数据库 1.1 外接数据库配置入口 外接数据库的配置入口&#xff0c;有三种形式&#xff1a; 1&#xff09;超级管理员第一次登录数据决策系统时&#xff0c;即可为系统配置外接数据库。如下图所示&#xff1a; 2&#xff09;对于使用内置数据库的系统&#xff0c;管…

蓝桥杯嵌入式|第十三届蓝桥杯嵌入式省赛程序设计试题及其题解

题目 十三届省赛是要制作一个可由串口设置密码的密码锁。在本场比赛中&#xff0c;我们将用到LED模块、按键模块、串口模块、定时器的PWM模块以及官方会提供源码的LCD模块。下面就请看原题&#xff1a; 题解 在正式题解前&#xff0c;大家需要注意以下几点&#xff1a; 由于LCD…

《计算机网络》——第二章知识点

物理层:在连接各种计算机的传输媒体上传输数据比特流&#xff0c;确定与传输媒体接口有关的一些特性。1.机械特性 定义物理连接的特性&#xff0c;规定物理连接时所采用的规格、接口形状、引线数目、引脚数量和排列情况。 2.电气特性 规定传输二进制位时&#xff0c;线路上信…

【深度学习框架TensorFlow】使用TensorFlow框架构建全连接的神经网络,实现手写数字识别

文章目录一.TensorFlow1.1 内容介绍二.开始实验2.1TensorFlow的基本使用2.2基于全连接神经网络的手写数字识别2.3 结论一.TensorFlow 使用深度学习框架TensorFlow。 目标&#xff1a; 1.了解TensorFlow的基本用法&#xff1b; 2.学习使用TensorFlow构建全连接的神经网络&…

双周赛(三)

T1&#xff1a; 如果你仍然再用二指禅打字&#xff0c;那我建议你重新学习打字&#xff0c;这样你打字会更快&#xff0c;感觉更舒适和愉快。 有很多网站教授正确的打字。下图描述了基本原理: 用同一手指按压颜色相同的键。黄色键需要用小指按压&#xff0c;蓝色的用无名指&a…

最新 iOS 更新后 iPhone 联系人和数据丢失/丢失

我两天前做了最新的更新&#xff0c;现在我有丢失的联系人。帮助&#xff01;&#xff01; 许多 iPhone 用户犹豫是否将他们的设备升级到最新的 iOS 系统有一个&#xff08;也许是几个&#xff09;充分的理由。每次 iOS 发布后&#xff0c;总会有新功能震撼我们的世界。但是&am…

Unity 小积累

** Unity 学习小积累 ** 1.FindObjectsOfType和FindObjectOfType 前者返回所有个体&#xff08;集合&#xff09; 后者返回第一个个体 &#xff08;单个&#xff09; 2.uinty打包问题 打包webgl遇到了 实际上和py没有关系 c盘不够了 单纯 3.Unity 默认下载位置 坑 1.Uni…

【css样式】页面实现一侧固定一侧滚动的效果,到底部后一起滚动

文章目录position的定位类型position的定位类型 static&#xff1a;默认值&#xff0c;没有定位&#xff0c;遵循正常的文档流 fixed&#xff1a;固定定位&#xff0c;元素的位置是相对于浏览器窗口 relative&#xff1a;相对定位&#xff0c;相对于其正常的位置&#xff0c;移…

BOSS直聘自动投简历的实现过程

这两年疫情&#xff0c;公司业务越来越差&#xff0c;必须得准备后路了&#xff0c;每天睡前都会在直聘上打一遍招呼&#xff0c;一直到打哈欠有睡意为止...,这样持续了一周&#xff0c;发现很难坚持&#xff0c;身为一名资深蜘蛛侠&#xff0c;怎么能这样下去呢&#xff1f;于…

3D模型的生成式AI

生成式 AI 席卷了 2022 年&#xff0c;我们最近决定 Physna 不应错过这个热点。 因此&#xff0c;尽管生成 AI 并不是我们的商业模式—Physna 是一家 3D 搜索和分析公司&#xff0c;专注于 AR/VR 和制造中的工程和设计应用—我们还是决定为 3D 模型和场景生成 AI 构建一个非常基…