信息内容安全实验
各种链接
教程
movielens数据集介绍1
movielens数据集介绍2
各领域公开数据集
差不多的原理+代码
用Python写个简单的推荐系统(一)
皮尔逊相关系数评估相似度
关于皮尔逊相关系数
两个变量之间的皮尔逊相关系数定义为两个变量之间的协方差和标准差的商:
以上方程定义了总体相关系数, 一般表示成希腊字母ρ(rho)。基于样本对协方差和标准差进行估计,可以得到样本相关系数, 一般表示成r:
对于有些用户会给评分的电影普遍打高分,而有些用户普遍打的分低,用皮尔逊相关系数就可以更好的体现相似度,一样可以体现出两种高低趋势下对同种电影的相似偏好
用皮尔逊相关度定义函数
def sim_pearson(prefer, person1, person2):
sim = {}
#查找双方都评价过的项
for item in prefer[person1]:
if item in prefer[person2]:
sim[item] = 1 #将相同项添加到字典sim中
#元素个数
n = len(sim)
if len(sim)==0:
return -1
# 所有偏好之和
sum1 = sum([prefer[person1][item] for item in sim])
sum2 = sum([prefer[person2][item] for item in sim])
#求平方和
sum1Sq = sum( [pow(prefer[person1][item] ,2) for item in sim] )
sum2Sq = sum( [pow(prefer[person2][item] ,2) for item in sim] )
#求乘积之和 ∑XiYi
sumMulti = sum([prefer[person1][item]*prefer[person2][item] for item in sim])
num1 = sumMulti - (sum1*sum2/n)
num2 = sqrt( (sum1Sq-pow(sum1,2)/n)*(sum2Sq-pow(sum2,2)/n))
if num2==0: ### 如果分母为0,本处将返回0.
return 0
result = num1/num2
return result
用皮尔逊相关系数的recommendations1 模块求相关评价值
import recommendations1
print (sim_pearson(critics, ‘Cathy’,’Sophie’)
0.39605901719066977
相似度排名列表
上述的方法只能先计算出任两个人之间的相似度,下面我们就来找和自己有相似品味的影评者。将该函数加入上面皮尔逊方法的recommendations1.py中,得到一个人员的有序列表
def topmatches (prefs,person,n,similarity=sim_pearson):
scores=[(similarity(prefs,person,other),other)
for other in prefs if other!=person]
scores.sort()#sort the similarity
scores.reverse()
return scores[0:n]
用MovieLens数据集做推荐(Python推荐系统二)
思路:下载MovieLens的数据集,对数据集进行函数定义,定义各数据列的名称,根据上一篇Python写出简单的推荐系统(一) 文中的recommendations.py 的用户相似度进行推荐。
协同过滤介绍和简单推荐系统的实现
获取推荐列表
依然以上面的prefer数据集为基础,根据计算结果将兴趣相似的用户评分较高的电影推荐给用户。
获取相似用户
#从用户评价字典中返回Top-K匹配者
#K,相似度函数 为可选参数
def topMatches(prefer, person, n=2, similarity=sim_pearson):
scores=[ (similarity(prefer,person,other),other) for other in prefer if other!=person ]
#对scores列表排序,从高到底
scores.sort()
scores.reverse()
return scores[0:n] #返回排序列表, 注意[0:n],仅返回前n项;
#测试
print("\n测试topMatches()方法......")
print(topMatches(dic, 'tommy'))
结果:
[(0.9999999999999988, 'jim'), (0.9999999999999973, 'jack')]
(相似度,姓名)
利用MovieLens公开数据集做推荐
#获取影片的id和标题(其他项类似)
movies = {}
for line in open(str1,'r'):
(id,title) = line.split('|')[0:2] #将返回列表的前2元素赋给元组
movies[id] = title
#print(movies[id]) [测试输出正常,但是遇到UnicodeEncodeError?]
完整代码:
文件一loadMovieLens.py,加载测试集数据
def loadMovieLens():
str1 = '/data/movielens/u.item'
#获取影片的id和标题(其他项类似)
movies = {}
for line in open(str1,'r'):
(id,title) = line.split('|')[0:2] #将返回列表的前2元素赋给元组
movies[id] = title
#print(movies[id]) [测试输出正常,但是遇到UnicodeEncodeError?]
# 加载数据
prefer = {}
for line in open('/data/movielens/u.data'):
(user, movieid, rating,ts) = line.split('\t') #数据集中每行有4项
prefer.setdefault(user, {}) #设置字典的默认格式,元素是user:{}字典
prefer[user][movies[movieid]] = float(rating)
# 返回字典:user以及评价过的电影
return prefer
预测准确度(离线)
这个指标是最重要的推荐系统离线评测指标。
对于测试集中的一个用户u和物品i,令rui是用户u对物品i的实际评分,而^rui是推荐算法给出的预测评分
RMSE的定义为:
假设我们用一个列表records存放用户评分数据,令records[i] = [u, i, rui, pui],其中rui是用户u对物品i的实际评分,pui是算法预测出来的用户u对物品i的评分,那么下面的代码实现了RMSE的计算过程。
def RMSE(records):
return math.sqrt(sum([(rui-pui)*(rui-pui) for u,i,rui,pui in records])/float(len(records)))
学习记录——推荐系统实践 2.3 MovieLens数据集的训练练习##### 预测准确度(TOPN推荐)
通过 准确率 / 召回率 评测推荐算法的精度
u 表示 用户 u
R(u) 表示推荐系统对用户 u 推荐 N 个 物品
T(u) 表示用户 u 在 测试集上 喜欢的 物品集合
召回率 = 推荐系统推荐正确的物品数 / 用户实际上喜欢的物品总数
准确率 = 推荐系统推荐正确的物品数 / 推荐系统推荐的物品总数
import math
# 预测准确度
# - 召回率
def Recall(train, test, N):
hit = 0
all = 0
tu = []
rank = dict()
for user in train.keys():
if user in list(test.keys()):
tu = test[user]
rank = GetRecommendation(user, N)
for item, pui in rank.items():
if item in tu:
hit += 1
all += len(tu)
return hit / (all * 1.0)
# - 准确率
def Precision(train, test, N):
hit = 0
all = 0
tu = []
rank = dict()
for user in train.keys():
if user in list(test.keys()):
tu = test[user]
rank = GetRecommendation(user, N)
for item, pui in rank.items():
if item in tu:
hit += 1
all += N
return hit / (all * 1.0)
目前的成果
from math import sqrt
import numpy as np
from loadMovieLens import loadMovieLensTrain
from loadMovieLens import loadMovieLensTest
from loadMovieLens import loadMovieLens
import math
### 计算pearson相关度
def sim_pearson(prefer, person1, person2):
sim = {}
#查找双方都评价过的项
for item in prefer[person1]:
if item in prefer[person2]:
sim[item] = 1 #将相同项添加到字典sim中
#元素个数
n = len(sim)
if len(sim)==0:
return -1
# 所有偏好之和
sum1 = sum([prefer[person1][item] for item in sim])
sum2 = sum([prefer[person2][item] for item in sim])
#求平方和
sum1Sq = sum( [pow(prefer[person1][item] ,2) for item in sim] )
sum2Sq = sum( [pow(prefer[person2][item] ,2) for item in sim] )
#求乘积之和 ∑XiYi
sumMulti = sum([prefer[person1][item]*prefer[person2][item] for item in sim])
num1 = sumMulti - (sum1*sum2/n)
num2 = sqrt( (sum1Sq-pow(sum1,2)/n)*(sum2Sq-pow(sum2,2)/n))
if num2==0: ### 如果分母为0,本处将返回0.
return 0
result = num1/num2
return result
### 获取对item评分的K个最相似用户(K默认20)
def topKMatches(prefer, person, itemId, k=20, sim = sim_pearson):
userSet = []
scores = []
users = []
#找出所有prefer中评价过Item的用户,存入userSet
for user in prefer:
if itemId in prefer[user]:
userSet.append(user)
#计算相似性
scores = [(sim(prefer, person, other),other) for other in userSet if other!=person]
#按相似度排序
scores.sort()
scores.reverse()
if len(scores)<=k: #如果小于k,只选择这些做推荐。
for item in scores:
users.append(item[1]) #提取每项的userId
return users
else: #如果>k,截取k个用户
kscore = scores[0:k]
for item in kscore:
users.append(item[1]) #提取每项的userId
return users #返回K个最相似用户的ID
### 计算用户的平均评分
def getAverage(prefer, userId):
count = 0
sum = 0
for item in prefer[userId]:
sum = sum + prefer[userId][item]
count = count+1
return sum/count
### 平均加权策略,预测userId对itemId的评分
def getRating(prefer1, userId, itemId, knumber=20,similarity=sim_pearson):
sim = 0.0
averageOther =0.0
jiaquanAverage = 0.0
simSums = 0.0
#获取K近邻用户(评过分的用户集)
users = topKMatches(prefer1, userId, itemId, k=knumber, sim = sim_pearson)
#获取userId 的平均值
averageOfUser = getAverage(prefer1, userId)
#计算每个用户的加权,预测
for other in users:
sim = similarity(prefer1, userId, other) #计算比较其他用户的相似度
averageOther = getAverage(prefer1, other) #该用户的平均分
# 累加
simSums += abs(sim) #取绝对值
jiaquanAverage += (prefer1[other][itemId]-averageOther)*sim #累加,一些值为负
# simSums为0,即该项目尚未被其他用户评分,这里的处理方法:返回用户平均分
if simSums==0:
return averageOfUser
else:
return (averageOfUser + jiaquanAverage/simSums)
# 提供推荐,利用所有人评价的加权均值。 相似度高,影响因子越大。
def getRecommendations(prefer, person, similarity=sim_pearson):
totals = {}
simSums = {}
for other in prefer:
if other == person:
continue
else:
sim = similarity(prefer, person, other) #计算比较其他用户的相似度
#相似度>0
if sim<=0: continue
for item in prefer[other]:
if item not in prefer[person]:
#加权评价值:相似度*评价值
totals.setdefault(item,0) #每轮循环开始时初始化为0
totals[item] += prefer[other][item]*sim
#相似度之和
simSums.setdefault(item,0)
simSums[item] += sim
#建立归一化列表
ranks = [ (total/simSums[item],item) for item,total in totals.items() ]
#返回经排序后的列表
ranks.sort()
ranks.reverse()
return ranks
##==================================================================
## getAllUserRating(): 获取所有用户的预测评分,存放到fileResult中
##
## 参数:fileTrain,fileTest 是训练文件和对应的测试文件,fileResult为结果文件
## similarity是相似度度量方法,默认是皮尔森。
##==================================================================
def getAllUserRating(fileTrain='u1.base', fileTest='u1.test', fileResult='result.txt', similarity=sim_pearson):
prefer1 = loadMovieLensTrain(fileTrain) # 加载训练集
prefer2 = loadMovieLensTest(fileTest) # 加载测试集
inAllnum = 0
prefer={}
mid = 0
rmse = 0
file = open(fileResult, 'a')
file.write("%s\n"%("------------------------------------------------------"))
for userid in prefer2: #test集中每个用户
for item in prefer2[userid]: #对于test集合中每一个项目用base数据集,CF预测评分
rating = getRating(prefer1, userid, item, 20) #基于训练集预测用户评分(用户数目<=K)
file.write('%s\t%s\t%s\n'%(userid, item, rating))
temp = pow(prefer2[userid][item]-rating,2)
mid += temp
inAllnum = inAllnum +1
num = num + 1
rmse += math.sqrt(mid/num)
file.close()
print("-------------Completed!!-----------",inAllnum)
print("rmse=",rmse/inAllnum)
def recommand(userId):
rec = [0]*20
itemId = [0]*20
recc = {}
flag = 0
for i in range(20):
rec[i] = float(0)
for line in open('result.txt', 'r'): # 打开指定文件
num = 1
i = 18
(userid, item, rating) = line.split('\t') # 数据集中每行有3项
if userid == userId:
flag = 1
if float(rating) > float(rec[19]):
rec[19] = rating
rat = rating
itemId[19] = item
for n in range(0,19):
if float(rat) > float(rec[i]):
rating = rec[i]
rec[i] = rec[i+1]
rec[i+1] = rating
item = itemId[i]
itemId[i] = itemId[i+1]
itemId[i+1] = item
i =i-1
n = n + 1
elif userid < userId: continue
else :
for i in range(20):
if itemId[i] !=0:
print("recommand user ",userId," movie: " ,itemId[i])
break
############ 主程序 ##############
if __name__ == "__main__":
uid = 0
prompt = """
----------------选择你想要的服务----------------
(1)计算各用户预测评分
(2)推荐系统
(3)退出
请输入你想要的服务:"""
while True:
choice = input(prompt)
if choice == '3':
break
elif choice == '1':
print("\n--------------基于MovieLens的推荐系统 运行中... -----------\n")
getAllUserRating('u1.base', 'u1.test', 'result.txt')
print("\n-------------------MovieLens 测试数据集的推荐系统--------------------")
#prefers = loadMovieLens()
#print("\n1.*********基于用户的推荐**********\n")
#print("用户87的评价列表为:",prefers['87'])
#print("\n**********推荐影片*********\n")
#rec = getRecommendations(prefers, '87')[0:20]
#print(rec)
else :
print("输入用户ID:")
uid = input()
recommand(uid)