06、基于内容的过滤算法Tensorflow实现

06、基于内容的过滤算法Tensorflow实现

开始学习机器学习啦,已经把吴恩达的课全部刷完了,现在开始熟悉一下复现代码。对这个手写数字实部比较感兴趣,作为入门的素材非常合适。

05、基于梯度下降的协同过滤算法中已经介绍了协同过滤算法的基本实现方法,但是这种方法仅根据用户的相似度进行推荐,而不关注用户或者电影本身的一些特征的匹配,基于内容的过滤算法正式为了对此进行改进。

此处还是以电影推荐作为实际的案例

1、基于内容的过滤算法实现原理

基于内容的过滤算法的神经网络实现依赖于现有的特征数据,这个特征数据包括用户的特征数据电影本身的特征数据。常理来讲,最终的打分结果是用户自身的特征和电影本身的属性共同决定的,但是其互相影响的机制可能并不明确,因此可以使用如下的神经网络模型直接训练得到结果:
在这里插入图片描述
对于上图,在吴恩达的解释中,Vu和Vm分别是用户和电影的特征向量,这个特征是从原有的基础数据(如电影类型、用户爱好、用户年龄等等)中训练出来的,其并没有具体对应的特征含义

因此,其所介绍的基于内容的过滤算法完全基于神经网络的模型得到预测的打分结果,进而进行推荐,下面对原理步骤进行解释。

2、数据集的简单解释

全部的工程文件可以在最上方的链接进行下载。这个数据集的来源是:dataset,吴恩达老师的数据在此基础上进行了二元化的处理,所以看着非常难以理解。

首先是content_user_train.csv这个文件,,其抬头在content_user_train_header.txt中将其组合即可得到用户的数据,如下所示:
在这里插入图片描述
但是值得注意的是,数据和很多的重复的,例如对于用户3,其第40-43行都是一样的数据,可以看到用户3给一个电影打过分:
在这里插入图片描述
而这代表用户3看过的电影在content_item_train.csv这个文件的第40-43行,可以看到只有72378这个代号的电影,这个电影占用四行,代表它在四个分类(比如爱情、浪漫、动作等等),电影的平均分是2.6。
在这里插入图片描述
content_item_train.csv这个文件的抬头在content_item_train_header.txt中,将其组合即可得到电影的数据,例如:
在这里插入图片描述

为充分解释,再举一个用户2的例子,其重复占用从第1行到第39行:
在这里插入图片描述
而在content_item_train.csv这个文件中的第1行到第39行,表示其看过6874、8798、46970等16个电影,每个电影属于多少个分类,每个电影就会占用多少行(6874占用3个分类就有三行):
在这里插入图片描述

content_item_train.csv中的电影会有重复,毕竟可能不同用户都给同一电影打分,因此6874除了第一行有第474行也有,这么设计只是为了查找时方便对应,但是训练速度估计比较着急
在这里插入图片描述
content_item_vecs.csv这里面存储的也是电影的相关原始特征,但是其不会出现上面的重复,因为其不需要和用户对应且电影id递增排列。
在这里插入图片描述
content_movie_list.csv这里面是id所对应的实际电影:
在这里插入图片描述

3、基于内容的过滤算法实现步骤

STEP1: 引入包并加载数据集(不考虑用户ID、评分次数和平均评分、电影ID,所以需要移除部分数据):

from keras import Model
import pandas as pd
import tensorflow as tf
from tensorflow import keras
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.model_selection import train_test_split
from Content_Based_Filtering_recsysNN_utils import *
pd.set_option("display.precision", 1)

# 加载数据,设置配置变量
item_train, user_train, y_train, item_features, user_features, item_vecs, movie_dict, user_to_genre = load_data()
# 计算用户特征的数量,训练时移除用户ID、评分次数和平均评分
num_user_features = user_train.shape[1] - 3
# 计算物品特征的数量,训练时移除电影ID
num_item_features = item_train.shape[1] - 1
# 用户向量的起始位置
uvs = 3
# 物品向量的起始位置
ivs = 3
# 在训练中使用的用户列的起始位置
u_s = 3
# 在训练中使用的物品列的起始位置
i_s = 1

