随着信息技术和互联网的发展,人们逐渐从信息匮乏的时代走入了信息过载的时代。在这个时代,无论是信息消费者还是信息生产者都遇到了很大的挑战:如何从大量信息中找到自己感兴趣的信息是一件非常困难的事情,这个时候就需要推荐系统。推荐系统不需要用户提供明确的需求,而是通过分析用户的历史行为给用户的兴趣建模,从而主动给用户推荐能够满足他们兴趣和需求的信息。
基于邻域的算法是推荐系统中最基本的算法,该算法不仅在学术界得到了深入研究,而且在业界得到了广泛应用。基于邻域的算法分为两大类,一类是基于用户的协同过滤算法,另一类是基于物品的协同过滤算法。这里我们主要讲解基于用户的协同过滤算法。
-
原理
俗话说“物以类聚、人以群分”,拿漫威英雄来说,如果 A A A喜欢钢铁侠、美国队长、死侍等, B B B 也都喜欢这些人物形象,但他还喜欢蜘蛛侠,那么很有可能 A A A 也喜欢蜘蛛侠这个人物。
所以说,当一个用户 A A A 需要个性化推荐时,可以先找到和他兴趣相似的用户群体 B B B,然后把 B B B 喜欢的而 A A A 没有听说过的物品推荐给 A A A,这就是基于用户的系统过滤算法。 -
流程
- 找到与目标用户相似的用户集合
- 找到这个集合中用户喜欢的且目标用户没有听说过的物品推荐给目标用户
- 用户相似度计算
协同过滤算法主要利用行为的相似度计算兴趣的相似度。给定用户 u u u 和用户 v v v ,令 N ( u ) N(u) N(u) 表示用户 u u u 感兴趣的物品集合,令 N ( v ) N(v) N(v) 为用户 v v v 感兴趣的物品集合。那么我们可以通过 J a c c a r d Jaccard Jaccard 公式或者余弦公式来计算用户 u u u, v v v 的相似程度:
J a c c a r d Jaccard Jaccard公式:
w u v = ∣ N ( u ) ∩ N ( v ) ∣ ∣ N ( u ) ∪ N ( v ) ∣ {w_{uv}} = \frac{
{|N(u) \cap N(v)|}}{
{|N(u) \cup N(v)|}} wuv=∣N(u)∪N(v)∣∣N(u)∩N(v)∣
余弦相似度公式:
w u v = ∣ N ( u ) ∩ N ( v ) ∣ ∣ N ( u ) ∣ ∣ N ( v ) ∣ {w_{uv}} = \frac{
{|N(u) \cap N(v)|}}{
{\sqrt {|N(u)||N(v)|} }} wuv=∣N(u)∣∣N(v)∣∣N(u)∩N(v)∣
假设目前共有4个用户: A A A、 B B B、 C C C、 D D D;共有5个漫威英雄人物:死侍、钢铁侠、美国队长、黑豹、蜘蛛侠。用户与人物之间的爱好程度如下图所示:
用户 | 喜爱英雄人物 |
---|---|
A | 死侍、钢铁侠、美国队长 |
B | 死侍、黑豹 |
C | 钢铁侠、蜘蛛侠 |
D | 蜘蛛侠、黑豹、美国队长 |
存储的数据格式为:
def load_data(filePath):
dataSet = {
}
with open(filePath, "r", encoding="utf-8") as f:
for line in f:
user, hero, rating = line.strip().split(",")
dataSet .setdefault(user, {
})
dataSet [user][hero] = rating
return dataSet
得到数据集格式如下:
{
'A': {
'死侍': '1', '钢铁侠': '1', '美国队长': '1'}, 'B': {
'死侍': '1', '黑豹': '1'}, 'C': {
'钢铁侠': '1', '蜘蛛侠': '1'}, 'D': {
'蜘蛛侠': '1', '黑豹': '1', '美国队长': '1'}}
数据处理好之后,需要建立物品到用户的倒排表,对于每个物品都保存对该物品产生过行为的用户列表。倒排表为喜欢每个物品对应的用户,如下所示:
喜爱英雄人物 | 用户 |
---|---|
死侍 | A、B |
钢铁侠 | A、C |
美国队长 | A、D |
黑豹 | B、D |
蜘蛛侠 | C、D |
实现该功能的python方法:
def calc_user_sim(dataSet): # 建立物品-用户的倒排列表
item_users = dict()
for user, items in dataSet.items():
for movie in items:
if movie not in item_users:
item_users[movie] = set()
item_users[movie].add(user)
print("物品-用户倒排列表: ", item_users)
return item_users
结果如下:
物品-用户倒排列表: {
'钢铁侠': {
&#