奇异值分解(Singular Value Decomposition)算法,可以将数据映射到低维空间,常用于从有噪声数据中抽取相关特征。
(1)先利用SVD从数据中构建一个主题空间;
(2)然后在该空间下计算相似度;
(1)优点:简化数据,去除噪声,提高算法的结果
(2)缺点:数据的转换可能难以理解
(3)应用:最优化问题、特征值问题、最小乘方问题、广义逆矩阵问题、信息检索、图像压缩等。
协同过滤是通过将用户和其他用户的数据进行对比来实现推荐。当知道两个用户或两个物品之间的相似度时,就可以利用已有数据来预测未知用户的喜好。协同过滤不关心物品的描述属性,而是按照许多用户的观点来计算相似度。
相似度的计算主要有两种方法:基于物品(item-based)的相似度和基于用户(user-based)的相似度。具体选择哪一种,取决于用户或物品的数量。当用户数量远大于物品种类时(如电商网站推荐、电影推荐),更倾向于使用基于物品相似度的计算方法。
常见的相似度计算方法有三种:
(1)欧氏距离计算相似度:
(2)Pearson相关系数计算相似度:
(3)余弦计算相似度:
现在构建一个推荐引擎,该推荐引擎关注的是餐馆食物的推荐。当一个人外出吃饭时,如果不能确定该到哪儿吃饭,该点什么菜。我们的推荐系统就可以给他提供一个个性化推荐。
构建餐馆菜肴推荐系统时,主要分两个阶段:
第一阶段,先构建一个基本的推荐系统,能够寻找用户没有尝过的菜肴。
第二阶段,通过SVD来减少特征空间并提高推荐的效果。
推荐系统的过程流程是:给定一个用户,系统会为此用户返回N个最好的推荐菜。为了实现这一点,我们需要做到:
(1)寻找用户没有评级的菜肴,即用户—物品矩阵中的0值;
(2)在用户没有评级的所有物品中,对每个物品预计一个可能的评级分数。
(3)对这些物品的评分从高到低进行排序,返回前N个物品。
基本推荐系统的代码如下所示:
# -*- coding: utf-8 -*-
"""
Created on Thu Dec 15 11:02:00 2016
@author: Administrator
"""
from numpy import *
from numpy import linalg as la
def loadExData():
return [[1,1,1,0,0],
[2,2,2,0,0],
[1,1,1,0,0],
[5,5,5,0,0],
[1,1,0,2,2],
[0,0,0,3,3],
[0,0,0,1,1]]
#相似度计算
#1.使用欧氏距离计算相似度
def eulidSim(inA,inB):
return 1.0/(1.0 + la.norm(inA - inB))
#2.使用Pearson相关系数计算相似度
def pearsonSim(inA,inB):
if len(inA) < 3 :
return 1.0
return 0.5 + 0.5 * corrcoef(inA,inB,rowvar = 0)[0][1]
#3.使用余弦相似度计算相似度
def cosineSim(inA,inB):
num = float(inA.T*inB)
denom = la.norm(inA) * la.norm(inB)
return 0.5 + 0.5 * (num / denom)
#基于物品相似度的推荐引擎
def standEst(dataMat,user,simMeas,item):
n = shape(dataMat)[1]
simTotal = 0.0
ratSimTotal = 0.0
for j in range(n):
userRating = dataMat[user,j]
if userRating == 0:
continue
overLap = nonzero(logical_and(dataMat[:,item].A>0,dataMat[:,j].A>0))[0]
if len(overLap) == 0:
similarity = 0
else:
similarity = simMeas(dataMat[overLap,item],dataMat[overLap,j])
#
simTotal += similarity
ratSimTotal += similarity * userRating
if simTotal == 0 :
return 0
else:
return ratSimTotal / simTotal
#
def recommend(dataMat,user,N=3,simMeas=cosineSim,estMethod=standEst):
unratedItems = nonzero(dataMat[user,:].A == 0)[1]
if len(unratedItems) == 0 :
return 'you rated everything'
itemScores = []
for item in unratedItems:
estimatedScore = estMethod(dataMat,user,simMeas,item)
itemScores.append((item,estimatedScore))
return sorted(itemScores,key=lambda jj:jj[1],reverse=True)[:N]