推荐系统:从基础到实践
1. 产品评分预测
在预测产品评分时,我们可以使用用户 - 用户协同过滤的方法。以用户 X、Y 和 Z 为例,假设我们要预测用户 X 对 Disposos’ Diapers 的评分,而用户 Y 和 Z 已经对该产品进行了评分。
首先,我们有如下的基础评分表:
| 顾客 | Snarky’s 薯片 | SoSo 润肤乳 | Duffly 啤酒 | BetterTap 水 | XXLargeLivin’ 足球衫 |
| ---- | ---- | ---- | ---- | ---- | ---- |
| X | 4 | 3 | | | |
| Y | 3.5 | 2.5 | | | |
| Z | 4 | 3.5 | | | |
接着,对评分进行中心化处理:
| 顾客 | Snarky’s 薯片 | SoSo 润肤乳 | Duffly 啤酒 | BetterTap 水 | XXLargeLivin’ 足球衫 |
| ---- | ---- | ---- | ---- | ---- | ---- |
| X | 0.33 | -0.66 | | | |
| Y | 0 | -1 | | | |
| Z | -0.125 | -0.625 | | | |
然后,计算用户 X 与用户 Y、Z 的中心化余弦相似度:
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
user_x = [0, 0.33, 0, -0.66, 0, 0.33, 0]
user_y = [0, 0, 0, -1, 0, 0.5, 0.5]
similarity_xy = cosine_similarity(np.array(user_x).reshape(1, -1), np.array(user_y).reshape(1, -1))
user_z = [0, -0.125, 0, -0.625, 0, 0.375, 0.375]
similarity_xz = cosine_similarity(np.array(user_x).reshape(1, -1), np.array(user_z).reshape(1, -1))
得到用户 X 与用户 Y 的相似度为 0.42447212,与用户 Z 的相似度为 0.46571861。
最后,根据相似度对用户 Y 和 Z 的评分进行加权平均,计算用户 X 对 Disposos’ Diapers 的预测评分:
rating_prediction = (0.42447212 * 4 + 0.46571861 * 4.5) / (0.42447212 + 0.46571861)
print(rating_prediction) # 输出 4.26
由此可知,用户 X 对 Disposos’ Diapers 的预期评分为 4.26。
2. 物品 - 物品协同过滤
除了用户 - 用户协同过滤,还有物品 - 物品协同过滤方法,该方法在实践中通常优于用户 - 用户过滤。以用户对歌曲的评分为例,有如下的效用矩阵:
| 实体 | U1 | U2 | U3 | U4 | U5 |
| ---- | ---- | ---- | ---- | ---- | ---- |
| S1 | 2 | 4 | 5 | | |
| S2 | 3 | 3 | | | |
| S3 | 1 | 5 | 4 | | |
| S4 | 4 | 4 | 4 | | |
| S5 | 3 | 5 | | | |
假设我们想知道用户 3 对歌曲 S5 的评分,我们将寻找与 S5 相似的歌曲。
首先,对每首歌曲的评分进行中心化处理,并计算与目标行 S5 的余弦相似度:
| 实体 | U1 | U2 | U3 | U4 | U5 | 中心化余弦相似度 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| S1 | -1.66 | 0.33 | 1.33 | | | 0.98 |
| S2 | 0 | 0 | 0 | | | 0 |
| S3 | -2.33 | 1.66 | 0.66 | | | 0.72 |
| S4 | 0 | 0 | 0 | | | 0 |
| S5 | -1 |? | 1 | | | 1 |
选择 k = 2 作为最近邻的数量,歌曲 S1 和 S3 与 S5 最相似,用户 3 对 S1 和 S3 的评分分别为 4 和 5。
计算用户 3 对歌曲 S5 的预测评分:
rating_s5 = (0.98 * 4 + 0.72 * 5) / (0.98 + 0.72)
print(rating_s5) # 输出 4.42
根据物品 - 物品协同过滤,用户 3 对歌曲 S5 的预测评分为 4.42。
3. 用户 - 用户与物品 - 物品协同过滤对比
用户 - 用户协同过滤存在一定的局限性。例如,你和朋友可能有一些共同的兴趣爱好,但也有各自独特的兴趣领域。在用户 - 用户推荐中,即使你们在很多方面相似,但由于某些独特兴趣的存在,你可能会收到一些不符合你兴趣的推荐。而物品 - 物品过滤则可以避免这种情况,为你提供更符合你兴趣的推荐。
4. 基于内容的过滤
基于内容的过滤以 Pandora 音乐为例。创始人 Tim Westergren 发现很多优秀的音乐作品没有得到足够的关注,他认为这是因为音乐没有被推送给足够多的合适人群。于是,他开始思考将每首音乐分解成不同的特征,构建音乐基因组。
他们雇佣了一批音乐家,对超过一百万首音乐的近 400 个不同音乐特征进行了细致编码,每个特征在 0 到 5 分的范围内进行评分。每首三到四分钟的歌曲分类大约需要半小时。这些特征包括主唱声音的沙哑程度、每分钟的节拍数等。
经过近一年的时间,他们的第一个原型完成,完全在 Excel 中使用 VBA 宏构建,返回一个推荐大约需要四分钟。最终,这个系统取得了成功,现在的 Pandora 音乐已经拥有数百万的日活跃用户。
在基于内容的过滤中,歌曲不再被视为一个不可分割的整体,而是成为可以使用余弦相似度进行比较的特征向量。同时,听众的口味也可以表示为向量,以便与歌曲进行比较。
5. 混合系统
在大规模生产环境中,通常会使用混合系统,结合协同过滤和基于内容的过滤。下面是两种过滤方法的优缺点对比:
| 过滤方法 | 优点 | 缺点 |
| ---- | ---- | ---- |
| 协同过滤 | 无需手动创建特征 | 没有大量的物品和用户时效果不佳;物品数量远超过可购买数量时会出现稀疏性问题 |
| 基于内容的过滤 | 不需要大量用户 | 定义合适的特征具有挑战性;缺乏意外发现的惊喜 |
基于内容的过滤在用户基数较小时是更好的选择,随着用户数量的增长,添加协同过滤可以为推荐增加更多的意外惊喜。
6. 构建推荐引擎
我们将使用 GitHub API 创建一个基于协同过滤的推荐引擎,具体步骤如下:
1. 导入所需的库:
import pandas as pd
import numpy as np
import requests
import json
- 在 GitHub 上创建账户并为一些仓库加星标,无需注册开发者计划,从个人资料中获取授权令牌。
- 生成 API 使用的令牌:访问 https://github.com/settings/tokens,点击“Generate new token”按钮,选择权限(如 public_repo),复制生成的令牌。
myun = "YOUR_GITHUB_HANDLE"
mypw = "YOUR_PERSONAL_TOKEN"
- 创建函数获取自己加星标的仓库:
my_starred_repos = []
def get_starred_by_me():
resp_list = []
last_resp = ''
first_url_to_get = 'https://api.github.com/user/starred'
first_url_resp = requests.get(first_url_to_get, auth=(myun, mypw))
last_resp = first_url_resp
resp_list.append(json.loads(first_url_resp.text))
while last_resp.links.get('next'):
next_url_to_get = last_resp.links['next']['url']
next_url_resp = requests.get(next_url_to_get, auth=(myun, mypw))
last_resp = next_url_resp
resp_list.append(json.loads(next_url_resp.text))
for i in resp_list:
for j in i:
msr = j['html_url']
my_starred_repos.append(msr)
get_starred_by_me()
- 解析出加星标仓库的用户名称:
my_starred_users = []
for ln in my_starred_repos:
right_split = ln.split('.com/')[1]
starred_usr = right_split.split('/')[0]
my_starred_users.append(starred_usr)
- 创建函数获取这些用户加星标的仓库:
starred_repos = {k: [] for k in set(my_starred_users)}
def get_starred_by_user(user_name):
starred_resp_list = []
last_resp = ''
first_url_to_get = 'https://api.github.com/users/' + user_name + '/starred'
first_url_resp = requests.get(first_url_to_get, auth=(myun, mypw))
last_resp = first_url_resp
starred_resp_list.append(json.loads(first_url_resp.text))
while last_resp.links.get('next'):
next_url_to_get = last_resp.links['next']['url']
next_url_resp = requests.get(next_url_to_get, auth=(myun, mypw))
last_resp = next_url_resp
starred_resp_list.append(json.loads(next_url_resp.text))
for i in starred_resp_list:
for j in i:
sr = j['html_url']
starred_repos.get(user_name).append(sr)
for usr in list(set(my_starred_users)):
try:
get_starred_by_user(usr)
except:
print('failed for user', usr)
- 构建特征集:
repo_vocab = [item for sl in list(starred_repos.values()) for item in sl]
repo_set = list(set(repo_vocab))
- 为每个用户创建二进制向量:
all_usr_vector = []
for k, v in starred_repos.items():
usr_vector = []
for url in repo_set:
if url in v:
usr_vector.extend([1])
else:
usr_vector.extend([0])
all_usr_vector.append(usr_vector)
df = pd.DataFrame(all_usr_vector, columns=repo_set, index=starred_repos.keys())
- 添加自己的行到数据框:
my_repo_comp = []
for i in df.columns:
if i in my_starred_repos:
my_repo_comp.append(1)
else:
my_repo_comp.append(0)
mrc = pd.Series(my_repo_comp).to_frame('acombs').T
mrc.columns = df.columns
fdf = pd.concat([df, mrc])
- 计算相似度:
from scipy.stats import pearsonr
sim_score = {}
for i in range(len(fdf)):
ss = pearsonr(fdf.iloc[-1, :], fdf.iloc[i, :])
sim_score.update({i: ss[0]})
sf = pd.Series(sim_score).to_frame('similarity')
- 排序并找到最相似的用户:
sf_sorted = sf.sort_values('similarity', ascending=False)
通过以上步骤,我们可以找到与自己最相似的用户,并根据他们加星标的仓库生成推荐。
下面是构建推荐引擎的流程图:
graph TD;
A[导入库] --> B[获取授权令牌];
B --> C[获取自己加星标的仓库];
C --> D[解析用户名称];
D --> E[获取用户加星标的仓库];
E --> F[构建特征集];
F --> G[创建二进制向量];
G --> H[添加自己的行到数据框];
H --> I[计算相似度];
I --> J[排序找到最相似的用户];
综上所述,我们介绍了产品评分预测的方法,包括用户 - 用户协同过滤和物品 - 物品协同过滤,以及基于内容的过滤和混合系统。最后,详细阐述了如何使用 GitHub API 构建一个基于协同过滤的推荐引擎。这些方法和技术可以帮助我们更好地理解和实现推荐系统。
推荐系统:从基础到实践
7. 推荐生成与分析
在找到最相似的用户后,我们可以利用他们加星标的仓库来生成推荐。我们选取三个最相似的用户(排除自己),分别是用户 6、用户 42 和用户 116。
首先,创建一个包含自己和这三个最相似用户加星标仓库的 DataFrame:
all_recs = fdf.iloc[[6, 42, 116, fdf.index.get_loc(myun)], :]
然后,查看是否有我们都加星标的仓库:
common_starred = all_recs[(all_recs == 1).all(axis = 1)]
print(common_starred)
结果显示,大家似乎都喜欢 scikit - learn 和机器学习相关的仓库。接着,我们找出自己未加星标但这三个用户都加星标的仓库:
str_recs_tmp = all_recs[all_recs[myun] == 0].copy()
str_recs = str_recs_tmp.iloc[:, :-1].copy()
commonly_starred_not_mine = str_recs[(str_recs == 1).all(axis = 1)]
print(commonly_starred_not_mine)
发现没有特别明显被遗漏的仓库。再看看至少有两个用户加星标的仓库,通过对行求和来筛选:
summed_recs = str_recs.sum(axis = 1).to_frame('total').sort_values(by = 'total', ascending = False)
print(summed_recs)
这里出现了很多优秀的机器学习和人工智能仓库,例如 fuzzywuzzy,这是一个很实用但自己之前未加星标的仓库。
8. 推荐系统的优化方向
为了进一步优化推荐结果,我们可以采取以下两种方法:
-
基于星标数量排序
:可以通过再次调用 GitHub API,利用提供星标数量信息的端点,根据仓库获得的总星标数对推荐进行排序。
-
添加内容过滤层
:这就是前面提到的混合系统中的内容过滤部分。我们需要从自己的仓库中创建一组特征,以反映自己感兴趣的类型。一种方法是对加星标仓库的名称和描述进行分词,生成一组单词特征。例如,会包含 Python、Machine Learning、Data Science 等单词。
以下是一个简单的示例,展示如何创建特征集:
import nltk
from nltk.tokenize import word_tokenize
nltk.download('punkt')
feature_set = []
for repo in my_starred_repos:
# 假设可以通过 API 获取仓库描述
description = get_repo_description(repo)
tokens = word_tokenize(repo + ' ' + description)
feature_set.extend(tokens)
feature_set = list(set(feature_set))
在 DataFrame 中,列将是单词特征(n - 元组),行将是通过协同过滤步骤生成的仓库。我们可以再次使用自己的仓库进行比较,运行相似度计算过程。
9. 总结与展望
推荐系统在当今的信息时代中扮演着至关重要的角色,它能够帮助用户从海量的信息中快速找到自己感兴趣的内容。本文介绍了多种推荐系统的方法,包括用户 - 用户协同过滤、物品 - 物品协同过滤、基于内容的过滤以及混合系统,并详细阐述了如何使用 GitHub API 构建一个基于协同过滤的推荐引擎。
不同的推荐方法各有优缺点,用户 - 用户协同过滤简单直接,但在数据稀疏时效果不佳;物品 - 物品协同过滤在实践中表现更好,能减少不相关推荐;基于内容的过滤可以深入挖掘用户的兴趣特征,但特征定义具有挑战性。混合系统结合了协同过滤和基于内容的过滤,能够取长补短,提供更优质的推荐。
在实际应用中,我们可以根据具体的场景和数据特点选择合适的推荐方法,并通过不断优化和改进,提高推荐系统的性能和效果。例如,在构建推荐引擎时,我们可以进一步优化特征提取方法、调整相似度计算方式,或者引入更多的数据来源和特征信息。同时,我们也可以考虑用户的实时反馈,动态调整推荐策略,以提供更加个性化和精准的推荐服务。
以下是推荐系统优化步骤的流程图:
graph TD;
A[生成初始推荐] --> B[基于星标数量排序];
A --> C[添加内容过滤层];
B --> D[优化推荐结果];
C --> D;
D --> E[考虑用户反馈];
E --> F[动态调整推荐策略];
总之,推荐系统的发展前景广阔,随着技术的不断进步和数据的不断丰富,我们有理由相信,未来的推荐系统将能够为用户提供更加智能、高效、个性化的推荐服务。
| 优化方法 | 操作步骤 |
|---|---|
| 基于星标数量排序 | 1. 调用 GitHub API 中提供星标数量信息的端点;2. 根据星标数量对推荐仓库进行排序 |
| 添加内容过滤层 | 1. 对自己加星标仓库的名称和描述进行分词;2. 生成单词特征集;3. 在新的 DataFrame 中使用特征集和协同过滤生成的仓库进行相似度计算 |
超级会员免费看

被折叠的 条评论
为什么被折叠?



