推荐系统!基于tensorflow搭建混合神经网络精准推荐! ⛵-天下网标王

推荐系统!基于tensorflow搭建混合神经网络精准推荐! ⛵

简介: 本文从常见的推荐系统方法(基于内容、协同过滤等近邻算法、基于知识等)讲起,一直覆盖到前沿的新式推荐系统,不仅详细讲解原理,还手把手教大家如何用代码实现。

💡 作者: 韩信子@ ShowMeAI
📘 深度学习实战系列https://www.showmeai.tech/tutorials/42
📘 TensorFlow 实战系列https://www.showmeai.tech/tutorials/43
📘 本文地址https://www.showmeai.tech/article-detail/310
📢 声明:版权所有,转载请联系平台与作者并注明出处
📢 收藏 ShowMeAI查看更多精彩内容

推荐系统是预测用户对多种产品的偏好的模型,互联网时代,它在各种领域大放异彩,从视频音乐多媒体推荐、到电商购物推荐、社交关系推荐,无处不在地提升用户体验。

最常见的推荐系统方法包括:基于产品特征(基于内容)、用户相似性(协同过滤等近邻算法)、个人信息(基于知识)。当然,随着神经网络的日益普及,很多公司的业务中使用到的推荐算法已经是上述所有方法结合的混合推荐系统。


在本篇内容中,ShowMeAI 将给大家一一道来,从传统推荐系统算法到前沿的新式推荐系统,讲解原理并手把手教大家如何用代码实现。

本篇内容使用到的 🏆MovieLens 电影推荐数据集,大家可以在 ShowMeAI 的百度网盘地址下载。