STEP2: 数据标准化与测试集的分割:

# 如果为True,则对数据应用标准化
scaledata = True
# 归一化训练数据
if scaledata:
    # 保存原始的item_train和user_train数据
    item_train_save = item_train
    user_train_save = user_train

    # 对item_train数据进行标准化处理
    scalerItem = StandardScaler()
    scalerItem.fit(item_train)
    item_train = scalerItem.transform(item_train)

    # 对user_train数据进行标准化处理
    scalerUser = StandardScaler()
    scalerUser.fit(user_train)
    user_train = scalerUser.transform(user_train)

    # 对y_train数据进行归一化处理,使其值在-1到1之间
    scaler = MinMaxScaler((-1, 1))
    scaler.fit(y_train.reshape(-1, 1))
    y_train = scaler.transform(y_train.reshape(-1, 1))

# 使用train_test_split函数将数据集分割为训练集和测试集,其中训练集占比为80%
item_train, item_test = train_test_split(item_train, train_size=0.80, shuffle=True, random_state=1)
user_train, user_test = train_test_split(user_train, train_size=0.80, shuffle=True, random_state=1)
y_train, y_test = train_test_split(y_train, train_size=0.80, shuffle=True, random_state=1)

# 打印训练集和测试集的形状
print(f"movie/item training data shape: {item_train.shape}")
print(f"movie/item test  data shape: {item_test.shape}")


STEP3: 模型构建与训练(其中特征数量num_outputs 指的是训练最终得到的特征数量,即Vu和Vm的维度,理论上可以随意选取):

# 构建模型  
# 输出的电影特征和用户特征数量,都是32  
num_outputs = 32  
tf.random.set_seed(1)  # 设置随机种子以确保结果的可复现性  
  
# 定义用户神经网络  
user_NN = tf.keras.models.Sequential([  
  tf.keras.layers.Dense(256, activation='relu'),  # 第一层有256个神经元,使用ReLU激活函数  
  tf.keras.layers.Dense(128, activation='relu'),  # 第二层有128个神经元,使用ReLU激活函数  
  tf.keras.layers.Dense(num_outputs),            # 输出层有32个神经元  
])  
  
# 定义物品神经网络  
item_NN = tf.keras.models.Sequential([  
  tf.keras.layers.Dense(256, activation='relu'),  # 第一层有256个神经元,使用ReLU激活函数  
  tf.keras.layers.Dense(128, activation='relu'),  # 第二层有128个神经元,使用ReLU激活函数  
  tf.keras.layers.Dense(num_outputs),            # 输出层有32个神经元  
])  
  
# 创建用户输入并连接到基础网络  
input_user = tf.keras.layers.Input(shape=(num_user_features))  # 定义用户输入层  
vu = user_NN(input_user)  # 将用户输入传入用户神经网络  
vu = tf.linalg.l2_normalize(vu, axis=1)  # 对用户向量进行L2正则化  
  
# 创建物品输入并连接到基础网络  
input_item = tf.keras.layers.Input(shape=(num_item_features))  # 定义物品输入层  
vm = item_NN(input_item)  # 将物品输入传入物品神经网络  
vm = tf.linalg.l2_normalize(vm, axis=1)  # 对物品向量进行L2正则化  
  
# 计算两个向量vu和vm的点积  
output = tf.keras.layers.Dot(axes=1)([vu, vm])  # 计算点积作为输出  
  
# 指定模型的输入和输出  
model = Model([input_user, input_item], output)  # 定义模型  
model.summary()  # 打印模型概要  
  
