KNN模型、KNN算法2-协同过滤推荐
K近邻模型、KNN算法1案例假设有用户对曾经购买过的商品的评分数据,如何利用这份数据给用户做商品推荐?或者对一个用户,应该给他推荐哪些商品?思路逻辑图Python代码#!/usr/bin/env python# -*- coding: utf-8 -*-#@Time: 2019-11-18 22:36#@Author: gaollimport timeimpo...
·
K近邻模型、KNN算法1
案例
假设有用户对曾经购买过的商品的评分数据,如何利用这份数据给用户做商品推荐?或者对一个用户,应该给他推荐哪些商品?
思路逻辑图
Python代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#@Time: 2019-11-18 22:36
#@Author: gaoll
import time
import random
import math
from math import sqrt
import numpy as np
import matplotlib.pyplot as plt
#构造相似度函数
#欧几里德距离评价--基于距离的相似度评价
def sim_distance(vec1,vec2):
#先确认两人有哪些是共同评价过的
same = []
for i in range(len(vec1)):
if vec1[i] !='-1' and vec2[i]!='-1':
#-1表示此人未对这个商品作为评价。筛选出两人共同评价过的商品
same.append(i)
n = len(same)
if n == 0 :
return 0 #两人没有共同评价过的商品,相似度为0
sumsq = sum([pow(float(vec1[i])-float(vec2[i]),2) for i in same])
return 1/(1+sqrt(sumsq))
#皮尔逊相关度评价--去中心化的余弦公式
def sim_pearson(vec1,vec2):
#先确认两人有哪些是共同评价过的
same = []
for i in range(len(vec1)):
if vec1[i] !='-1' and vec2[i]!='-1':
same.append(i)
n = len(same)
if n == 0 :
return 0
#求简单和
sum1 = sum([ float(vec1[i]) for i in same ])
sum2 = sum([ float(vec2[i]) for i in same ])
#求平方和
sumsq1 = sum([ pow(float(vec1[i]),2) for i in same ])
sumsq2 = sum([ pow(float(vec2[i]),2) for i in same ])
#求点积和
pdsum = sum([ float(vec1[i])* float(vec2[i]) for i in same])
#根据皮尔逊等价公式
num = pdsum - (sum1*sum2)/n
den = sqrt((sumsq1-pow(sum1,2)/n)*(sumsq2-pow(sum2,2)/n))
if den == 0:
return 0
return num/den
#获取跟物品vec最相似的物品TopN
def topmatches(data,vec,k=5,simf=sim_pearson):
scores = [(simf(data[i],vec),i) for i in range(len(data)) if data[i] !=vec]
scores.sort()
scores.reverse()
return scores[0:k]
#解释Topmatch对应的物品名
def printtopmatches(scorestop,productnames):
topmatchproduct = []
for (sim,id) in scorestop:
name = productnames[id]
topmatchproduct.append((sim,name))
return topmatchproduct
#为所有物品构造相互比较的数据集,并存放最相似的K项。这个数据可以提前计算好保存使用,只需定期更新计算即可
def calculateSimilarItems(data,k=10):
result ={}
n = len(data)
for i in range(n):
vec = data[i]
if i%100 ==0:
print('Processing: %d/%d'%(i,n)) #打印计算进程,大数据集时方便查看
scorestop = topmatches(data,vec,k)
result[i]=scorestop
return result
#根据用户过去评价过的物品,从上述计算过的物品比较数据集中找出相近的物品,对于用户没有浏览或评价过的物品,根据KNN算法原理计算他可能给出的评价,根据这个预测的评价为该用户提供推荐
#利用所有人的评价的加权平均,为他人提供推荐。权重为相似度系数
def getrecommendations(similaritems,user_prefers,productnames):
#遍历下用户已经评价过哪些商品
userScored = set()
for (score,item_id) in user_prefers:
userScored.add(item_id)
predict_scores = {}
total_similarity = {}
#遍历循环用户评价过的物品
for (score,item_id) in user_prefers:
#与物品item_id相似的Top
topmatches = similaritems[item_id]
for (similarity,match_id) in topmatches:
if match_id in userScored:
continue
predict_scores.setdefault(match_id,0.0)
predict_scores[match_id] += float(similarity)*float(score) #用户对已有物品评价 * 两物品的相似系数
total_similarity.setdefault(match_id,0.0)
total_similarity[match_id] +=float(similarity)
ranking = []
for id in predict_scores.keys():
if total_similarity[id] == 0:
ranking.append((0.0,productnames[id]))
else:
ranking.append((predict_scores[id]/total_similarity[id],productnames[id]) )
#返回从高到低的评价
ranking.sort()
ranking.reverse()
return ranking
if __name__ == '__main__':
#加载数据
import prefers_data
productnames = []
prefers_data = 'prefers.txt'
scores = []
for line in open(prefers_data):
arr = line.strip('\n').split(',')
name = arr[0]
score = arr[1:]
productnames.append(name)
scores.append(score)
#计算商品的相似系数
ItemSimScores=calculateSimilarItems(scores)
#用户曾经评价过商品1,2,给这个用户做商品推荐
user_prefers=[(3.0,1),(4.5,2)]
getrecommendations(ItemSimScores,user_prefers,productnames)
结果展示
Out:
[(4.288867926988538, 'Just My Luck'),
(4.131737499239237, 'Superman returns'),
(3.845774165407422, 'You and I'),
...]
Done
更多推荐
已为社区贡献9条内容
所有评论(0)