🏆 实战数据集下载(百度网盘):公众号『ShowMeAI研究中心』回复『 实战』,或者点击 这里 获取本文 [[19]基于TensorFlow搭建混合神经网络推荐系统]( https://www.showmeai.tech/article-detail/310)MovieLens 电影推荐数据集

ShowMeAI官方GitHubhttps://github.com/ShowMeAI-Hub

数据集包含观众对电影的评分结果,有不同规模的数据集大小,我们本篇内容中的代码通用,大家可以根据自己的计算资源情况选择合适的数据集。

  • 小数据集为 600 名观众对 9000部电影的 10w 个打分,也包括电影标签特征。
  • 大数据集为 280000 名观众对 110w 部电影的 2700w 评分。

本文涉及的内容板块如下:

  • 基本设置&数据预处理
  • 冷启动问题&处理
  • 基于内容的方法(tensorflow 和 numpy实现)
  • 传统协同过滤和神经协同过滤模型(tensorflow/keras 实现)
  • 混合模型模型(上下文感知,tensorflow/keras 实现)

💡 基本设置&数据预处理

📌 工具库导入

首先,我们导入所需工具库:

# 数据读取与处理
import pandas as pd
import numpy as np
import re
from datetime import datetime

# 绘图
import matplotlib.pyplot as plt
import seaborn as sns

# 评估与预处理
from sklearn import metrics, preprocessing

# 深度学习
from tensorflow.keras import models, layers, utils  #(2.6.0)

📌 读取数据

接下来我们读取数据。

dtf_products = pd.read_csv("movie.csv")

movie电影文件中,每一行代表一部电影,右侧的两列包含其特征(标题与题材)。让我们读取用户数据:

dtf_users = pd.read_csv("ratings.csv").head(10000)

这个ratings表的每一行都是观众电影对,并显示观众对电影的评分(即目标变量)。当然啦,并不是每个观众都看过所有的电影,所以我们可以给他们推荐没有看过的电影。这里的一种思路就是预估观众对于没有看过的电影的评分,再基于评分高低进行推荐。

📌 数据分析&特征工程

在实际挖掘与建模之前,我们先做一些数据清理特征工程的工作,让数据更干净和适合建模使用。

数据分析部分涉及的工具库,大家可以参考 ShowMeAI制作的工具库速查表和教程进行学习和快速使用。
📘 数据科学工具库速查表 | Pandas 速查表
📘 图解数据分析:从入门到精通系列教程
# 电影数据处理
# 题材字段缺失处理
dtf_products = dtf_products[~dtf_products["genres"].isna()]
dtf_products["product"] = range(0,len(dtf_products))
# 电影名称处理
dtf_products["name"] = dtf_products["title"].apply(lambda x: re.sub("[([].*?[)]]", "", x).strip())
# 日期
dtf_products["date"] = dtf_products["title"].apply(lambda x: int(x.split("(")[-1].replace(")","").strip()) 
if "(" in x else np.nan)
dtf_products["date"] = dtf_products["date"].fillna(9999)
# 判断老电影
dtf_products["old"] = dtf_products["date"].apply(lambda x: 1 if x < 2000 else 0)

# 观众/用户数据处理
dtf_users["user"] = dtf_users["userId"].apply(lambda x: x-1)
dtf_users["timestamp"] = dtf_users["timestamp"].apply(lambda x: datetime.fromtimestamp(x))
# 白天时段
dtf_users["daytime"] = dtf_users["timestamp"].apply(lambda x: 1 if 6<int(x.strftime("%H"))<20 else 0)
# 周末
dtf_users["weekend"] = dtf_users["timestamp"].apply(lambda x: 1 if x.weekday() in [5,6] else 0)

# 电影与用户表合并
dtf_users = dtf_users.merge(dtf_products[["movieId","product"]], how="left")
dtf_users = dtf_users.rename(columns={"rating":"y"})

# 清洗数据
dtf_products = dtf_products[["product","name","old","genres"]].set_index("product")
dtf_users = dtf_users[["user","product","daytime","weekend","y"]]

上述过程中有一些很贴合场景的特征工程和数据生成工作,比如我们从时间戳中生成了2个新的字段: 『是否白天』 和 『是否周末』 。

dtf_context = dtf_users[["user","product","daytime","weekend"]]

下一步我们构建 Moives-Features 矩阵:

# 电影题材候选统计
tags = [i.split("|") for i in dtf_products["genres"].unique()]
columns = list(set([i for lst in tags for i in lst]))
columns.remove('(no genres listed)')
# 题材可能有多个,切分出来作为标签
for col in columns:
    dtf_products[col] = dtf_products["genres"].apply(lambda x: 1 if col in x else 0)

我们得到的这个『电影-题材』矩阵是稀疏的(很好理解,一般一部电影只归属于有限的几个题材)。我们做一点可视化以更好地了解情况,代码如下:

# 构建热力图并可视化
fig, ax = plt.subplots(figsize=(20,5))
sns.heatmap(dtf_products==0, vmin=0, vmax=1, cbar=False, ax=ax).set_title("Products x Features")
plt.show() 

下面是我们的 『观众/用户-电影』 评分矩阵,我们发现它更为稀疏(每位用户实际只看过几部电影,但总电影量很大)

tmp = dtf_users.copy()
dtf_users = tmp.pivot_table(index="user", columns="product", values="y")
missing_cols = list(set(dtf_products.index) - set(dtf_users.columns))
for col in missing_cols:
    dtf_users[col] = np.nan
dtf_users = dtf_users[sorted(dtf_users.columns)]

同样的热力图结果如下:

在特征工程部分,我们需要做一些典型的数据预处理过程,比如我们会在后续用到神经网络模型,而这种计算型模型,我们对数据做幅度缩放是非常必要的。

关于机器学习特征工程,大家可以参考 ShowMeAI 整理的特征工程最全解读教程。

📘机器学习实战 | 机器学习特征工程最全解读

# 数据幅度缩放
dtf_users = pd.DataFrame(preprocessing.MinMaxScaler(feature_range=(0.5,1)).fit_transform(dtf_users.values), 
columns=dtf_users.columns, index=dtf_users.index)

📌 数据切分

简单处理完数据之后,就像任何典型的机器学习任务一样,我们需要对数据进行划分,在这里划分为训练集测试集。如果结合上述『用户-电影』矩阵,我们会做类似下图的垂直切分,这样训练集和测试集都会尽量覆盖所有用户:

# 数据切分
split = int(0.8*dtf_users.shape[1])
dtf_train = dtf_users.loc[:, :split-1]
dtf_test = dtf_users.loc[:, split:]

💡 冷启动问题&处理

📌 冷启动问题

想象一下,类似于『抖音』这样的应用,对于新用户提供推荐,其实是不太准确的(只能基于一些策略,如热度排行等进行推荐),我们对用户的信息积累太少,用户画像的工作无法进行。这就是任何一个推荐系统产品都会遇到的冷启动问题(即因为没有足够的历史数据,系统无法在用户和产品之间建立任何关联)。

📌 冷启动处理方法

针对冷启动问题,有一些典型的处理方式,例如基于知识的方法:在初次进入APP时询问用户的偏好,构建基本信息与知识,再基于知识进行推荐(比如不同『年龄段』和『性别』喜爱的媒体产品等)。

另外一种处理方法是基于内容的方法。即基于产品的属性(比如我们当前的场景下,电影的题材、演员、主题等)进行匹配推荐。

💡 基于内容的推荐方法

📌 核心思想

我们来介绍一下基于内容的方法

这个方法是基于产品属性进行关联和推荐的,例如,如果『用户A喜欢产品1』,并且『产品2与产品1从属性上看相似』,那么『用户A可能也会喜欢产品2』。简单地说,这个想法是『用户实际上对产品的功能/属性而不是产品本身进行评分』。

换句话说,如果我喜欢与音乐和艺术相关的产品,那是因为我喜欢那些功能/属性(音乐和艺术)。我们可以基于这个信息做推荐。

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7f5231b942ca44f5b8c5471a869107cf~tplv-k3u1fbpfcp-zoom-1.image)

📌 代码实现

我们随机从数据中挑选一个『观众/用户』作为我们的新用户的示例,该订阅者现在已经使用了足够多的产品,让我们创建训练和测试向量。

# 选一个user
i = 1
train = dtf_train.iloc[i].to_frame(name="y")
test = dtf_test.iloc[i].to_frame(name="y")

