全部版块 我的主页
论坛 数据科学与人工智能 人工智能 机器学习
1789 0
2016-04-06

一位算法师工程师的Spark机器学习笔记:构建一个简单的推荐系统

推荐引擎应用场景:
  • 用户有海量选择:随着场景内item越来越多,用户越来越难以选择到合适的产品
  • 个性化场景:在选择产品时,会借鉴那些与推荐用户相似地群体,利用群体智慧对用户进行推荐”千人千面”

在本篇博客中,会涉及到以下几个部分:

  • 介绍不同类型的推荐引擎
  • 使用用户偏好模型来构造推荐模型
  • 使用训练好的模型来为指定user计算给定item的相似度大的items
  • 使用标准的评测函数来构造推荐模型的好坏
推荐模型类别:
  • 基于item的过滤:使用item的内容或者属性,选择给定item的相似的item列表,这些属性一般为文本内容,包括题目、名、标签以及一些产品的元信息,通常也包括一些media信息,比如图像、音频等等
  • userId,itemId,rating和timestamp。

    from pyspark.mllib.recommendation import Rating from pyspark.mllib.recommendation import ALS ratings = rawRatings.map(lambda x : Rating(int(x[0]),int(x[1]),float(x[2]))) print ratings.first

    格式化数据,用于后面建模数据,导入Rating,ALS模块,下面是ALS类的使用说明:



    其中rank就是上面latent feature model中矩阵的k,在下面的实验中,我们设为50:

    model = ALS.train(ratings,50) # modelImplicit = ALS.(ratings,50,alpha=0.02) userFeatures = model.userFeatures print userFeatures.take(2)


    这里user1与user2,均用50维的向量来表示,也就是上面U*k那个矩阵的每个向量

    predictRating = model.predict(789,123) print predictRating

    预测用户789对item 123的rating值,结果为3.76599662082。


    topKRecs = model.recommendProducts(userId,K) for rec in topKRecs: print rec moviesForUser = ratings.groupBy(lambda x : x.user).mapValues(list).lookup(userId) # print moviesForUser for i in sorted(moviesForUser[0],key=lambda x : x.rating,reverse=True): print i.product # for # print moviesForUser


    使用recommendProducts来为用户推荐top10的items,其items顺序为降序。MoviesForUser是从ratings数据中找出的用户789rating最高的数据,仔细看下发现数据和我们的ratings里面找出的数据貌似一个都没有相同的,那么是不是说明我们的算法不给力呢?!这个可不一定,想想看,如果推荐系统只是推荐给你看过的电影,那么它一定是一个失败的,并且完全对系统的kpi数据无提升作用,前面提到,MF的实质是通过latent feature去找到与用户过去偏好高的有某些隐性相同特征的电影(这些由整体用户的集体智慧得到),比如可能是某一类型的电影、又或者相同的演员等等,所以这里不能说明推荐系统不给力,但是确实也很难具有解释性。

    Item recommendations

    基于MF的方法中,我们可以利用之前看到k*I的矩阵,计算两个向量质检的相似性,也就是item的相似性。这样,可以很容易做相似商品推荐的场景。这里我们定义相似函数为余弦相似性:

    import numpy as np def cosineSImilarity(x,y): return np.dot(x,y)/(np.linalg.norm(x)*np.linalg.norm(y))testx = np.array([1.0,2.0,3.0]) print cosineSImilarity(testx,testx)

    然后,通过ALS建模的item的向量,拿到对应地item的向量表示:


    itemId = 567 itemFactor = model.productFeatures.lookup(itemId)[0] # itemFactor = itemFactor[1] print itemFactor # model.productFeatures.collect sims = model.productFeatures.map(lambda (id,factor):(id,cosineSImilarity(np.array(factor), np.array(itemFactor))))sims.sortBy(lambda (x,y):y,ascending=False).take(10)

    利用ALS的item向量拿到itemId为567的向量表示,然后对model的item的特征向量来计算与567的相似度,按降序排序并取top10



    这样,可以找到与567这个item相似性最大的itemlist。

    怎么判断我们生成的模型性能呢?常用的有一些比如Mean Squared Error,Root Mean Squared Error,但是这类标准无法考量推荐最终的items的排序问题,在实际工作中用的比较多的是Mean Average Precision,考虑到了item的排序造成的影响。

    MSE&RMSE:

    userProducts = ratings.map(lambda rating:(rating.user,rating.product)) print userProducts.take(1)[0] predictions = model.predictAll(userProducts).map(lambda rating:((rating.user,rating.product) ,rating.rating)) print predictions.take(5)ratingsAndPredictions = ratings.map(lambda rating:((rating.user,rating.product),rating.rating)) .join(predictions)

    MSE = ratingsAndPredictions.map(lambda ((x,y),(m,n)):math.pow(m-n,2)).reduce(lambda x,y:x+y)/ratingsAndPredictions.count print MSE print math.sqrt(MSE)

    先map ratings数据得到用户对item的组合,然后对这类数据predictAll计算该用户对item的rating估计值。然后利用join函数将预测的数据与ratings中的数据”联合”起来,塞入相似度函数进行计算,最终结果如下:

    备注:看到这里肯定有人会问题,你之前在前面recommendProducts的,没有一个item是与ratings的数据相同,但是这里为什么又对比ratings中的评分信息来衡量推荐模型的好坏呢。猜想:recommendProduct是基于最终预测的ratings的高低来推荐的,但是,考虑到前面分析的原因,应该是不仅仅是按predict的rating的高低来给定推荐产品而是参入了其他的考量,所以这里并不矛盾。

                                               转载链接:http://python.jobbole.com/84445/


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群