核心内容摘要
揭秘“9l免费版”:开启无限可能,畅享数字自由新纪元
基于hadoop的商城推荐系统 大数据个性化商城推荐 协同过滤推荐 推荐原理每天定时更新数据集数据集为当然商城中用户的订单信息将数据集保存在hadoop的hdfs文件系统中并触发计算根据余弦相似度计算用户间的相似度再根据相似度矩阵与评分矩阵进行预测评分的计算并将计算结果保存由服务器读取缓存用于推荐 浏览页面也是这个网址区别在于推荐算法是由hadoop执行MapReduce来实现 用户端浏览网址 http://
124.
221.
2
110:8080/tmall/ 管理员登录页面http://
124.
221.
2
110:8080/tmall/admin 测试账户 管理员1209577113/xq打开商城推荐系统的后台日志能看到每天凌晨三点准时跳动的任务进度条。
这个基于Hadoop的老伙计正吭哧吭哧处理着百万级用户行为数据像极了深夜加班的程序员。
咱们今天不聊高深算法就扒一扒这个系统怎么用MapReduce把用户剁手数据变成精准推荐。
数据准备阶段最刺激。
订单表在MySQL里躺到凌晨两点五十九分突然被sqoop一把拽进HDFS。
这里有个骚操作——订单表原始结构带着十几列字段但我们的MapReduce任务只要用户ID、商品ID、购买次数这三个字段。
于是第一个Mapper直接化身断舍离大师public static class DataFilterMapper extends MapperLongWritable, Text, Text, IntWritable{ Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] cols value.toString().split(,); String userId cols[5]; // 用户ID在第6列 String itemId cols[3]; // 商品ID在第4列 int purchaseCount Integer.parseInt(cols[10]); if(!userId.isEmpty() !itemId.isEmpty()){ context.write(new Text(userId _ itemId), new IntWritable(purchaseCount)); } } }这个Mapper干了两件事把用户和商品绑定成复合键顺便把购买次数转化为可计算的数值。
注意这里用下划线连接用户商品ID是个伏笔后面Reduce阶段拆开时会真香。
用户相似度计算是重头戏。
这里用余弦相似度但没直接算向量点积而是拆成三个部分用户A的评分平方和、用户B的评分平方和、AB的评分乘积和。
看Reducer里的这段魔术// 在Reducer的reduce方法中 double dotProduct 0; double normA 0; double normB 0; for (VectorElement element : elements) { if(element.type VectorType.A){ normA Math.pow(element.value,
; } else if(element.type VectorType.B){ normB Math.pow(element.value,
; } // 计算交叉乘积 for (VectorElement other : elements) { if(element.type ! other.type){ dotProduct element.value * other.value; } } } double similarity dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));这种拆解是为了应对MapReduce的分布式计算特性——直接把两个用户的向量拉到一台机器上计算比跨节点传数据高效得多。
不过这里有个坑当用户共同评价的商品很少时相似度会被放大所以实际代码里还加了阈值过滤。
基于hadoop的商城推荐系统 大数据个性化商城推荐 协同过滤推荐 推荐原理每天定时更新数据集数据集为当然商城中用户的订单信息将数据集保存在hadoop的hdfs文件系统中并触发计算根据余弦相似度计算用户间的相似度再根据相似度矩阵与评分矩阵进行预测评分的计算并将计算结果保存由服务器读取缓存用于推荐 浏览页面也是这个网址区别在于推荐算法是由hadoop执行MapReduce来实现 用户端浏览网址 http://
124.
221.
2
110:8080/tmall/ 管理员登录页面http://
124.
221.
2
110:8080/tmall/admin 测试账户 管理员1209577113/xq生成预测评分时更有意思。
系统并不是实时计算而是每天预处理好topN相似用户的推荐池。
看这段用缓存机制的骚操作// 在推荐服务层 MapLong, ListUserSimilarity simCache LoadingCache.get(userSim); ListLong candidateItems currentUser.getBrowsedItems(); for (Long itemId : candidateItems) { double weightedSum 0; double simSum 0; for (UserSimilarity simUser : simCache.get(userId)) { Integer rating ratingDao.getUserItemRating(simUser.userId, itemId); if(rating ! null){ weightedSum simUser.similarity * rating; simSum Math.abs(simUser.similarity); } } if(simSum
{ predictedRating weightedSum / simSum; if(predictedRating
3.
{ // 过滤低分推荐 recommendQueue.add(itemId); } } }这里暗藏一个业务逻辑只推荐预测评分超过
5分的商品。
实际上线后发现这个阈值让点击率提升了23%因为过滤掉了大量勉强及格的推荐。
凌晨四点十二分当最后一个MapReduce任务完成时HDFS上的推荐结果文件已经悄悄更新。
前端的Nginx缓存则在五分钟内逐渐失效用户醒来后看到的猜你喜欢其实是昨夜数据战场厮杀后的幸存者。
这种离线推荐虽然有点时间差但对于非秒杀类商城来说省下的实时计算资源够再部署三个备用节点了。
访问测试地址时注意看URL参数——虽然页面长得一样但带recommend1的请求会走Hadoop生成的推荐池去掉参数则展示默认的热销排行。
偷偷说用测试账号买几次电子产品第二天推荐栏马上会出现相关配件这比女朋友记你的喜好还准。