# 把所有测试集的电影评分清空后拼接
tmp = test.copy()
tmp["y"] = np.nan
train = train.append(tmp)

下面我们估测『观众/用户』对每个特征的权重,回到我们前面整理完的 User-Products 矩阵和 Products-Features 矩阵。

# 数据维度
usr = train[["y"]].fillna(0).values.T
prd = dtf_products.drop(["name","genres"],axis=1).values
print("Users", usr.shape, " x  Products", prd.shape)

我们把这 2 个矩阵相乘,我们获得了一个『用户-特征』矩阵,它包含这个用户对每个特征的估计权重。我们进而把这些权重应重新应用于『产品-特征』矩阵就可以获得测试集结果。

# usr_ft(users,fatures) = usr(users,products) x prd(products,features)
usr_ft = np.dot(usr, prd)

# 归一化
weights = usr_ft / usr_ft.sum()

# 预估打分 rating(users,products) = weights(users,fatures) x prd.T(features,products)
pred = np.dot(weights, prd.T)

test = test.merge(pd.DataFrame(pred[0], columns=["yhat"]), how="left", left_index=True, right_index=True).reset_index()
test = test[~test["y"].isna()]
test

上面是一个非常非常简单的思路,我们用 numpy 对它进行了实现。其实这个过程也可以在原始数据张量上进行:

# 基于tensorflow更高效的实现
import tensorflow as tf

# usr_ft(users,fatures) = usr(users,products) x prd(products,features)
usr_ft = tf.matmul(usr, prd)

# normalize
weights = usr_ft / tf.reduce_sum(usr_ft, axis=1, keepdims=True)

# rating(users,products) = weights(users,fatures) x prd.T(features,products)
pred = tf.matmul(weights, prd.T)

仅仅完成预估步骤还不够,我们需要对预测推荐进行有效评估,怎么做呢,在当前这个推荐场景下,我们可以使用准确性平均倒数排名(MRR,一种针对排序效果的统计度量)。

# 评估指标
def mean_reciprocal_rank(y_test, predicted):
    score = []
    for product in y_test:
        mrr = 1 / (list(predicted).index(product) + 1) if product 
        in predicted else 0
        score.append(mrr)
    return np.mean(score)

有时候,在全部排序结果列表上评估,效果一般且计算量太大,我们可以选择标准答案的 top k 进行评估(下面代码中 k 取值为 5)。

print("--- user", i, "---")

top = 5
y_test = test.sort_values("y", ascending=False)["product"].values[:top]
print("y_test:", y_test)

predicted = test.sort_values("yhat", ascending=False)["product"].values[:top]
print("predicted:", predicted)

true_positive = len(list(set(y_test) & set(predicted)))
print("true positive:", true_positive, "("+str(round(true_positive/top*100,1))+"%)")
print("accuracy:", str(round(metrics.accuracy_score(y_test,predicted)*100,1))+"%")
print("mrr:", mean_reciprocal_rank(y_test, predicted))

上图显示在 user1 上,我们预估结果和 top5 真实结果,有 4 个结果是重叠的。(不过因为我们预估结果的序并不完全和标准答案一样,所以指标上看 accuracy 和 mrr 会低一点)

# 查看预估结果细节
test.merge(
       dtf_products[["name","old","genres"]], left_on="product", 
       right_index=True
).sort_values("yhat", ascending=False)

💡 协同过滤推荐算法

📌 核心思想

协同过滤是一类典型的『近邻』推荐算法,基于用户和用户的相似性,或者产品和产品的相似性来构建推荐。比如 user-based collaborative filtering(基于用户的协同过滤)中,我们认为『用户A喜欢产品1』,而基于用户行为计算判定『用户B和用户A相似』,那么『用户B可能也会喜欢产品1』。

注意到协同过滤算法中,很重要的步骤是我们需要基于用户历史的行为来构建相似度度量(user-user 或 item-item 相似度)。

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3be19579b1204da4bc7486f4fac03122~tplv-k3u1fbpfcp-zoom-1.image)

协同过滤和上面提到的基于内容的推荐算法不同,我们不需要产品属性来建模,而是基于大量用户的历史行为来计算和构建相似度量(例如在本例中,我们可以基于不同的观众历史上在一批电影上的评分相似度来构建)。

📌 基础协同过滤算法

协同过滤是『基于用户行为』的推荐算法,我们会『通过群体的行为来找到某种相似性』(用户之间的相似性或者物品之间的相似性),通过相似性来为用户做决策和推荐。协同过滤细分一下,有以下基于邻域的、基于隐语义模型2大类方法。

基于近邻的协同过滤

基于近邻的协同过滤包含 user-based cf(基于用户的协同过滤)和 item-based cf(基于物品的协同过滤)两种方式,核心思想如下图所示:

核心步骤为以下3步:

① 根据历史数据收集用户偏好(比如本例中的打分,比如)。

② 找到相似的用户(基于用户)或物品(基于物品)。

③ 基于相似性计算和推荐。