# 设置模型的优化器和损失函数  
tf.random.set_seed(1)  
cost_fn = tf.keras.losses.MeanSquaredError()  # 使用均方误差作为损失函数  
opt = keras.optimizers.Adam(learning_rate=0.01)  # 使用Adam优化器,学习率为0.01  
model.compile(optimizer=opt, loss=cost_fn)  # 编译模型  
  
# 训练模型  
tf.random.set_seed(1)  
model.fit([user_train[:, u_s:], item_train[:, i_s:]], y_train, epochs=20)  # 对模型进行20轮训练  
  
# 评估模型在测试集上的表现  
model.evaluate([user_test[:, u_s:], item_test[:, i_s:]], y_test)  # 计算模型在测试集上的损失值

STEP4: 基于模型的新用户最佳推荐

首先要构建新用户的特征:

# 给新用户推荐
new_user_id = 5000
new_rating_ave = 1.0
new_action = 5
new_adventure = 1
new_animation = 1
new_childrens = 5
new_comedy = 1
new_crime = 5
new_documentary = 1
new_drama = 1
new_fantasy = 1
new_horror = 1
new_mystery = 1
new_romance = 1
new_scifi = 5
new_thriller = 1
new_rating_count = 1

user_vec = np.array([[new_user_id, new_rating_count, new_rating_ave,
                      new_action, new_adventure, new_animation, new_childrens,
                      new_comedy, new_crime, new_documentary,
                      new_drama, new_fantasy, new_horror, new_mystery,
                      new_romance, new_scifi, new_thriller]])

下面是基于新用户特征、所有的电影特征和现有模型进行预测:

# generate and replicate the user vector to match the number movies in the data set.
user_vecs = gen_user_vecs(user_vec,len(item_vecs))

# 进行预测并按照推荐程度进行排序
sorted_index, sorted_ypu, sorted_items, sorted_user = predict_uservec(user_vecs,  item_vecs, model, u_s, i_s,
                                                                       scaler, scalerUser, scalerItem, scaledata=scaledata)
# 打印结果
print_pred_movies(sorted_ypu, sorted_user, sorted_items, movie_dict, maxcount = 10)

其中预测函数中需要先进行归一化,如何进行预测:

def predict_uservec(user_vecs, item_vecs, model, u_s, i_s, scaler, ScalerUser, ScalerItem, scaledata=False):  
    """  
    给定一个用户向量,对item_vecs中的所有电影进行预测,返回一个按预测评分排序的数组预测值,  
    以及按预测评分排序索引排序的用户和物品数组。  
    """  
    # 判断是否需要缩放数据  
    if scaledata:  
        # 如果需要缩放,则使用ScalerUser和ScalerItem对user_vecs和item_vecs进行缩放  
        scaled_user_vecs = ScalerUser.transform(user_vecs)  
        scaled_item_vecs = ScalerItem.transform(item_vecs)  
        # 使用缩放后的数据进行预测  
        y_p = model.predict([scaled_user_vecs[:, u_s:], scaled_item_vecs[:, i_s:]])  
    else:  
        # 如果不需要缩放,则直接使用原始数据进行预测  
        y_p = model.predict([user_vecs[:, u_s:], item_vecs[:, i_s:]])  
      
    # 使用scaler对预测结果进行逆变换  
    y_pu = scaler.inverse_transform(y_p)  
  
    # 检查预测结果中是否有负数,如果有则打印错误信息  
    if np.any(y_pu < 0):   
        print("Error, expected all positive predictions")  
      
    # 对预测结果进行排序,获取排序索引,并按照排序索引对预测结果、物品和用户进行排序  
    sorted_index = np.argsort(-y_pu, axis=0).reshape(-1).tolist()  # 取反以获得最高评分在前  
    sorted_ypu = y_pu[sorted_index]  
    sorted_items = item_vecs[sorted_index]  
    sorted_user = user_vecs[sorted_index]  
      
    # 返回排序索引、排序后的预测结果、排序后的物品和用户  
    return (sorted_index, sorted_ypu, sorted_items, sorted_user)

4、结果分析

