目录
一、推荐系统
1、提出建议
2、制定代价函数
二、协同过滤算法(Collaborative Filtering Algorithm)
1、定义
2、举例说明
3、冷启动问题
三、二进制标签
1、定义
2、举例说明
四、均值归一化
1、定义
2、举例说明
五、协同过滤算法的代码实现
六、寻找相关特征
1、常见方法
2、举例说明
在典型的推荐系统中,有一定数量的用户和一定数量的项目。在这种情况下,目的是给用户推荐可能感兴趣的项目。
假设有一家大型电影流媒体网站,用户可以对电影进行评级。用来表示用户数量,这里
,
表示为项目数,在例子中电影有5部所以
。如果用户
对电影
进行了评分,得到
的值为1,没有进行评分则值为0。如用户Alice对电影1进行了评分,
,但是对电影3没有进行评分,则
,即为是否评分的标签。
则为用户
给电影
的评分,
即为2号用户Bob给3号电影的评分为4分。
添加两个关于电影的特征x1和x2,引入作为表示特征数量的值,
为第i个电影的特征向量。
则预测用户对电影
的评分可以通过以下公式,
这里的参数和
是用来预测用户 j 对电影 i 的评分的参数,
是电影 i 的特征。
用来表示用户 j 评价的电影数量。
在给定的数据情况下学习参数 和
,制定相关的代价函数。
在只关注用户j的情况下,使用均方误差,即预测值减去真实值,然后平方。选择参数w和b来最小化预测值与实际值之间的平方误差,求平方误差和时,仅对用户实际评分过的项目做求和计算, 最后可以对平方误差和除以
进行归一化计算,末尾加上防止过拟合的正则化项,正则化项中的k=n中n是指电影的特征数量n。事实证明,对于推荐系统,实际消除
会方便,
只是该表达式中的一个常数,最终得到的值不会有影响。最小化这个代价函数会获得一组参数来预测用户 j 对其他电影的评分。
对于所有用户学习参数时,将求出从到
的所有用户的代价函数总和,这成为所有用户学习的所有参数的代价函数。如果使用梯度下降或任何其他优化算法来最小化总的代价函数,就会得到一组参数来预测所有用户对电影的评价。
协同过滤算法是一种推荐算法,其目的是为用户推荐他们可能感兴趣的物品。该算法使用用户的历史行为和偏好来预测他们对尚未查看或评分的物品的偏好。
协同过滤算法有两种类型:基于用户和基于物品。基于用户的协同过滤算法根据用户之间的相似度来推荐物品。它首先计算用户之间的相似度,并根据这些相似度为每个用户推荐适合他们的物品。基于物品的协同过滤算法是相反的,它根据物品之间的相似度来推荐物品。
协同过滤算法分为两种主要类型:基于用户的协同过滤和基于物品的协同过滤。
1. 基于用户的协同过滤(User-based Collaborative Filtering):
基于用户的协同过滤通过分析用户之间的相似性来进行推荐。算法的核心思想是如果两个用户在过去的行为上有相似之处,那么它们在未来行为上也可能有相似之处。具体步骤如下:
2. 基于物品的协同过滤(Item-based Collaborative Filtering):
基于物品的协同过滤通过分析物品之间的相似性来进行推荐。算法的核心思想是如果两个物品在被用户同时喜欢的频率较高,那么这两个物品具有较高的相似度。具体步骤如下:
协同过滤算法的优点是可以提供个性化的推荐结果,适用于面对大规模数据的推荐任务。然而,该算法也存在一些问题,如冷启动问题(对新用户或新物品难以给出准确推荐)和数据稀疏性问题(数据集中存在大量缺失数据)。因此,协同过滤算法通常需要与其他推荐算法结合使用,以提高推荐的准确性和覆盖率。
协同过滤算法的原理是将用户或物品表示为向量,并使用这些向量来预测评分或推荐物品。为此,算法使用矩阵分解技术,例如奇异值分解(SVD)或潜在因子模型(LFM),将用户和物品映射到低维嵌入空间中的向量。
协同过滤算法有几个优点。首先,它可以根据用户的历史行为和偏好进行个性化推荐。其次,它是一种简单且易于实现的算法。然而,它也存在一些局限性。例如,它可能会出现冷启动问题,在新用户或新物品的情况下,很难生成准确的推荐。此外,它可能会出现数据稀疏性的问题,在这种情况下,算法可能无法识别用户或物品之间的相似性。
总的来说,协同过滤算法是一种有用的推荐算法,可以在电子商务、社交媒体和在线广告等应用程序中使用。
如果每部电影都有特征,根据特征可以使用基本的线性回归来学习预测电影的评级,但是如果没有特征该如何去获取。
假设已经获得了四位用户的参数和
,预测用户j对电影i的评分需要使用公式
,为了简化这个例子,将所有的
的值都设为0。在此示例中有用户已经评价的电影评级,可以借助参数来合理预测电影的特征。
notes:
在我们得知每一个用户的参数w,b之后,可以根据这个用户已知的读电影的评分去倒推特征向量x的值。
向量了可以理解为用户 j 对特征x1、x2等特征的对应数值,w向量是配合x特征值的,即用户 j 对特征x1爱情片的喜爱程度和对特征x2动作片的喜爱程度。
构造相关的代价函数来实际学习特征值x1和x2。在一个典型的线性回归应用程序中,如果只有一个用户,也就是只有一组参数,实际上没有足够的信息来确定特征x1和x2,这就是为什么在线性回归上不可能反推出特征x1和x2。但是在协同过滤算法中,因为有多个用户对同一电影的评分,有多组参数,可以去猜测这些特征的可能值。
对于个用户给定对应的参数
和
,学习电影i的特征向量,可以得到代价函数
,对其进行最小化平方误差。然后要学习所有特征
,可以将代价函数
求和。使用梯度下降算法或者其他优化算法来最小化这个代价函数
可以得到电影的所有特征
。
将学习参数和
的代价函数和学习特征
的代价函数放在一起,在其中明确对所有的i和j求和,然后将两者的正则化项添加进来。
使用梯度下降算法来最小化代价函数,代价函数是w,b,x的函数,梯度下降更新参数中的每一个,可以得到使代价函数最小化的参数w,b,x。
得出的平均值称之为协同过滤,协同过滤这个名称是因为多个用户协同评价同一部电影,让你了解这部电影可能是什么样子,就可以猜测合适的特征是什么,反过来又允许预测尚未评价同一部电影的其他用户会如何评价。这种协同过滤是从多个用户收集数据,用户之间的协作可以帮助预测未来其他用户的评价。
协同过滤算法的冷启动问题指的是当系统中没有足够的用户行为数据时,很难推荐新的物品给用户。这种情况下,协同过滤算法无法使用已有的用户历史行为数据来分析用户的兴趣和偏好,从而无法进行推荐。冷启动问题主要有以下几种情况:
新用户冷启动问题:当一个新用户加入系统时,由于缺乏其历史行为数据,协同过滤算法无法准确分析其兴趣和偏好,从而无法进行精准推荐。
新物品冷启动问题:当一个新物品加入到系统中时,协同过滤算法也无法准确地分析其特征和属性,从而无法与历史数据进行匹配,使得该物品很难被推荐给用户。
稀疏矩阵问题:即使系统中已有一定数量的用户历史行为数据和物品属性信息,由于用户-物品矩阵过于稀疏,也会导致协同过滤算法推荐效果不佳。
针对这些冷启动问题,可以采用以下解决方法:为新用户提供个性化的推荐问卷,收集用户的兴趣和偏好信息;采用基于内容的推荐算法为新物品打标签,建立物品特征库;采用混合推荐算法,并将内容信息和用户行为数据结合起来进行推荐,提高推荐准确度。
在协同过滤算法中,二进制标签通常用来表示用户对特定物品的行为,如是否对某件商品进行了购买或评分等。
在基于用户的协同过滤算法中,我们需要将每个用户的对物品的行为用二进制标签进行编码。例如,对于一个电商平台,我们可以将用户对某种商品的购买行为编码为1,未购买的行为编码为0。然后,我们可以使用这些二进制标签来计算用户之间的相似度,并根据相似度来推荐物品。
类似地,在基于物品的协同过滤算法中,我们同样需要将每个物品的属性或特征用二进制标签进行编码。例如,对于一个电影推荐系统,我们可以将每个电影的种类、导演、演员等特征用二进制标签进行编码。然后,我们可以根据不同用户对这些二进制标签的偏好程度来计算物品之间的相似度,从而推荐相应的电影。
总之,协同过滤算法中的二进制标签可以帮助我们理解用户对物品的行为和偏好,并推荐相应的物品,提高系统的个性化推荐效果。
推荐系统或者协同过滤算法都涉及到二进制标签,只是以某种方式表述是或不是的问题。将算法泛化到二进制,概括算法的过程如同线性回归到逻辑回归,从预测数字到二进制标签。
对于二进制标签,预测标签通过逻辑函数g来实现。将很像线性回归的模型转变成逻辑回归的模型。构建此算法,需要将代价函数从平方误差代价函数改为更适合逻辑回归的二元标签代价函数。
当使用二进制标签时, 为0或1时,则预测函数
变为逻辑函数。与推导逻辑回归时类似,为单个示例制定了损失函数L,有时称为二元交叉熵代价函数。为了使其适应协同过滤算法,代价函数
是所有参数w,b以及每个项目的特征x的函数。
均值归一化也叫标准化,是一种常见的数据预处理方法,主要是为了消除不同数据之间的尺度差异带来的影响,使得不同的特征具有相同的重要性,从而提高模型的精确度和稳定性。
其方法主要是对每个特征列进行均值和方差的计算,然后用每个值减去均值,再除以方差,这样原始数据就被映射到了以均值为中心,方差为单位的空间中。此方式的计算公式如下:
其中,X表示原始数据,代表该特征列的均值,
代表该特征列的标准差。
这种预处理方法的好处是可以避免因为不同特征之间的尺度差异造成的预测不准问题,同时减少梯度下降的训练时间。不过这种方式的缺点是在处理较大的数据集时,计算均值和方差会耗费较多时间,因此需要进行性能优化。
如果通过将电影评级标准化为具有一致的平均值,即执行均值归一化,也许会表现得更好。
添加一个尚未对任何电影进行评级的第五个用户Eve,添加均值归一化有助于算法对用户Eve做出更好的预测。
事实上,如果要在这个数据上训练一个协同过滤算法,那么通过最小化代价函数得到参数的值,实际上会得到第五个用户Eve的参数,
。因为Eve还未对任何电影进行评级,所以参数w和b不会影响代价函数中的第一项,因为Eve的电影评级都不会在这个平方误差代价函数中起作用(因为第一项中求和公式的条件是有评价之后,即
才会进行求和计算,而Eve并内有对任何电影进行评级,所以当
和
时,代价函数中第一项都是0,只有第二和第三项正则化项,因此当
和
时,最小化代价函数也就是最小化参数
)。因此,最小化代价函数意味着使参数w尽可能地小,最后参数
,
。但是如果这是Eve的参数,那么平均值最终会预测Eve的所有电影评级
为0。因此,该算法将预测一个尚未对所有内容进行评分的新用户,会对所有电影都评0分。
将数据写成矩阵格式,矩阵第i行表示第i部电影五个人的评分,矩阵第j列表示第j个用户对五部电影的评分。
进行均值归一化之前,计算出每部电影的平均评分,即矩阵每行的均值(不将未评价的“?”数据计算在内)。 将这些均值列到一个向量中,称之为向量,指代每部电影的平均评分向量。
通过将原始数据矩阵从每个评级中减去平均评级,得到一个新的矩阵,(相当于每个点到中心的距离),也就是新的。使用新的
,为电影i上的用户j学习
、
和
。但是因为在均值归一化步骤中减去了电影i的
,为了避免不是负值的评级,则加回这个
,即公式变为
所以,按照这样处理之后,对于新用户Eve还未对任何电影评级,平均值可能会学习参数,
,通过公式
计算之后,得到预测的Eve可能会对电影i的评价为电影i的均值
,似乎较为合理,这个算法的效果导致新用户的初始猜测可能正好等于其他用户对这五部电影的评分的平均值。
notes:
在此示例中,所做的是将矩阵的行进行均值归一化,这在新用户尚未对很多电影进行评分时会有所帮助,还有一种替代方法,是将该矩阵的列进行均值归一化,也是一种可行的方法。
但是,在推荐系统的应用程序中,规范化行以便于给新用户提供似乎合理的评级,比规范化列更重要。如果规范化列的话,有一部完全没有人评价过的全新电影,可能不应该一开始就给大量用户推荐,因为对该全新电影的了解不多。
import numpy as np
from scipy.spatial.distance import pdist, squareform
from tabulate import tabulate
def calculate_similarity(ratings):
# 找出所有物品的列表
items = set()
for user_ratings in ratings.values():
items.update(user_ratings.keys())
# 创建用户索引和物品索引的映射
user_mapping = {i: user for i, user in enumerate(ratings.keys())}
item_mapping = {i: item for i, item in enumerate(items)}
# 将评分数据转换为矩阵形式,对缺失评分用 0 填充
num_users = len(ratings)
num_items = len(items)
ratings_matrix = np.zeros((num_users, num_items))
for i, (user, user_ratings) in enumerate(ratings.items()):
for j, item in enumerate(items):
if item in user_ratings:
ratings_matrix[i, j] = user_ratings[item]
# 计算用户之间的相似度
similarity = 1 - squareform(pdist(ratings_matrix, 'cosine'))
return similarity, user_mapping, item_mapping
# 测试数据
ratings = {
'User1': {'Item1': 4, 'Item2': 3, 'Item3': 5},
'User2': {'Item1': 2, 'Item4': 4},
'User3': {'Item2': 5, 'Item4': 3},
'User4': {'Item3': 2, 'Item5': 4},
'User5': {'Item1': 5, 'Item2': 4, 'Item3': 3, 'Item4': 2}
}
# 计算用户之间的相似度
similarity, user_mapping, item_mapping = calculate_similarity(ratings)
# 打印相似度矩阵
# user_mapping = {0: 'User1', 1: 'User2', 2: 'User3', 3: 'User4', 4: 'User5'}
# similarity = {
# (0, 0): 1.0,
# (0, 1): 0.50395263,
# (0, 2): 0.5592123,
# (0, 3): 0.33505811,
# (0, 4): 0.90913729,
# (1, 0): 0.50395263,
# (1, 1): 1.0,
# (1, 2): 0.97843195,
# (1, 3): 0.96362411,
# (1, 4): 0.82719057,
# (2, 0): 0.5592123,
# (2, 1): 0.97843195,
# (2, 2): 1.0,
# (2, 3): 0.80178373,
# (2, 4): 0.86562397,
# (3, 0): 0.33505811,
# (3, 1): 0.96362411,
# (3, 2): 0.80178373,
# (3, 3): 1.0,
# (3, 4): 0.45911973,
# (4, 0): 0.90913729,
# (4, 1): 0.82719057,
# (4, 2): 0.86562397,
# (4, 3): 0.45911973,
# (4, 4): 1.0,
# }
# 构建表格数据
table_data = []
for i, user1 in user_mapping.items():
row = [user1]
for j, user2 in user_mapping.items():
row.append(f"{similarity[(i, j)]:.2f}")
table_data.append(row)
# 打印表格
table_header = [""] + [user_mapping[j] for j in user_mapping]
table = tabulate(table_data, headers=table_header, tablefmt="pipe")
print(table)
这段代码实现了一个计算用户之间相似度的函数 `calculate_similarity`,并在测试数据上进行了演示。
1. `calculate_similarity(ratings)` 函数用于计算用户之间的相似度。它接受一个评分数据的字典作为输入。
2. 首先, 代码通过遍历评分数据,获取了所有物品的列表,并将其存储在集合 `items` 中。这一步是为了确保考虑到所有可能的物品。
3. 接下来,代码创建了两个字典:`user_mapping` 和 `item_mapping`。`user_mapping` 用于建立用户索引和用户名称之间的映射关系,`item_mapping` 用于建立物品索引和物品名称之间的映射关系。这两个字典是为了便于后续的矩阵操作和结果的可读性。
4. 然后,代码将评分数据转换成矩阵形式,并且对缺失的评分用0进行填充。这样,就得到了一个评分矩阵 `ratings_matrix`,其中每行代表一个用户,每列代表一个物品,矩阵中的元素是用户对物品的评分。
5. 使用 `pdist(ratings_matrix, 'cosine')` 函数计算了评分矩阵中用户之间的余弦相似度,并将结果存储在 `similarity` 变量中。余弦相似度可以用来度量用户评分之间的相似性,取值范围为 -1 到 1,值越接近1表示两个用户的评分越相似。
6. 最后,函数返回了相似度矩阵 `similarity`,以及用户索引和物品索引的映射字典 `user_mapping` 和 `item_mapping`。
7. 在测试数据的部分,给定了一个包含用户和物品评分的 `ratings` 字典。
8. 接下来,将调用 `calculate_similarity` 函数,传入测试数据,并将返回的相似度矩阵、用户索引和物品索引分别赋值给 `similarity`、`user_mapping` 和 `item_mapping` 变量。
9. 然后,使用 `tabulate` 函数将相似度矩阵转换为表格形式的字符串。该函数使用表头和表格数据作为输入,通过选择适当的表格格式进行转换。
10. 最后,通过调用 `print` 函数将表格打印出来。表格中的行表示用户,列表示用户之间的相似度。表格中的数值是相似度的值,保留两位小数。
最后,打印出用户之间的相似度。
运行结果:
在协同过滤算法中,寻找相关特征是非常重要的,因为它会直接影响到推荐准确度和用户体验。下面是一些常见的寻找相关特征的方法:
用户行为:用户在网站上的行为可以反映出其兴趣和偏好,比如点击、观看、收藏、评分等,可以通过对这些行为进行分析,找出用户对哪些物品感兴趣,并推荐相关物品。
用户属性:用户的属性信息也可以用来描述用户的兴趣,比如年龄、性别、职业等,不同属性的用户可能对不同类型的物品感兴趣,因此可以将用户属性作为相关特征,提高推荐准确度。
用户社交网络关系:用户之间的联系可以反映出他们之间的共同兴趣和价值观,比如朋友、关注、互动等,可以通过分析用户之间的社交网络关系,找出用户之间的相似性并推荐相关物品。
物品属性:物品的属性信息可以反映其特征和类型,比如电影的类型、歌曲的风格等,可以通过对这些属性进行分析,找出相似的物品并推荐。
物品标签:用户对物品进行标记的标签可以反映物品的特征和类型,比如电影的标签、歌曲的标签等,可以通过对这些标签进行分析,找出相似的物品并推荐。
物品关联关系:不同物品之间可能存在关联关系,比如同一系列的电影、同一专辑的歌曲等,可以通过分析这些关联关系,推荐相关的物品。
总的来说,寻找相关特征的方法比较多,需要根据实际情况选择合适的方法,并将这些特征结合在一起,来描述用户和物品之间的相似性,从而提高推荐准确度。
在学习到每个项目i的特征时,发现查看各个特征
,会发现很难解释特征的含义,但是尽管如此,学习到的特征确实传达了该项目的一些信息。事实证明,给定项目i的特征
,如果想找到其他项目在某些方面与之相似的,可以尝试找具有与
特征相似的
的项目k。特别的是,给定一个特征向量
,确定与特征向量
相似的方法如下:
计算出对应特征之间的平方距离,如果不仅找到特征之间距离最小的一个项目,而且找到了在设定阈值之内的,具有相似特征向量的几个项目,则都可以是相似项目。