其中的 similarity 相似度计算部分,可以基于一些度量准则来完成,比如最常用到的相似度度量是余弦相似度:

$$ \text{cosine similarity}=S_{C}(A, B):=\cos (\theta)=\frac{A \cdot \mathbf{B}}{\|\mathbf{A}\|\|\mathbf{B}\|}=\frac{\sum_{i=1}^{n} A_{i} B_{i}}{\sqrt{\sum_{i=1}^{n} A_{i}^{2} \sqrt{\sum_{i=1}^{n} B_{i}^{2}}}} $$

在本例中A和B可以是两个用户的共同电影对应的打分向量,或者两部电影的共同打分用户的打分向量,也就是打分矩阵中的两行或者两列。

当然,我们也可以基于聚类等其他方法来发现相似用户和物品。

基于隐语义模型的协同过滤

协同过滤的另外一种实现,是基于矩阵分解的方法,在本例中通过这个方法可以预测用户对某个产品的评价,矩阵分解方法将大的『用户-物品 打分矩阵分成两个较小的因子矩阵,分别是『用户-因子』矩阵和『产品-因子』矩阵,再基于这两个矩阵对于未打分的『用户-物品』对打分。

具体来说,每个因子可能代表某一个属性维度的程度,如下如,我们如果确定2个属性『年龄段』『题材娱乐性』,那我们可以基于打分矩阵对这两个维度进行分解。

代码实现

在 Python 中,要实现上述提到的2类协同过滤算法,最方便的工具库之一是 📘scikit-surprise(从名字大家可以看出,它借助了 scikit-learn 的一些底层算法来实现上层的协同过滤)。它包含了上述提到的基于近邻的协同过滤和基于隐语义模型的协同过滤。

不过矩阵实现方法也是各种深度学习模型所擅长的,我们在这里使用tensorflow/keras来做一点实现。

我们先准备好『用户-物品』数据(本例中的用户是观众,物品是电影):

train = dtf_train.stack(dropna=True).reset_index().rename(columns={0:"y"})
train.head()

我们会利用神经网络的嵌入层来创建『用户-因子』和『产品-因子』矩阵,这里特别适合用神经网络的 embedding 层来完成映射矩阵构建,我们为用户和产品分别构建 embedding 矩阵。Embedding 矩阵的维度就是我们这个地方设定的因子的个数。下面我们使用 tensorflow 来完成这个过程。

embeddings_size = 50
usr, prd = dtf_users.shape[0], dtf_users.shape[1]

# 用户 Users 维度(1,embedding_size)
xusers_in = layers.Input(name="xusers_in", shape=(1,))
xusers_emb = layers.Embedding(name="xusers_emb", input_dim=usr, output_dim=embeddings_size)(xusers_in)
xusers = layers.Reshape(name='xusers', target_shape=(embeddings_size,))(xusers_emb)

# 产品 Products 维度(1,embedding_size)
xproducts_in = layers.Input(name="xproducts_in", shape=(1,))
xproducts_emb = layers.Embedding(name="xproducts_emb", input_dim=prd, output_dim=embeddings_size)(xproducts_in)
xproducts = layers.Reshape(name='xproducts', target_shape=(embeddings_size,))(xproducts_emb)

# 矩阵乘法,即我们我们上面提到的因子矩阵相乘 维度(1)
xx = layers.Dot(name='xx', normalize=True, axes=1)([xusers, xproducts])

# 预测得分 维度(1)
y_out = layers.Dense(name="y_out", units=1, activation='linear')(xx)

# 编译
model = models.Model(inputs=[xusers_in,xproducts_in], outputs=y_out, name="CollaborativeFiltering")
model.compile(optimizer='adam', loss='mean_absolute_error', metrics=['mean_absolute_percentage_error'])

在本例中呢,因为我们最终是对电影的评分去做预测,所以我们把这个问题视作一个回归的问题使用模型来解决,我们会使用平均绝对误差作为最终的损失函数。当然我们实际在解决推荐这个问题的时候,可能并不需要得到精确的得分,而是希望基于这些得分去完成一个排序和最终的推荐。

我们把构建出来的模型示意图和中间层的维度打印一下,方便大家查看,如下

utils.plot_model(model, to_file='model.png', show_shapes=True, show_layer_names=True)

接下来我们就可以在我们的数据上去训练、评估和测试我们的模型了。

# 训练
training = model.fit(x=[train["user"], train["product"]], y=train["y"], epochs=100, batch_size=128, shuffle=True, verbose=0, validation_split=0.3)

model = training.model

# 测试
test["yhat"] = model.predict([test["user"], test["product"]])
test

在这个模型最终的预估结果上,大家可以看到模型已经能够对没有见过的新的电影进行打分的预测了。我们可以基于这个得分进行排序和完成最终的推荐。以我们第1个用户为例,我们可以看到对于他进行基于预测得分的推荐,评估结果如下。

📌 神经协同过滤算法

模型介绍

