协同过滤学习笔记(一)

import numpy as np

users = {'zhangsan': {'book1': 2.0, 'book2': 3.5, 'book3': 4.0, 'book5': 3.0},
         'lisi': {'book1': 1.5, 'book3': 3.0, 'book4': 5.0},
         'wangwu': {'book2': 3.0, 'book4': 1.0},
         'maliu': {'book1': 1.0, 'book2': 3.0, 'book3': 4.0, 'book4': 5.0, 'book5': 3.0},
         'tom': {'book1': 4.75, 'book2': 4.5, 'book3': 5, 'book4': 4.25, 'book5': 4},
         'jerry': {'book1': 4, 'book2': 3, 'book3': 5, 'book4': 2, 'book5': 1}
         }


# 距离计算策略
# 如果数据受分数贬值,使用Pearson系数
# 如果数据稠密,几乎所有属性都没有零值,使用欧式或曼哈顿
# 如果数据稀疏,考虑余弦相似度

# part1 :距离计算
def distance_manhatan(user1, user2):
    distance = 0
    for keys in user1:
        if keys in user2:
            distance += abs(user1[keys] - user2[keys])
    return distance


def distance_minkov(user1, user2, param):
    distance = 0
    for keys in user1:
        if keys in user2:
            distance += abs(user1[keys] - user2[keys]) ** param
    distance = distance ** (1 / param)
    return distance


def compute_nearest(username, users=users):
    distances = {}
    for user in users:
        distance = distance_minkov(users[username], users[user], 1)
        distances[user] = distance
    sorted(distances.items(), key=lambda item: item[1])
    return distances


# part2:由于用户评价差异带来的问题,即严苛的用户和宽松的用户
# 解决办法使用皮尔逊相关系数
def pearson(user1, user2):
    # 使用原型公式需要多次遍历,所以这里的计算使用Pearson变体,
    sum_xy = 0
    sum_x = 0
    sum_y = 0
    sum_x2 = 0
    sum_y2 = 0
    # 共同打分项数量
    n = 0
    for user in user1:
        if user in user2:
            x = user1[user]
            y = user2[user]
            n += 1
            sum_xy += x * y
            sum_x += x
            sum_y += y
            sum_x2 += x ** 2
            sum_y2 += y ** 2

    # 计算分母
    denominator = (sum_x2 - (sum_x ** 2) / n) ** 0.5 * (sum_y2 - (sum_y ** 2) / n) ** 0.5
    # print(denominator)
    if denominator == 0:
        return 0
    else:
        result = (sum_xy - sum_x * sum_y / n) / denominator
        return result


# cosine simularity
# part3 question 数据稀疏性问题:如在总量上亿的音乐中,利用播放次数比较两个用户,他们的公共部分绝大多数为0,但是我们不想使用这些0
# 类似地是利用词频比较书籍。因此,使用余弦相似度会忽略这种0-0匹配,即我们都没有,但并不意味我们是一类人
# cosine 属于【-1,1】
def cos(ranking1, ranking2):
    xy = np.dot(list(ranking1.values()), list(ranking2.values()))
    # print(xy)
    # 注意**的优先级比乘除高需要加括号
    x_len = (np.dot(list(ranking1.values()), list(ranking1.values()))) ** (1 / 2)
    # print(x_len)
    y_len = (np.dot(list(ranking2.values()), list(ranking2.values()))) ** (1 / 2)
    # print(y_len)
    cosine = xy / (x_len * y_len)
    return cosine


# part4:新问题又出现了,当两个用户有20首相同评价的歌时候,其中评价很相似,但是假设有另外一个用户评价过1首歌评分和他们完全相同,
# 按现行的计算方法,1首歌反而更近,设置0值会控制任一距离的计算方法,所以,变通方案是利用共同评级的歌曲距离除以共同评级的数目

# part5:当我们基于单个最相似的用户进行推荐的时候,任何该用户的怪癖都将会被推荐,所以一种解决办法是基于多个相似用户进行推荐
# 接下来我们使用k近邻来解决。
# 例如使用k=3来对tom进行推荐,那么最近的三个邻居和tom的Pearson系数如下所示jerry 0.8,bruce 0.7,bird 0.5
# 那么三人的Pearson加权占比为40%,35%,25%,假设他们对《晴天》的评价为4.5,5,3.5
# 那么最终评级+=加权占比*评价=4.275

if __name__ == '__main__':
    distance_manhatan1 = distance_manhatan(users['zhangsan'], users['wangwu'])
    distance_minkov1 = distance_minkov(users['zhangsan'], users['wangwu'], 2)
    result = pearson(users['zhangsan'], users['lisi'])
    # print(result)
    cosine = cos(users['tom'], users['jerry'])
    print('cosdistance: ' + str(cosine))
    # print(compute_nearest('zhangsan'))
    # print(distance_manhatan1)
    # print(distance_minkov1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值