按照我给出的新用户的特性:action、childrens、crime、scifi是其比较喜欢的,推荐的排名前十的电影如下:
在这里插入图片描述
可以看到其推荐的东西也比较符合这些特征。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用最少数量的箭引爆气球[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 有一些球形气球贴在一堵用XY平面表示的墙面上。墙面上的气球记录在整数数组points&#xff0c;其中points[i] [xstart, xend]表示水平直径在xstart和xend之间的气球。你不知道气球的确切y坐标。一支弓箭可以沿着x轴从不同点完全垂直…

Springboot-注册注解【springboot常用注解】

1.组件注册 1.1 使用的注解 Configuration:普通配置类,替代以前的配置文件,配置类本身也是容器的组件|SpringBootConfiguration:Springboot配置类,与Configuration功能一样|Bean:替代以前的Bean标签,如果没有在Bean标签内定义名字,则默认组件的名字为方法名,可以直接修改注解…

在gitlab上使用server_hooks

文章目录 1. 前置条件2. Git Hook2.1 Git Hook 分为两部分&#xff1a;本地和远程2.1.1 本地 Git Hook&#xff0c;由提交和合并等操作触发&#xff1a;2.1.2 远程 Git Hook&#xff0c;运行在网络操作上&#xff0c;例如接收推送的提交&#xff1a; 3. 操作步骤3.1 对所有的仓…

Linux下的文件IO之系统IO

1. 知识点 读入写出&#xff0c;切记以我们程序为中心向文件或者别的什么东西读入写出&#xff08;输入流输出流&#xff09; 人话就是 文件向我们程序就是读入 程序向文件或者别的什么就是写出 2. open打开文件 open.c /****************************************************…

C++ 学习之函数成员指针的一个小细节

看看下面的代码&#xff0c;你能看出错误吗 class A { public:void fun(){}}; int main() {A a;void (A:: * p)() &A::fun;(*p)(); } 这段代码在调用成员函数时存在问题。正确的方式是使用对象来调用成员函数&#xff0c;而不是通过指针。以下是修正后的代码&#xff1a…

STM32CubeIDE(CUBE-MX hal库)----定时器

系列文章目录 STM32CubeIDE(CUBE-MX hal库)----初尝点亮小灯 STM32CubeIDE(CUBE-MX hal库)----按键控制 STM32CubeIDE(CUBE-MX hal库)----串口通信 文章目录 系列文章目录前言一、定时器二、使用步骤三、HAL库实验代码三、标准库代码 前言 STM32定时器是一种多功能外设&#…

异常 Exception 02

异常 Exception 02 六、异常处理1、基本介绍2、异常处理的方式3、示意图 try-catchthrows1、介绍2、注意事项 自定义异常1、基本概念2、自定义异常的步骤3、实例4、throw和throws的区别 六、异常处理 1、基本介绍 异常处理就是当异常发生时,对异常处理的方式。 2、异常处理的…

以STM32CubeMX创建DSP库工程方法一

以STM32CubeMX创建DSP库工程方法 略过时钟树的分配和UART的创建等&#xff0c;直接进入主题生成工程文件 它们中的文件功能如下&#xff1a; 1&#xff09;BasicMathFunctions 基本数学函数&#xff1a;提供浮点数的各种基本运算函数&#xff0c;如向量加减乘除等运算。 2&…

VBA代码解决方案第8讲:用FindPrevious进行重复搜索及利用LIKE查找

《VBA代码解决方案》(版权10028096)这套教程是我最早推出的教程&#xff0c;目前已经是第三版修订了。这套教程定位于入门后的提高&#xff0c;在学习这套教程过程中&#xff0c;侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码…

货代FOB条款卖方必备的知识:发货人都要承担哪些费用呢?

据统计&#xff0c;中国出口中以FOB成交的占到70%&#xff0c;但专家指出&#xff1a;FOB对出口商的风险更大&#xff0c;有可能造成货、款两空的结局。 目前我国出口合同以FOB价格条款成交的比例越来越大&#xff0c;而且收货人指定船公司的少&#xff0c;指定境外货代的多&am…

3款厉害的小工具,小黑子都在用!

大家好&#xff0c;我是 Javapub。 程序员与普通人最大的区别是什么&#xff0c;当然是会使用工具。基于一些同学经常问我的问题&#xff0c;接下来给大家分享几款我经常使用的工具&#xff0c;主打一个提升效率。 第一款 Everything 用 windwos 的同学都体会过&#xff0c;…

带大家做一个,易上手的家常土豆片

还是先从冰箱里那一块猪瘦肉 搞一点蒜和生姜 切成小块 装进一个碗里 这里一点就够了 一条绿皮辣椒 切片 三个左右干辣椒 随便切两刀 让它小一点就好了 一起装一个碗 一大一小两个土豆切片 猪肉切片 起锅烧油 然后 下肉翻炒 等肉变颜色捞出来 然后放入土豆 和小半碗水 让…

JeecgBoot低代码开发—Vue3版前端入门教程

JeecgBoot低代码开发—Vue3版前端入门教程 后端接口配置VUE3 必备知识1.vue3新特性a. https://v3.cn.vuejs.org/b.setup的用法c.ref 和 reactive 的用法d.新版 v-model 的用法e.script setup的用法 2.TypeScript基础 后端接口配置 如何修改后台项目路径 http://127.168.3.52:8…

【玩转 EdgeOne】| 腾讯云下一代边缘加速CDN EdgeOne 是安全加速界的未来吗?

目录 前言边缘加速与安全加固边缘计算与CDN的融合EdgeOne优秀的安全特性EdgeOne卓越的性能表现灵活的配置和管理生态系统的支持与发展技术创新与未来展望EdgeOne试用结束语 前言 在当下互联网的迅猛发展的时刻&#xff0c;云计算和边缘计算技术的快速发展为网络加速领域带来了…

awk从放弃到入门(10):awk内置函数

awk从放弃到入门&#xff08;10&#xff09;&#xff1a;awk内置函数 算数函数字符串函数其他函数 本博文转载自 这篇文章中的知识点是建立在前文的基础上的&#xff0c;如果你还没有掌握前文中的知识&#xff0c;请先参考之前的文章。 注&#xff1a;在阅读这篇文章之前&…

Abbyy FineReader16最新版本有哪些新功能?

在数字化时代&#xff0c;数据处理和转换变得非常重要&#xff0c;Abbyy FineReader 就是一款专门用于处理、转换和识别图像和 PDF 文件的软件。在本文中&#xff0c;我们将会详细介绍 Abbyy FineReader 的功能以及适合使用该软件的电脑。 ABBYY Finereader 16-安装包下载如下&…

滴滴2023.11.27P0级故障技术复盘回顾(k8s的的错?)

本文从滴滴官方恢复及技术公众号带大家从技术角度复盘这次事故 目录 1. 背景 2. 滴滴官方消息 3. 问题分析及定位 4.网传的k8s及解析 5.k8s引发的思考&#xff1a;举一反三&#xff0c;怎么避免再次出现 6.近段时间其他平台崩溃回顾 1. 背景 11 月 27 晚约 10 点&#xf…

TFIDF、BM25、编辑距离、倒排索引

TFIDF TF刻画了词语t对某篇文档的重要性&#xff0c;IDF刻画了词语t对整个文档集的重要性

最简单的链路追踪收集器

链路追踪可帮助您快速了解程序服务之间的调用关系&#xff0c;并快速洞悉内部发生的情况。主流的链路追踪系统有zipkin,jaeger,skywalking等&#xff0c;由于opentelemetry的存在&#xff0c;都具有opentelemetry的转换器。 我们利用opentelemetry来进行zipkin,jaeger,skywalk…

智能优化算法应用:基于生物地理学算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于生物地理学算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于生物地理学算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.生物地理学算法4.实验参数设定5.算法结果…