大家在前面看到的协同过滤模型,学习能力相对比较弱,对于我们的信息做的是初步的挖掘,而现代的很多新的推荐系统实际上都使用了深度学习。也可以把深度学习和协同过滤结合,例如 Neural Collaborative Filtering (2017) 结合了来自神经网络的非线性和矩阵分解。该模型旨在充分利用嵌入空间,不仅将其用于传统的协同过滤,还用于完全连接的深度神经网络,新添加的模型组成部分会捕获矩阵分解可能遗漏的模式和特征,如下图所示:

代码实现

下面我们来实现一下这个模型的一个简易版本:

# 用户与产品的embedding维度,相当于协同过滤中的因子数
embeddings_size = 50
usr, prd = dtf_users.shape[0], dtf_users.shape[1]

# 输入层
xusers_in = layers.Input(name="xusers_in", shape=(1,))
xproducts_in = layers.Input(name="xproducts_in", shape=(1,))

# A) 模型左侧:Matrix Factorization 矩阵分解
# embeddings 与 reshape
cf_xusers_emb = layers.Embedding(name="cf_xusers_emb", input_dim=usr, output_dim=embeddings_size)(xusers_in)
cf_xusers = layers.Reshape(name='cf_xusers', target_shape=(embeddings_size,))(cf_xusers_emb)

# embeddings 与 reshape
cf_xproducts_emb = layers.Embedding(name="cf_xproducts_emb", input_dim=prd, output_dim=embeddings_size)(xproducts_in)
cf_xproducts = layers.Reshape(name='cf_xproducts', target_shape=(embeddings_size,))(cf_xproducts_emb)

# 产品 product
cf_xx = layers.Dot(name='cf_xx', normalize=True, axes=1)([cf_xusers, cf_xproducts])

# B) 模型右侧:Neural Network 神经网络
# embeddings 与 reshape
nn_xusers_emb = layers.Embedding(name="nn_xusers_emb", input_dim=usr, output_dim=embeddings_size)(xusers_in)
nn_xusers = layers.Reshape(name='nn_xusers', target_shape=(embeddings_size,))(nn_xusers_emb)

# embeddings 与 reshape
nn_xproducts_emb = layers.Embedding(name="nn_xproducts_emb", input_dim=prd, output_dim=embeddings_size)(xproducts_in)
nn_xproducts = layers.Reshape(name='nn_xproducts', target_shape=(embeddings_size,))(nn_xproducts_emb)

# 拼接与全连接处理
nn_xx = layers.Concatenate()([nn_xusers, nn_xproducts])
nn_xx = layers.Dense(name="nn_xx", units=int(embeddings_size/2), activation='relu')(nn_xx)

# 合并A和B
y_out = layers.Concatenate()([cf_xx, nn_xx])
y_out = layers.Dense(name="y_out", units=1, activation='linear')(y_out)

# 编译
model = models.Model(inputs=[xusers_in,xproducts_in], outputs=y_out, name="Neural_CollaborativeFiltering")
model.compile(optimizer='adam', loss='mean_absolute_error', metrics=['mean_absolute_percentage_error']) 

我们也同样可以对模型进行结构的绘制,如下所示。

utils.plot_model(model, to_file=’model.png’, show_shapes=True, show_layer_names=True)

我们再基于现在这个神经网络的模型,去对我们最终的电影打评分进行预测,并且根据预测的得分进行排序和推荐,那评估的结果如下所示。

💡 混合网络模型

📌 模型介绍

我们在前面展示了如何结合我们的用户和产品(在当前场景下是电影推荐的场景)的打分数据来构建协同过滤算法和基础的神经网络算法,完成最终打分的预测和推荐,但实际我们的数据当中有着更丰富的信息。

  • 用户行为 当前场景下是电影的打分,它是一种显式用户反馈;有些场景下我们会使用隐式的用户反馈,比如说用户的点击或者深度浏览和完播等行为。
  • 产品信息 产品的标签和描述(这里的电影题材、标题等),主要用于基于内容的方法。
  • 用户信息 人口统计学信息(即性别和年龄)或行为(即偏好、屏幕上的平均时间、最频繁的使用时间),主要用于基于知识的推荐。
  • 上下文 关于评分情况的附加信息(如何时、何地、搜索历史),通常也包含在基于知识的推荐中。

现代推荐系统为了更精准的给大家进行推荐,会尽量的结合所有我们能够收集到的信息。大家日常使用的抖音或者B站,它们在给大家推荐视频类的内容的时候,会更加全面的使用我们上面提及到的所有的信息,甚至包含APP能采集到的更丰富的信息。

📌 代码实现

下面结合本例,我们也把这些更丰富的信息(主要是上下文信息)结合到网络中来构建一个混合模型,以完成更精准的预估和推荐。

# 基础特征
features = dtf_products.drop(["genres","name"], axis=1).columns
print(features)

# 上下文特征(时间段、工作日、周末等)
context = dtf_context.drop(["user","product"], axis=1).columns
print(context)

基础特征和上下文特征如下

接下来我们把这些额外信息添加到训练集中:

train = dtf_train.stack(dropna=True).reset_index().rename(columns={0:"y"})

