数据挖掘指南之推荐系统读书笔记
文章目录
推荐系统
通过协同过滤的方式推荐相关内容.
协同过滤
通过查找一个与你相似的用户, 然后将ta喜欢的内容推荐给你.
怎么查找相似用户呢? 使用距离算法或者相关系数.
距离算法
通过将用户习惯或动作量化, 转换为可以计算的向量, 通过距离算法可以计算两个向量之间的距离, 通过相关系数计算公式可以计算相似程度. 而距离相近的用户,我们也认为两者相似.
距离算法: 曼哈顿距离、欧几里得距离、闵科夫斯基距离.
假设两个向量分别是(x1,x2), (y1,y2)
曼哈顿距离
\mid{x_1 - y_1}\mid + \mid{x_2 - y_2}\mid
欧几里得距离
\sqrt{(x_1 - y_1)^2 + (x_2 - y_2)^2}
闵可夫斯基距离
d(x,y) = (\sum_{k=1}^n{\mid{x_k - y_k}\mid^r})^{1/r}
相关系数: 皮尔森相关系数、余弦相似度.
皮尔森相关系数
r = \frac{\sum_{i=1}^{n}{x_iy_i} - \frac{\sum_{i=1}^{n}{x_i}\sum_{i=1}^{n}{y_i}}{n}}{\sqrt{\sum_{i=1}^{n}{x_i}^2 - {(\sum_{i=1}^{n}{x_i})^2 \over {n}}}\sqrt{\sum_{i=1}^{n}{x_i}^2 - {(\sum_{i=1}^{n}{x_i})^2 \over {n}}}}
皮尔森相关系数可使用np.corrcoef计算
np.corrcoef(x, y)
output
[[correlation(x, x), correlation(x, y)]
[correlation(y, x), correlation(y,y)]]
余弦相关系数
\cos{(x,y)} = \frac{x \cdot y}{{\mid\mid{x}\mid\mid}\times{\mid\mid{y}\mid\mid}}
\mid\mid{x}\mid\mid = \sqrt{\sum_{i=1}^{n}{x_i^2}}
其中范数可使用np.linalg.norm计算
点积可使用np.dot计算
相似度总结
如果数据存在“分数膨胀”问题,就使用皮尔逊相关系数。
如果数据比较“密集”,变量之间基本都存在公有值,且这些距离数据是非常重要的,那就使用欧几里得或曼哈顿距离。
如果数据是稀疏的,则使用余弦相似度。
K近邻算法
# 计算距离
def manhattan(user1, user2):
return np.sum(np.abs(df_user[user1] - df_user[user2]))
# 计算最近用户
def computeNeartNeighbor(username, users):
"""
计算与之相邻的距离
:params username: string
:params users: pd.DataFrame
"""
distance_lis = []
for user in users.columns:
if username != user:
distance = manhattan(username, user)
distance_lis.append((distance, user))
distance_lis.sort()
return distance_lis
# 推荐最近用户喜欢而被推荐用户没有评分的作品
def recommend(username, users):
"""
为username推荐
:params username: string
:params users: pd.DataFrame
"""
nearest = computeNeartNeighbor(username, users)[0][1]
recommandations = []
neighborRatings = users[nearest]
userRatings = users[username]
for index, value in enumerate(userRatings):
# 如果该用户没有评分但是最相关的用户有评分
if np.isnan(value) and not np.isnan(neighborRatings.iloc[index]):
recommandations.append((neighborRatings.index[index], neighborRatings.iloc[index]))
return sorted(recommandations, key=lambda artistTuple: artistTuple[1], reverse=True)
在实际使用过程中, k值一般不会为1,所以可以为每个用户的评分加权.
# 汇总K邻近用户的评分
for i in range(self.k):
# 计算饼图的每个分片
weight = nearest[i][1] / totalDistance
# 获取用户名称
name = nearest[i][0]
# 获取用户评分
neighborRatings = self.data[name]
# 获得没有评价过的商品
for artist in neighborRatings:
if not artist in userRatings:
if artist not in recommendations:
recommendations[artist] = (neighborRatings[artist]
* weight)
总结
选择合适的距离算法或者相似度算法找到相似的用户,然后将相似用户的喜好推荐给被推荐用户.