# 《推荐系统实践》：如何利用用户标签数据?

## 实验设置

```def PrecisionRecall(test_data, recommendations, N):
hit = 0
n_recall = 0
n_precision = 0
for user,ru in recommendations.items():
tu = test_data[user]
for item in sorted(ru.items(), key=itemgetter(1), reverse=True)[0:N]:
if item in tu:
hit += 1
n_precision += 1
n_recall += len(tu)
recall = hit / (n_recall * 1.0)
precision = hit / (n_precision * 1.0)
return list(recall, precision)```

```def Coverage(train_data, test_data, recommendations, N):
total_items = set()
recommend_items = set()
for user, items in train_data.items():
for item in items:
for user, ru in recommendations.items():
for item, weight in sorted(ru.items(), key=itemgetter(1), reverse=True)[0:N]:
return (len(recommend_items) * 1.0) / (len(total_items) * 1.0);```

```def CosineSim(item_tags, i, j):
ret = 0
for b,wib in item_tags[i].items():
if b in item_tags[j]:
ret += wib * item_tags[j][b]
ni = 0
nj = 0
for b, w in item_tags[i].items():
ni += w * w   for b, w in item_tags[j].items():
nj += w * w   if ret == 0:
return 0
return ret / math.sqrt(ni * nj)```

```def Diversity(item_tags, recommend_items):
ret = 0
n = 0
for i in recommend_items.keys():
for j in recommend_items.keys():
if i == j:
continue
ret += CosineSim(item_tags, i, j)
n += 1
return ret / (n * 1.0)```

```def AveragePopularity(item_pop, recommend_results):
ret = 0
n = 0
for u, recommend_items in recommend_results.items():
for item in recommend_items.keys():
ret += math.log(1 + item_pop [item])
n += 1
return ret / (n * 1.0)```

## 一个最简单的算法

• 统计每个用户最常用的标签。
• 对于每个标签，统计被打过这个标签的次数最多的物品。
• 对于一个用户，首先找到他常用的标签，然后对于这些常用标签，找到具有这些标签的最热门的物品，推荐给这个用户。

`records[i] = [user, item, tag]`

，其中user_tags[u][b] =

，其中tag_items[b][i] =

```def InitStat(records):
user_tags = dict()
tag_items = dict()
for user, item, tag in records.items():
if user not in user_tags:
user_tags[user] = dict()
if tag not in user_tags[user]:
user_tags[user][tag] = 1
else:
user_tags[user][tag] += 1

if tag not in tag_items:
tag_items[tag] = dict()
if item not in tag_items[tag]:
tag_items[tag][item] = 1
else:
tag_items[tag][item] += 1```

```def Recommend(user):
recommend_items = dict()
for tag, wut in user_tags[user].items():
for item, wti in tag_items[tag].items():
if item not in recommend_items:
recommend_items[item] = wut * wti           else:
recommend_items[item] += wut * wti   return recommend_items```

## 算法的改进

[具体实验结果待正式发表时公布]

[具体实验结果待正式发表时公布]

### 标签清理

• 去除词频很高的停止词。
• 去除因词根不同造成的同义词，比如 recommender system和recommendation system。
• 去除因分隔符造成的同义词，比如 collaborative_filtering和collaborative-filtering。

[具体实验结果待正式发表时公布]

## 基于图的推荐算法

PageRank算法最初是用来对互联网上的网页进行排名的算法。网页通过超级链接形成了图。PageRank假设用户从所有网页里随机挑出一个网页，然后开始通过超级链接进行网上冲浪。到达每个网页后，用户首先会以d的概率继续冲浪，而在冲浪时，用户会以同等的概率在当前网页的所有超级链接中随机挑选一个进入下一个网页。那么，在这种模拟下，最终每个网页都会有一个被用户访问到的稳定概率，而这个概率就是网页的排名。

PageRank算法通过如下的迭代关系式来计算网页的权重：

(1)一开始，每个顶点的排名都是一样的，PR(A) = PR(B) = PR(C) = PR(D) = PR(E) = 1 / 5，令d = 0.85。

(2)根据前面的迭代关系式有

`PR(A) = (1 – 0.85) / 5 + 0.85 * (PR(B) / 2) = 0.115PR(B) = (1 – 0.85) / 5 + 0.85 * (PR(C) / 1) = 0.2PR(C) = (1 – 0.85) / 5 + 0.85 * (PR(A) / 2 + PR(D) / 2 + PR(E) / 2) = 0.285PR(D) = (1 – 0.85) / 5 + 0.85 * (PR(E) / 2) = 0.115PR(E) = (1 – 0.85) / 5 + 0.85 * (PR(A) / 2 + PR(B) / 2 + PR(D) / 2) = 0.285`

(3)继续按照前面的迭代关系式，有

`PR(A) = (1 – 0.85) / 5 + 0.85 * (PR(B) / 2) = 0.115PR(B) = (1 – 0.85) / 5 + 0.85 * (PR(C) / 1) = 0.27225PR(C) = (1 – 0.85) / 5 + 0.85 * (PR(A) / 2 + PR(D) / 2 + PR(E) / 2) = 0.248875PR(D) = (1 – 0.85) / 5 + 0.85 * (PR(E) / 2) = 0.151125PR(E) = (1 – 0.85) / 5 + 0.85 * (PR(A) / 2 + PR(B) / 2 + PR(D) / 2) = 0.21275`

PageRank算法认为，用户每次都是从所有顶点中以相同的概率随机挑选一个顶点，然后开始随机游走，而且在每次随机游走经过每个顶点时，都会有1 - d的概率停止游走。那么，如果我们要计算所有点相对于某一个顶点的相关度排名，我们可以假设用户每次都从某一个顶点v出发，然后在每次随机游走经过每个顶点时都以1-d的概率停止游走，从v重新开始。 那么，最终每个顶点被访问的概率就是这些顶点和v的相关度排名。

PageRank可以用来给图中的顶点进行全局的排名，但它无法用来给每个用户个性化的对所有物品排序。为了解决个性化排名的问题，斯坦福大学的Haveliwala提出了TopicRank的算法 ，这个算法可以用来做个性化排序，因此本文将其称为PersonalRank。PersonalRank的迭代公式如下：

```def BuildGraph(tagging_records):
graph = dict()
for user, item, tag in tagging_records:
addToMat(graph, ‘i:’+item, ‘t:’+tag, 1)def Recommend(user, d, K):
rank = dict()
rank[‘u:’+user] = 1
for step in range(0:K):
for i, ri in rank.items():
for j, wij in graph[i]:
tmp_rank[j] += d * ri * wij
tmp_rank[‘u:’ + user] = (1 – d)
sum_weight = sum(tmp_rank.values())
rank = dict()
for i, ri in tmp_rank.items():
rank[i] = ri / sum_weight
tmp_rank = dict()
return rank```

[相关实验：发表时公布

A. 迭代次数K对精度的影响

B. 边权重的定义对精度的影响

]

822 篇文章234 人订阅

0 条评论

## 相关文章

48760

227100

451100

30060

14620

### 破解黑盒？谷歌让你理解机器如何“思考”

AiTechYun 编辑：xiaoshan 在2015年，谷歌曾尝试去想象神经网络如何理解产生了迷幻图像的图像。不久之后，谷歌把其代码开源为“DeepDream...

30050

34250

40140

### 资源 | AI Challenger 2018 即将进入决赛，八大数据集抢先看

AI 研习社消息，由创新工场、搜狗、美团点评、美图联合主办的 AI Challenger 2018 即将进入第二阶段比赛。今年的大赛主题是「用 AI 挑战真实...

23520

32340