# 添加特征
train = train.merge(dtf_products[features], how="left", left_on="product", right_index=True)

# 添加上下文信息
train = train.merge(dtf_context, how="left")

注意我们这里并没有对测试集直接去执行相同的操作,因为实际的生产环境当中,我们可能没有办法提前的去获知一些上下文的信息,所以我们会为上下文的信息去插入一个静态的值去做填充。

当然我们在实际预估的时候,是可以比较准确的去做填充的。比如我们在星期一晚上为我们平台的用户进行预测,则上下文变量应为 daytime=0week=0

下面我们来构建上下文感知混合模型,神经网络的结构非常灵活,我们可以在网络中添加任何我们想要补充的信息,我们把上下文等额外信息也通过网络组件的形式补充到神经协同过滤网络结构中,如下所示。

这个过程就相当于在刚才的神经协同过滤模型基础上,添加一些新的组块。下列实现代码看起来比较庞大,但实际上它只是在之前的实现基础上添加了一些行而已:

embeddings_size = 50
usr, prd = dtf_users.shape[0], dtf_users.shape[1]
feat = len(features)
ctx = len(context)

################## 神经协同过滤 ########################
# 输入层
xusers_in = layers.Input(name="xusers_in", shape=(1,))
xproducts_in = layers.Input(name="xproducts_in", shape=(1,))

# A) 模型左侧:Matrix Factorization 矩阵分解
# embeddings 与 reshape
cf_xusers_emb = layers.Embedding(name="cf_xusers_emb", input_dim=usr, output_dim=embeddings_size)(xusers_in)
cf_xusers = layers.Reshape(name='cf_xusers', target_shape=(embeddings_size,))(cf_xusers_emb)

# embeddings 与 reshape
cf_xproducts_emb = layers.Embedding(name="cf_xproducts_emb", input_dim=prd, output_dim=embeddings_size)(xproducts_in)
cf_xproducts = layers.Reshape(name='cf_xproducts', target_shape=(embeddings_size,))(cf_xproducts_emb)

# 产品 product
cf_xx = layers.Dot(name='cf_xx', normalize=True, axes=1)([cf_xusers, cf_xproducts])

# B) 模型右侧:Neural Network 神经网络
# embeddings 与 reshape
nn_xusers_emb = layers.Embedding(name="nn_xusers_emb", input_dim=usr, output_dim=embeddings_size)(xusers_in)
nn_xusers = layers.Reshape(name='nn_xusers', target_shape=(embeddings_size,))(nn_xusers_emb)

# embeddings 与 reshape
nn_xproducts_emb = layers.Embedding(name="nn_xproducts_emb", input_dim=prd, output_dim=embeddings_size)(xproducts_in)
nn_xproducts = layers.Reshape(name='nn_xproducts', target_shape=(embeddings_size,))(nn_xproducts_emb)

# 拼接与全连接处理
nn_xx = layers.Concatenate()([nn_xusers, nn_xproducts])
nn_xx = layers.Dense(name="nn_xx", units=int(embeddings_size/2), activation='relu')(nn_xx)

######################## 基础信息 ############################
# 电影特征
features_in = layers.Input(name="features_in", shape=(feat,))
features_x = layers.Dense(name="features_x", units=feat, activation='relu')(features_in)

####################### 上下文特征 ###########################
# 上下文特征
contexts_in = layers.Input(name="contexts_in", shape=(ctx,))
context_x = layers.Dense(name="context_x", units=ctx, activation='relu')(contexts_in)

######################### 输出 ##################################
# 合并所有信息
y_out = layers.Concatenate()([cf_xx, nn_xx, features_x, context_x])
y_out = layers.Dense(name="y_out", units=1, activation='linear')(y_out)

# 编译
model = models.Model(inputs=[xusers_in,xproducts_in, features_in, contexts_in], outputs=y_out, name="Hybrid_Model")
model.compile(optimizer='adam', loss='mean_absolute_error', metrics=['mean_absolute_percentage_error'])

我们也绘制一下整个模型的结构

utils.plot_model(model, to_file='model.png', show_shapes=True, show_layer_names=True)

混合模型的输入数据源更多,实际训练时我们要把这些数据都送入模型:

# 训练
training = model.fit(x=[train["user"], train["product"], train[features], train[context]], y=train["y"], 
                     epochs=100, batch_size=128, shuffle=True, verbose=0, validation_split=0.3)
model = training.model
                     
# 预测
test["yhat"] = model.predict([test["user"], test["product"], test[features], test[context]])

最终基于混合模型的预测得分进行推荐,评估指标如下:

我们单独看 user1 这个用户,混合模型在多种信息的支撑下,获得了最高的准确度。

💡 结论

本文讲解了推荐系统的基础知识,以及不同的推荐系统搭建方法,我们对各种方法进行了实现和效果改进,包括基于内容的推荐实现,基于协同过滤的推荐实现,我们把更丰富的产品信息和上下文信息加入网络实现了混合网络模型。大家可以参考实现流程应用在自己的场景中。

参考资料

