目录
一、协同过滤算法与基于内容过滤算法的对比
对于协同过滤,一般时我们根据用户给出的评分,算法会根据用户的评分,给用户推荐新的东西。(对于缺少信息的时候,比如一个用户只对很少电影进行评分,该给他推荐什么电影;或者有一部新电影没有人评分过,该向哪些用户推荐它。对于这些问题,使用协同过滤可能会出现预测不准的情况。)
使用协同过滤,一般方法是根据与目标用户给出相似评分的相似用户的评级给目标用户推荐项目。相比之下,基于内容的过滤采用不同的方法来向目标用户推荐。基于内容的过滤算法会根据用户的特征和物品的特征向目标用户推荐物品,以找到合适的匹配项。换句话说,需要每个用户的一些特则,以及每个项目的一些特则,使用这些特征来尝试决定哪些项目和用户可能彼此匹配。
使用基于内容过滤算法,它仍然有用户对某些项目进行评分的数据,所以它会像协同过滤一样,使用r(i ,j)表示用户j是否对项目i进行评分;y(i,j)用户j对项目i的评分是多少。不同的是基于内容过滤算法可以很好的利用用户和项目的特征来进行匹配。
基于内容的过滤算法的关键在于,能够充分利用用户和项目的特征来找到比纯粹的协同过滤算法可能更好的匹配。
对于用户的特征,例如年龄、性别、国籍等,依据这些用户数据可以得到一个特征向量来表示用户j的特征。对于电影的特征,例如上映时间、类型、评分等,依据这些电影的数据可以得到一个特征向量
来表示电影i的特征。给定这样的特征,任务是尝试弄清给定的电影i是否会与用户j很好的匹配。
暂时不考虑参数,不会对算法性能造成影响,将
和
替换为与用户j相关的向量
,和与电影i相关的向量
。
是一个向量,根据用户j的特征
计算的数字列表,而
是根据电影i的特征
计算得出的数字列表。对这两个向量
和
做出适当的选择,那么这两个向量之间的点积能够很好的预测用户j给电影i的评分。
notes:
基于内容的过滤是根据用户的特征来推荐的,协同过滤则是通过与用户评价相似的其他用户推荐的。
相当于用用户行为特征设计出系数向量w,用电影特征设计出x向量。
给定用户的特征,需要通过计算得到一个简洁或紧凑的向量
来表示用户的偏好。类似地给定电影的特征
,通过计算得到简洁紧凑的向量
来表示电影的特征。需要注意的是,虽然
和
的大小可能不同,但是这里的向量
和
必须具有相同的维度。
总之,在协同过滤算法中,有许多用户对不同项目进行评分,相反的是,在基于内容的过滤中,有用户的特征和项目的特征,目的是找到一种方法使用户和项目之间有良好的匹配。
二 、基于内容过滤的深度学习算法
1、定义
基于内容过滤的深度学习算法是一种利用深度学习技术实现的推荐算法。它的主要思想是利用用户过去的行为和偏好以及物品的内容特征,通过深度学习模型来预测用户对物品的兴趣度,并向用户推荐可能感兴趣的物品。
具体来说,基于内容过滤的深度学习算法一般分为以下几个步骤:
-
特征提取:首先需要对物品的内容进行特征提取。这一步通常是使用卷积神经网络(CNN)或循环神经网络(RNN)等深度学习模型提取物品的视觉、文本、音频或其他内容特征。
-
特征表示:将提取出的物品特征表示为向量形式。这可以通过将特征传递给全连接层或使用池化层来完成。
-
用户特征提取与表示:同样地,需要提取和表示用户的特征。这可以通过用户历史行为数据进行,比如用户评级和阅读历史等。
-
构建模型:将用户和物品的特征输入到深度学习模型中,以预测用户对物品的兴趣度。一般会选择一些常用的深度学习模型,比如多层感知机(MLP)、卷积神经网络(CNN)、循环神经网络(RNN)等,并使用反向传播算法进行优化。
-
推荐:根据预测的结果进行推荐,并将推荐结果反馈给用户。
基于内容过滤的深度学习算法具有一定的优点,包括可以利用物品的内容特征提高推荐效果,可以避免冷启动问题,同时也可以处理长尾问题。但是,它也存在一些不足之处,比如需要大量的物品内容和用户行为数据来训练模型,同时也可能存在一些过拟合和泛化能力不强的问题。
2、举例说明
给定一个描述用户的特征向量,例如年龄和性别、国家等,需要计算出向量,类似地,给定一个描述电影的向量,例如发行年份,类别等,需要计算出向量
。
神经网络通过将用户或者电影的特征 和
作为输入,然后使用几个层输出描述用户或者电影的向量
和
。最后,将预测用户对该电影的评分,为
和
的点积。
注意的是,假设用户网络和电影网络可以具有不同数量的隐藏层和每个隐藏层的不同数量的单元,但是所有输出层都需要具有相同尺寸的相同维度。
在以上的预测过程中,预测的是电影评级,如果有二进制标签,表示用户j是否喜欢第j项目,那么修改该网络的输出代替
,可以将sigmoid函数应用于此来预测
为1的概率。
上图中的用户网络和电影网络绘制为两个独立的神经网络,但是实际上可以绘制在一个图表中。
这个模型有许多参数,神经网络的每一层都有一组常用的神经网络参数,对于训练得到这些参数,可以构造一个代价函数J,跟协同过滤算法中看到的代价函数有点相似。训练这个模型的方式取决于神经网络的参数,提供已知的用户与电影的向量和
还有标签
,训练神经网络参数时,借助
与
的最小平方误差来得到合适的参数。
根据预测
的好坏来判断这个网络,并使用代价函数,使用梯度下降或其他一些优化算法来调整神经网络的参数导致代价函数J尽可能地小。也可以添加通常的神经网络正则化项,来对模型进行正则化保持参数值影响较小。
在训练了这个模型之后,可以用该模型寻找相似物品。
给定一部电影,向量描述了电影i的,如果像找到其他类似的电影,可以寻找其他电影k使得描述电影k的向量
与描述电影i的向量之间的平方距离很小。
notes:
可以在一夜之间运行一个计算服务器来遍历所有电影的列表,并为每部电影找到与之相似的电影,第二天用户访问该网站并且浏览特定的电影,已经预先计算出的10-20部电影就可以展示给用户。
该算法有一个局限性,如果有大量的电影需要推荐,对于电影的大目录,那么运行的成本就会非常高。
三、从大型目录中推荐
许多大型规模推荐系统的实现分为两个步骤,检索步骤和排名步骤。
在检索步骤中生成大量可能的项目候选者列表,试图涵盖可能向用户推荐的许多项目,然后在检索步骤中,如果包含太多用户可能不太喜欢的项目,那么在排名步骤中将微调并选择最好的项目推荐给用户。
检索步骤的目的是尽可能的确保广泛的覆盖范围,以便有足够的项目中,至少有一些好的项目。最后,将在检索步骤中获取到的所有项目组合到一个列表中,删除重复项,删除用户已经看多的项目。
排名步骤中,获取在检索步骤中得到的列表,使用学习模型对其排名,这意味着把用户特征向量和电影特征向量输入到这个神经网络中,并为每个用户-项目对计算预测评分,基于此获得的多数项目,是用户最有可能给予高评价的项目。
一项额外的优化是,如果提前为所有项目计算了特征向量v,那么需要做的就是在用户神经网络上进行一次推理,计算出特征向量。然后使用两个特征向量进行点积得到检索步骤得到的项目。
四、推荐系统中的伦理
推荐算法系统中的伦理问题是一个重要的话题,因为推荐算法的结果会直接影响到用户的购买决策。以下是推荐算法系统中存在的一些伦理问题:
-
偏见问题:推荐系统可能会基于用户的性别、种族、宗教信仰等因素,偏向某些商品或排斥某些商品,造成不同用户之间的不公平。
-
隐私问题:为了提高推荐准确性,推荐系统需要收集用户的个人信息、历史行为等数据。如果这些数据被滥用或泄露,将会对用户的隐私权产生威胁。
-
反人类问题:推荐系统可能会基于用户的历史行为、兴趣偏好等因素,过度推荐某些商品,从而使用户陷入信息过载的状态。
-
风险问题:推荐系统可能会疏忽一些可能存在较大风险的商品,例如低质量产品、不健康产品等,对用户的健康和利益构成威胁。
为了解决这些伦理问题,推荐算法系统需要尽可能保护用户的隐私,避免偏见问题,不过度推荐某些产品,同时也需要对推荐的商品进行风险评估,保护用户的安全和利益。
五、基于内容过滤的代码实现
代码如下所示,随机生成内容数据。
import random # 导入random模块,用于生成随机数
from prettytable import PrettyTable # 导入PrettyTable模块,用于创建漂亮的表格
# 随机生成用户历史行为数据
def generate_user_history(num_users, num_items):
user_history = {} # 创建一个空字典,用于存储用户历史行为数据
for user in range(num_users):
history = random.sample(range(num_items), random.randint(1, num_items//2)) # 随机生成用户历史行为数据
user_history[user] = history # 将用户历史行为数据添加到字典中
return user_history
# 随机生成内容特征数据
def generate_item_features(num_items, num_features):
item_features = {} # 创建一个空字典,用于存储内容特征数据
for item in range(num_items):
features = [random.random() for _ in range(num_features)] # 随机生成内容特征值
item_features[item] = features # 将内容特征值添加到字典中
return item_features
# 随机生成用户特征数据
def generate_user_features(num_users, num_features):
user_features = {} # 创建一个空字典,用于存储用户特征数据
for user in range(num_users):
features = [random.random() for _ in range(num_features)] # 随机生成用户特征值
user_features[user] = features # 将用户特征值添加到字典中
return user_features
# 基于内容过滤的推荐算法
def content_based_recommendation(user_history, item_features, user_features):
recommended_items = {} # 创建一个空字典,用于存储推荐结果
for user, history_items in user_history.items():
recommended_items[user] = [] # 对于每个用户,创建一个空列表,用于存储推荐的内容
for item, features in item_features.items():
if item not in history_items: # 如果内容不在用户的历史行为中
score = sum([user_feature * item_feature for user_feature, item_feature in zip(user_features[user], features)]) # 计算推荐内容的评分
recommended_items[user].append((item, score)) # 将推荐内容及其评分添加到列表中
recommended_items[user].sort(key=lambda x: x[1], reverse=True) # 根据评分对推荐内容进行排序,降序排列
return recommended_items
# 生成随机数据
num_users = 10 # 用户数量
num_items = 20 # 内容数量
num_features = 5 # 特征数量
user_history = generate_user_history(num_users, num_items) # 生成用户历史行为数据
item_features = generate_item_features(num_items, num_features) # 生成内容特征数据
user_features = generate_user_features(num_users, num_features) # 生成用户特征数据
# 进行推荐
recommended_items = content_based_recommendation(user_history, item_features, user_features) # 基于内容过滤的推荐算法
# 创建表格
table = PrettyTable() # 创建一个表格对象
table.field_names = ["内容"] + [f"用户 {i}" for i in range(num_users)] # 设置表格的列名
# 获取每个用户的推荐结果
user_recommendations = [[] for _ in range(num_users)] # 创建一个二维列表,用于存储每个用户的推荐结果
for i, user in enumerate(recommended_items):
for item, score in recommended_items[user]:
user_recommendations[i].append((item, round(score, 4))) # 保留四位小数,将推荐结果添加到列表中
# 添加推荐结果到表格
for item in range(num_items):
row = [f"内容 {item}"] # 创建一行数据,起始为内容信息
for user in range(num_users):
score = next((score for (i, score) in user_recommendations[user] if i == item), 0) # 获取用户对该内容的评分
row.append(score) # 将评分添加到行中
table.add_row(row) # 将行添加到表格中
# 打印表格
print(table)
# 打印用户和内容的信息
print("\n用户特征:")
for user, features in user_features.items():
print(f"用户 {user}: {features}")
print("\n内容特征:")
for item, features in item_features.items():
print(f"内容 {item}: {features}")
用户特征:
内容特征:
运行结果: