推荐系统初探
算法思路
推荐系统应该算最简单的算法之一了,主要分为通过用户的购买信息来推荐商品和通过商品的被购买信息来推荐用户。
以用户角度为例。首先要找到与该被推荐用户相似的一些用户并计算其相似度。然后找到那些该被推荐用户没有购买但与他相似的用户已经购买的一些商品。通过相似度给予这些不同的商品权重,然后求和得到各个商品可能购买的几率或者评分。
以python为例具体程序
按欧式距离法求相似度
欧式距离显示的是以各个属性为坐标求得的两个用户的属性距离,这个算法与kmeans算法很相似
import datas #datas为要调用的数据集,放在另外一个文件里面
def distance(dataset,obperson,comperson):
dist=sum(pow(dataset[obperson][item]-dataset[comperson][item],2)
for item in dataset[obperson]
if item in dataset[comperson])
leng=sum(1 for items in dataset[obperson]
if items in dataset[comperson])
if leng>0:
pdist=dist/leng #因为可能涉及到的商品数目不一样所以拿总距离除商品数目更合理
if pdist:
return 1/(1+pdist) #返回1/(1+pdist)是因为距离越近应该是相似度越高,所以拿这个函数把原距离转换一下
按Pearson相关系数法求相似性
相关系数法相比距离法来表达相似度可能更加直接,不过如果涉及的是二分类(买或者没买)问题时可能没有距离法理想
import datas #加载数据集
import math
def pearson(dataset,obperson,comperson):
sum_xy=sum(dataset[obperson][items]*dataset[comperson][items]
for items in dataset[obperson]
if items in dataset[comperson])
sum_x=sum(dataset[obperson][items]
for items in dataset[obperson]
if items in dataset[comperson])
sum_y=sum(dataset[comperson][items]
for items in dataset[obperson]
if items in dataset[comperson])
sum_x2=sum(pow(dataset[obperson][items],2)
for items in dataset[obperson]
if items in dataset[comperson])
sum_y2=sum(pow(dataset[comperson][items],2)
for items in dataset[obperson]
if items in dataset[comperson])
nums =sum(1
for items in dataset[obperson]
if items in dataset[comperson])
pearson=(nums*sum_xy-sum_x*sum_y)/math.sqrt((nums*sum_x2-pow(sum_x,2))*(nums*sum_y2-pow(sum_y,2)))
return pearson
进行商品评分估计
求得相似度后,就需要通过与被推荐用户具有相似购买行为的用户的购买信息来预测该被推荐用户没有购买的商品的情况了。比如跟用户A具有很高相似度的是用户B,用户B对商品M的评价为某个分值(比如5分),而用户A由于并没有购买商品M,所以对商品M没有评价,但我们可以通过用户B的评价大概判断出A如果购买了M,因为A与B有差不多的品味,那么A很可能也会对商品M有差不多的评分。如果5分算最高分的话,那么理所当然商家应该对用户A进行关于商品M的营销。
from distance import distance
from correlation import pearson
from datas import recdata
#上面主要是引用一下之前构造的求相似度的函数和数据集,如果放在一个文件下面当然就不需要载入,不过建议还是放在不同文件下面,这样更利于维护
def recommendation(data,obperson,way):
#得到要推荐人没有购买商品而其他相似人买了商品的评分和相似性
totalrank={}
totalsimi={}
for person in data:
if person==obperson:continue
#先找到所有目标客户没有但相似客户有的商品
simi=way(data,obperson,person)
for items in data[person]:
if items not in data[obperson] or data[obperson][items]==0:
totalrank.setdefault(items,0)
totalrank[items]+=data[person][items]*simi
totalsimi.setdefault(items,0)
totalsimi[items]+=simi
#然后用每个商品的总得分除总权数
eachrank=[(totalrank[item]/totalsimi[item],item) for item in totalrank]
eachrank.sort()
eachrank.reverse()
return eachrank
这样基本一个小型的推荐系统就完成了,通过比较也可以发现不管是距离法还是Pearson相关系数法来求相似度得到的结果是差不多的。
以商品的角度
上面例子是以用户的角度,通过用户的购买信息来找到最相似的用户来推测未购买商品的信息,但当用户的购买信息不多的时候,得到的相似度的可信度是很低的,这个时候最好就以商品的角度来查找最相似的两个商品。如果其中一个商品M被A用户购买了,因为商品N和商品M最相似,那么很可能也会被A购买,那么就可以推荐该商品给用户A。当然是否最相似的商品会被购买还是不购买时要看商品的属性的。如果商品是多次消费的,那么购买M和N没区别当然会购买。但是如果商品是很长时间才需购买的,那么很显然购买了M的用户自然不会再买跟M没什么区别的N了。
python代码
以商品为角度的算法和以用户为角度的算法大同小异,只需要把原数据集做合理转化就行。
def transformation(dataset):
transdata={}
for person in dataset:
for item in recdata[person]:
transdata.setdefault(item,{})
transdata[item][person]=recdata[person][item]
return transdata