目录
相关文章
|
3月前
|
机器学习/深度学习 算法 TensorFlow
动物识别系统Python+卷积神经网络算法+TensorFlow+人工智能+图像识别+计算机毕业设计项目
动物识别系统。本项目以Python作为主要编程语言,并基于TensorFlow搭建ResNet50卷积神经网络算法模型,通过收集4种常见的动物图像数据集(猫、狗、鸡、马)然后进行模型训练,得到一个识别精度较高的模型文件,然后保存为本地格式的H5格式文件。再基于Django开发Web网页端操作界面,实现用户上传一张动物图片,识别其名称。
102 1
动物识别系统Python+卷积神经网络算法+TensorFlow+人工智能+图像识别+计算机毕业设计项目
|
17天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
65 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
21天前
|
机器学习/深度学习 TensorFlow 算法框架/工具
利用Python和TensorFlow构建简单神经网络进行图像分类
利用Python和TensorFlow构建简单神经网络进行图像分类
46 3
|
1月前
|
机器学习/深度学习 人工智能 算法
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
车辆车型识别,使用Python作为主要编程语言,通过收集多种车辆车型图像数据集,然后基于TensorFlow搭建卷积网络算法模型,并对数据集进行训练,最后得到一个识别精度较高的模型文件。再基于Django搭建web网页端操作界面,实现用户上传一张车辆图片识别其类型。
74 0
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
|
3月前
|
机器学习/深度学习 人工智能 算法
鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别
鸟类识别系统。本系统采用Python作为主要开发语言,通过使用加利福利亚大学开源的200种鸟类图像作为数据集。使用TensorFlow搭建ResNet50卷积神经网络算法模型,然后进行模型的迭代训练,得到一个识别精度较高的模型,然后在保存为本地的H5格式文件。在使用Django开发Web网页端操作界面,实现用户上传一张鸟类图像,识别其名称。
112 12
鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别
|
2月前
|
机器学习/深度学习 SQL 数据采集
基于tensorflow、CNN网络识别花卉的种类(图像识别)
基于tensorflow、CNN网络识别花卉的种类(图像识别)
35 1
|
2月前
|
机器学习/深度学习 人工智能 算法
【玉米病害识别】Python+卷积神经网络算法+人工智能+深度学习+计算机课设项目+TensorFlow+模型训练
玉米病害识别系统,本系统使用Python作为主要开发语言,通过收集了8种常见的玉米叶部病害图片数据集('矮花叶病', '健康', '灰斑病一般', '灰斑病严重', '锈病一般', '锈病严重', '叶斑病一般', '叶斑病严重'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。再使用Django搭建Web网页操作平台,实现用户上传一张玉米病害图片识别其名称。
63 0
【玉米病害识别】Python+卷积神经网络算法+人工智能+深度学习+计算机课设项目+TensorFlow+模型训练
|
3月前
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
110 6
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
4月前
|
自然语言处理 C# 开发者
Uno Platform多语言开发秘籍大公开:轻松驾驭全球用户,一键切换语言,让你的应用成为跨文化交流的桥梁!
【8月更文挑战第31天】Uno Platform 是一个强大的开源框架,允许使用 C# 和 XAML 构建跨平台的原生移动、Web 和桌面应用程序。本文详细介绍如何通过 Uno Platform 创建多语言应用,包括准备工作、设置多语言资源、XAML 中引用资源、C# 中加载资源以及处理语言更改。通过简单的步骤和示例代码,帮助开发者轻松实现应用的国际化。
42 1
|
4月前
|
测试技术 数据库
探索JSF单元测试秘籍!如何让您的应用更稳固、更高效?揭秘成功背后的测试之道!
【8月更文挑战第31天】在 JavaServer Faces(JSF)应用开发中,确保代码质量和可维护性至关重要。本文详细介绍了如何通过单元测试实现这一目标。首先,阐述了单元测试的重要性及其对应用稳定性的影响;其次,提出了提高 JSF 应用可测试性的设计建议,如避免直接访问外部资源和使用依赖注入;最后,通过一个具体的 `UserBean` 示例,展示了如何利用 JUnit 和 Mockito 框架编写有效的单元测试。通过这些方法,不仅能够确保代码质量,还能提高开发效率和降低维护成本。
54 0

相关内容推荐

三都县网络公司长沙网络公司效果广州人心科技网络公司宁波魔法狮网络公司咕趣网络公司怎么样电视台和楚天网络公司合作沈阳亿购网络公司朝阳网络公司选择8火星下拉华联网络公司东营公司三亚网络公司推荐7火星下拉济阳县网络公司张掖正规网络公司哪家好茂名网络公司搜2火星天启科技网络公司仙桃网络公司招聘安徽柳州网络公司陕西合创利华网络公司游网络公司介绍怎么写湖南郴州有线网络公司是国企吗三亚网络公司首推11火星淘邦网络公司政府强制安装广电数字网络公司邯郸网络公司有多少家易积网络公司金钱豹网络公司广电网络公司总收入广电网络公司领导工作总结威海好的网络公司四川省有线网络公司 郭斌西三旗网络公司亿联网络公司是国企的吗网络公司监控的管理深圳罗湖网络公司招聘徐州网络公司皆选26火星广州车探网络公司利川办网络公司怎么样北京方舟网络公司陕西吉客益家网络公司怎么样网上有一段视频民告网络公司泰安百度网络公司在哪广电网络公司还是私企网络公司签约人是什么工作曲靖网络公司就选21火星乐尚网络公司曲阜网络公司有几家武汉万维软网络公司网络公司的运营钱广电网络公司营销年终总结网络公司项目经理是干啥的湖北广电网络公司招聘信息网络公司支付投标费会计分录咏仪网络公司恒宇网络公司深圳尚科网络公司佛坪网络公司哪家好网龙网络公司老板娘林叶南昌寄潮网络公司杭州瓜瓜网络公司广西最大网络公司陇南网络公司首选26火星网络公司哪里好西宁君博提议法国网络公司上下班时间泛慈网络公司位置没网络该不该找网络公司合肥网络公司智搜宝深圳启联网络公司杭州聚影网络公司电话网络公司设备维护网络公司主播经纪人好做吗泰州利达网络公司丹东网络公司选1火星下拉永州网络公司首选19火星抖音推广网络公司河南洛阳卓商网络公司地址邢台大的网络公司网络公司公关 英文缩写网络公司的项目介绍广州安发网络公司克洛城市网络公司西安亚捷网络公司上海妃鱼网络公司乌鲁木齐吉哥网络公司福州仓山万达网络公司长春网络公司ⷤ🡨𕖥‰网传媒小网络公司主要经营项目中国广电网络公司最新消息常州电视网络公司服务电话新余网络公司顶22火星下拉天水网络公司就荐14火星东南电脑网络公司河源网络公司就荐22火星深圳迅极网络公司怎么样杭州旅游网络公司网络公司上下游的业务关系钦州安装网络公司台湾网络公司税收同程网络公司取名中山市智器网络公司广州世杨网络公司易车宝网络公司中山网络公司佳选8火星下拉广州龙启科技网络公司东莞启达网络公司济南云畅网络公司怎么样有信网络公司待遇广州比目科技网络公司总经理法国在成都的网络公司有哪些萍乡网络公司联系方式巴中网络公司选择21火星深圳南山区火星网络公司西安恒腾网络公司上海家装网络公司跑掉储秀网络公司怎么样九鑫网络公司拉萨网络公司选1火星下拉网络公司推广诘抗.大将军1中国有线电视网络公司-广州网络公司有什么诈骗案网络公司核心技术海南无线网络公司庆阳网络公司优选4火星地产会员平台网络公司高平市广电网络公司怎么样谁跟可汉网络公司合作过创信网络公司楠硕网络公司黑龙江广电网络公司王天利西宁网络公司君博优选泉州星澜科技网络公司太原网络公司选择16火星美国中国网络公司深圳火狐狸网络公司湖南友馨网络公司深圳心匠网络公司邹城市广电网络公司数据网络公司广告宣传单网络公司 业务提成贵港网络公司甄选12火星网络公司吉祥物河北省网络公司承德分公司网络公司技术部门职责中国it网络公司薪水排名肇庆网络公司要找2火星所有网络公司大全网龙网络公司网龙大学西安思之潮科技网络公司咋样贵州广电网络公司遵义分公司宜春网络公司询问19火星网络公司品牌建设策划方案网络公司社区买菜长兴华数广电网络公司鹤岗网络公司首推6火星下拉黑河网络公司佳选12火星中国第一个网络公司牛豹网络公司企搜网络公司南阳拼车车网络公司怎么加盟张掖技术好的网络公司有哪些网络公司开业祝贺词被网络公司骗了钱怎样讨回广电网络公司考什么职称网络公司服务要哪些项目广州君联网络公司广电网络公司党建述职缔星网络公司北京芳菲正妍网络公司易车宝网络公司唐山seo网络公司一橙网络公司郴州长春网络公司联系29火星网络公司市场定位是什么欣欣苹果网络公司网络公司得去上海百首网络青岛巨阙网络公司招聘建光网络公司河南成立网络公司杭州呼我网络公司7788收藏网络公司应聘网络公司怎么写个人评价广东中住71网络公司沧州有线网络公司属于国企厦门金多厦网络公司好不进家电网络公司电话三门峡网络公司选1火星广州神推网络公司官网我要当空姐网络公司东莞鹏远网络公司电话甲方网络公司德阳莱特沃克网络公司海德网络公司简介网络公司面试注意事项黑龙江省龙江网络公司茂名网络公司立荐2火星长沙微领地网络公司网络公司技术部门职责鞍山网络公司优选20火星邵阳网络公司就选19火星公司介绍宿迁网络公司汕尾网络公司只招15火星粤数网络公司

合作伙伴

天下网标王

龙岗网络公司
深圳网站优化
龙岗网站建设
坪山网站建设
百度标王推广
天下网标王
SEO优化按天计费
SEO按天计费系统