吴恩达强化学习复盘(7)基于内容的推荐算法思路
基于内容的过滤算法(Content-Based Filtering Algorithm)是推荐系统中的一种常见方法,它主要是根据用户和物品的特征来进行推荐。
·
基于内容的过滤算法
基于内容的过滤算法(Content-Based Filtering Algorithm)是推荐系统中的一种常见方法,它主要是根据用户和物品的特征来进行推荐。
基本原理
基于内容的过滤算法的核心思想是根据用户的历史行为(如购买、评分、浏览等)所体现出的偏好,以及物品本身的特征信息,来计算用户与物品之间的相似度,进而为用户推荐与他们过去喜欢的物品特征相似的其他物品。
例如,在电影推荐场景中,会考虑电影的类型(如动作、喜剧、爱情等)、导演、演员、上映年份等特征,同时分析用户以往对不同电影的评分,计算出用户对各种电影特征的偏好程度。然后,根据这些偏好,为用户推荐具有相似特征的电影。
简要步骤
- 特征提取:
- 用户特征:收集和整理用户的各种信息,如年龄、性别、兴趣爱好、历史行为数据(如购买记录、评分记录)等,并将其转化为特征向量。例如,将用户对不同类型电影的平均评分作为特征。
- 物品特征:提取物品的相关属性,如电影的类型、主演、导演等,也表示为特征向量。
- 相似度计算:使用合适的相似度度量方法(如余弦相似度、欧几里得距离等),计算用户与每个物品之间的相似度得分。
- 推荐生成:根据相似度得分,对物品进行排序,选择相似度较高的物品推荐给用户。
步骤详解
- 基于内容的过滤算法基础:
- 在基于内容的过滤算法中,仍然使用
表示用户 j 是否对项目 i 进行了评级,使用
表示用户 j 对项目 i 的评级(如果已定义)。
- 其关键在于能够充分利用用户和项目的特征,以找到比单纯的协同过滤方法更好的匹配。
- 在基于内容的过滤算法中,仍然使用
- 用户特征构建示例:
- 以电影推荐为例,用户的特征可以包括多种信息。比如用户的年龄、性别(性别可以用独热编码的方式表示,即根据用户自我认同的性别是男性、女性或未知,形成具有相应取值的特征)、国家(若世界上约有 200 个国家,可构建一个有大约 200 种可能取值的独热特征来表示用户所在国家)。
- 还可以依据用户的行为构建特征向量,例如查看目录中排名前一千的电影,构建一千个特征来表示用户看过这一千部最受欢迎电影中的哪些。
- 此外,根据用户对不同类型电影的评分也能构建新特征,如计算用户对每种电影类型(如爱情片、动作片等)给出的平均评分,这些平均评分可以作为描述用户的有效特征。虽然这些特征依赖于用户的评分,但这是构建用户特征向量的合理方式。最终,可以得到一个表示用户 j 的特征向量
。
- 电影特征构建示例:
- 对于每部电影或每个项目,同样可以构建一组特征。例如电影的年份、类型(若已知),如果存在对电影的批评评论,可构建一个或多个特征来体现评论家对电影的评价。
- 也可以利用用户对电影的评分来构造特征,如电影的平均评分,或者根据特定用户群体(如某个国家或特定用户群体)的平均评级来构建特征。由此可以为每部电影 i 构造特征向量
。
- 基于内容的过滤算法任务:
- 给定用户和电影的这些特征,任务是判断给定的电影 i 是否与用户 j 匹配良好。需要注意的是,用户特征和电影特征的维度可能差异很大,例如用户特征可能包含 1500 个数字,而电影特征可能只有 50 个数字,但这在基于内容的过滤算法中是允许的,后续会开发算法来学习如何匹配用户和电影。
- 预测评分方式的变化:
- 之前在协同过滤中,预测用户 j 对电影 i 的评分公式为
(
与
的点积加上
)。在开发基于内容的过滤算法时,去掉了
,实践表明这不会损害基于内容的过滤的性能。
- 用
代替
(V 表示为用户 j 计算的数字列表,即向量),用
代替
(为电影 i 计算的单独向量)。如果能合理选择
和
这两个向量,那么它们的点积有望很好地预测用户 j 对电影 i 的评分。
- 例如,学习算法得到的用户向量
可能包含反映用户对不同电影类型偏好的数字(如第一个数字表示喜欢爱情电影的程度,第二个数字表示喜欢动作电影的程度等),电影向量
也包含体现电影与不同类型相关程度的数字(如表示该电影是爱情电影或动作电影的程度)。通过计算这两个向量的点积(将对应元素相乘后求和),可以估计用户对该电影的喜好程度。
- 之前在协同过滤中,预测用户 j 对电影 i 的评分公式为
- 当前面临的挑战:
- 目前面临的挑战是,给定用户的特征
,如何计算能简洁表示用户偏好的向量 \
;以及给定电影的特征,如何计算
。并且
和
的维度必须相同,以便进行点积运算,例如它们都可能是由 32 个数组成的向量。
- 总结来说,协同过滤是基于用户对物品的评分来推荐,而基于内容的过滤是依据用户和项目的特征来寻找匹配。具体做法是计算用户和项目的向量
和
,并通过点积来找到良好匹配。关于如何计算
和
,将在下一个视频中继续探讨。
- 目前面临的挑战是,给定用户的特征
算法与深度学习的结合
- 解决这个挑战一种有效方法是运用深度学习,当前许多重要的商业基于内容的过滤系统都采用了这种方式。
- 在该算法中,需要根据用户的特征(如年龄、性别、国家等)计算向量
,以及根据电影的特征(如年份、发行、电影明星等)计算向量
。
用户网络和电影网络的构建
- 用户网络:为计算
,使用一个被称为用户网络的神经网络。该网络以用户的特征列表(年龄、性别、国家等)作为输入,通过一些层(如密集的神经网络层)进行处理,最终输出描述用户的向量
。这里的输出层有 32 个单元,所以
是一个包含 32 个数字的列表,这与之前多数输出层只有一个单元的神经网络不同。
- 电影网络:类似地,为计算电影的
,构建一个电影网络。该网络输入电影的特征,经过神经网络的几层处理后输出向量
,用于描述电影。最终通过
和
的点积来预测用户对电影的评级。用户网络和电影网络在隐层数量和每个隐层的单元数量上可以不同,但输出层的大小需保持一致。
算法的预测与修改
- 目前的描述中,若预测的是 1 到 5 星或 0.5 星的电影评级,可直接使用
和
的点积;若涉及用户对物品的收藏等二元标签情况,则可对
和
的点积应用 sigmoid 函数,以此预测概率。同时,可添加 i 和 j 上标来强调这是用户 j 对电影 i 的预测。
神经网络的整合与图示
- 虽然用户网络和电影网络可看作两个独立的神经网络,但实际上可以将它们绘制在一个图中,仿佛是一个单一的神经网络。在图的上半部分是用户网络,输入用户特征
并计算
;下半部分是电影网络,输入电影特征
并计算
,然后将这两个向量进行点积运算,得到预测结果。
模型的训练与代价函数
- 该模型包含很多参数,每个神经网络层都有一组常规参数。为训练用户网络和电影网络的所有参数,构造一个与协同过滤中类似的代价函数 J。假设已有一些用户对电影评分的数据,代价函数 J 是对所有有标签的用户 - 电影对(i 和 j),计算预测值
和
的点积)与实际评分
差值的平方和。
- 训练模型的方式是调整神经网络的参数,使得预测值与实际评分之间的平方误差尽可能小。这里没有用户网络和电影网络的单独训练程序,而是使用这个代价函数来训练所有参数,并根据
和
对
的预测程度来评估这两个网络。
- 为优化模型,可使用梯度下降或其他优化算法来调整神经网络的参数,使代价函数 J 最小。若要对模型进行正则化,还可添加常见的神经网络正则化项,促使网络保持参数值较小。
算法的其他用途与优势
- 训练好模型后,可利用它来寻找类似的物品。例如,对于描述用户 j 的特征为
的向量
和描述电影 i 的向量
,若想找到与电影 i 类似的其他电影,可寻找那些电影向量
与
之间平方距离较小的电影 k,这与协同过滤中寻找特征相似的电影类似。
- 此方法的一个优点是可以提前计算。例如,可在夜间运行计算机服务器,遍历所有电影列表,为每部电影找到相似的电影。这样,当用户次日访问网站浏览特定电影时,就能直接展示预先计算好的 10 到 20 部类似电影,这对于将该方法扩展到大型电影目录非常重要。
- 深度学习的优势在于更容易将多个神经网络组合在一起协同工作,构建更大的系统。这里将用户网络和电影网络组合,通过输出的内积操作,形成了更复杂且强大的架构。
示例代码
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# 模拟电影数据
movies = pd.DataFrame({
'title': ['电影1', '电影2', '电影3', '电影4', '电影5'],
'genre': ['动作, 冒险', '喜剧, 爱情', '动作, 科幻', '爱情, 剧情', '喜剧, 剧情']
})
# 特征提取:使用TF-IDF将电影类型文本转化为特征向量
vectorizer = TfidfVectorizer()
genre_matrix = vectorizer.fit_transform(movies['genre'])
# 计算电影之间的余弦相似度
similarity_matrix = cosine_similarity(genre_matrix)
# 定义一个函数,根据电影名称获取推荐电影
def get_recommendations(title, top_n=5):
idx = movies[movies['title'] == title].index[0]
sim_scores = list(enumerate(similarity_matrix[idx]))
sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
sim_scores = sim_scores[1:top_n+1] # 排除自身
movie_indices = [i[0] for i in sim_scores]
return movies['title'].iloc[movie_indices]
# 示例:获取电影1的推荐电影
print(get_recommendations('电影1'))
笔者注
在实际应用中,开发人员通常会花费大量时间精心设计输入到基于内容的过滤算法中的特征,因为合适的特征对于构建商业系统至关重要,说白了是磨细节。该算法的一个局限性是计算成本较高,尤其是当存在大量不同电影的大型目录且需要进行推荐时,读者可以自行深入研究。
更多推荐
所有评论(0)