赞
踩
评分预测公式:
算法实现
实现评分预测方法:predict
- # ......
-
- def predict(uid, iid, ratings_matrix, user_similar):
- '''
- 预测给定用户对给定物品的评分值
- :param uid: 用户ID
- :param iid: 物品ID
- :param ratings_matrix: 用户-物品评分矩阵
- :param user_similar: 用户两两相似度矩阵
- :return: 预测的评分值
- '''
- print("开始预测用户<%d>对电影<%d>的评分..."%(uid, iid))
- # 1. 找出uid用户的相似用户
- similar_users = user_similar[uid].drop([uid]).dropna()
- # 相似用户筛选规则:正相关的用户
- similar_users = similar_users.where(similar_users>0).dropna()
- if similar_users.empty is True:
- raise Exception("用户<%d>没有相似的用户" % uid)
-
- # 2. 从uid用户的近邻相似用户中筛选出对iid物品有评分记录的近邻用户
- ids = set(ratings_matrix[iid].dropna().index)&set(similar_users.index)
- finally_similar_users = similar_users.ix[list(ids)]
-
- # 3. 结合uid用户与其近邻用户的相似度预测uid用户对iid物品的评分
- sum_up = 0 # 评分预测公式的分子部分的值
- sum_down = 0 # 评分预测公式的分母部分的值
- for sim_uid, similarity in finally_similar_users.iteritems():
- # 近邻用户的评分数据
- sim_user_rated_movies = ratings_matrix.ix[sim_uid].dropna()
- # 近邻用户对iid物品的评分
- sim_user_rating_for_item = sim_user_rated_movies[iid]
- # 计算分子的值
- sum_up += similarity * sim_user_rating_for_item
- # 计算分母的值
- sum_down += similarity
-
- # 计算预测的评分值并返回
- predict_rating = sum_up/sum_down
- print("预测出用户<%d>对电影<%d>的评分:%0.2f" % (uid, iid, predict_rating))
- return round(predict_rating, 2)
-
- if __name__ == '__main__':
- ratings_matrix = load_data(DATA_PATH)
-
- user_similar = compute_pearson_similarity(ratings_matrix, based="user")
- # 预测用户1对物品1的评分
- predict(1, 1, ratings_matrix, user_similar)
- # 预测用户1对物品2的评分
- predict(1, 2, ratings_matrix, user_similar)
实现预测全部评分方法:predict_all
- # ......
- def predict_all(uid, ratings_matrix, user_similar):
- '''
- 预测全部评分
- :param uid: 用户id
- :param ratings_matrix: 用户-物品打分矩阵
- :param user_similar: 用户两两间的相似度
- :return: 生成器,逐个返回预测评分
- '''
- # 准备要预测的物品的id列表
- item_ids = ratings_matrix.columns
- # 逐个预测
- for iid in item_ids:
- try:
- rating = predict(uid, iid, ratings_matrix, user_similar)
- except Exception as e:
- print(e)
- else:
- yield uid, iid, rating
-
- if __name__ == '__main__':
- ratings_matrix = load_data(DATA_PATH)
-
- user_similar = compute_pearson_similarity(ratings_matrix, based="user")
-
- for i in predict_all(1, ratings_matrix, user_similar):
- pass
添加过滤规则
- def _predict_all(uid, item_ids, ratings_matrix, user_similar):
- '''
- 预测全部评分
- :param uid: 用户id
- :param item_ids: 要预测的物品id列表
- :param ratings_matrix: 用户-物品打分矩阵
- :param user_similar: 用户两两间的相似度
- :return: 生成器,逐个返回预测评分
- '''
- # 逐个预测
- for iid in item_ids:
- try:
- rating = predict(uid, iid, ratings_matrix, user_similar)
- except Exception as e:
- print(e)
- else:
- yield uid, iid, rating
-
- def predict_all(uid, ratings_matrix, user_similar, filter_rule=None):
- '''
- 预测全部评分,并可根据条件进行前置过滤
- :param uid: 用户ID
- :param ratings_matrix: 用户-物品打分矩阵
- :param user_similar: 用户两两间的相似度
- :param filter_rule: 过滤规则,只能是四选一,否则将抛异常:"unhot","rated",["unhot","rated"],None
- :return: 生成器,逐个返回预测评分
- '''
-
- if not filter_rule:
- item_ids = ratings_matrix.columns
- elif isinstance(filter_rule, str) and filter_rule == "unhot":
- '''过滤非热门电影'''
- # 统计每部电影的评分数
- count = ratings_matrix.count()
- # 过滤出评分数高于10的电影,作为热门电影
- item_ids = count.where(count>10).dropna().index
- elif isinstance(filter_rule, str) and filter_rule == "rated":
- '''过滤用户评分过的电影'''
- # 获取用户对所有电影的评分记录
- user_ratings = ratings_matrix.ix[uid]
- # 评分范围是1-5,小于6的都是评分过的,除此以外的都是没有评分的
- _ = user_ratings<6
- item_ids = _.where(_==False).dropna().index
- elif isinstance(filter_rule, list) and set(filter_rule) == set(["unhot", "rated"]):
- '''过滤非热门和用户已经评分过的电影'''
- count = ratings_matrix.count()
- ids1 = count.where(count > 10).dropna().index
-
- user_ratings = ratings_matrix.ix[uid]
- _ = user_ratings < 6
- ids2 = _.where(_ == False).dropna().index
- # 取二者交集
- item_ids = set(ids1)&set(ids2)
- else:
- raise Exception("无效的过滤参数")
-
- yield from _predict_all(uid, item_ids, ratings_matrix, user_similar)
-
- if __name__ == '__main__':
- ratings_matrix = load_data(DATA_PATH)
-
- user_similar = compute_pearson_similarity(ratings_matrix, based="user")
-
- for result in predict_all(1, ratings_matrix, user_similar, filter_rule=["unhot", "rated"]):
- print(result)
根据预测评分为指定用户进行TOP-N推荐:
- # ......
-
- def top_k_rs_result(k):
- ratings_matrix = load_data(DATA_PATH)
- user_similar = compute_pearson_similarity(ratings_matrix, based="user")
- results = predict_all(1, ratings_matrix, user_similar, filter_rule=["unhot", "rated"])
- return sorted(results, key=lambda x: x[2], reverse=True)[:k]
-
- if __name__ == '__main__':
- from pprint import pprint
- result = top_k_rs_result(20)
- pprint(result)
-
UI 和 UE(前端界面)
数据 (Lambda架构)
业务知识
算法
推荐系统整体架构
大数据Lambda架构
由Twitter工程师Nathan Marz(storm项目发起人)提出
Lambda系统架构提供了一个结合实时数据和Hadoop预先计算的数据环境和混合平台, 提供一个实时的数据视图
分层架构
数据不可变, 可进行任何计算, 可水平扩展
高延迟 几分钟~几小时(计算量和数据量不同)
日志收集 Flume
分布式存储 Hadoop hdfs
分布式计算 Hadoop MapReduce & spark
nosql(HBase/Cassandra)
Redis/memcache
MySQL
流式处理, 持续计算
存储和分析某个窗口期内的数据
最终正确性(Eventual accuracy)
实时数据收集 flume & kafka
实时数据分析 spark streaming/storm/flink
支持随机读
需要在非常短的时间内返回结果
读取批处理层和实时处理层结果并对其归并
Lambda架构图
推荐算法架构
召回决定了最终推荐结果的天花板
协同过滤(基于用户 基于物品的)
基于内容 (根据用户行为总结出自己的偏好 根据偏好 通过文本挖掘技术找到内容上相似的商品)
基于隐语义
召回决定了最终推荐结果的天花板, 排序逼近这个极限, 决定了最终的推荐效果
CTR预估 (点击率预估 使用LR算法) 估计用户是否会点击某个商品 需要用户的点击数据
策略调整
推荐系统的整体架构
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。