4 基于Hadoop的护肤品推荐系统设计
4.1 系统总体设计
本节包括两部分,首先从总体架构层面分析系统的结构,然后从功能上将系统划分成若干个部分。
4.1.1 系统架构设计
系统在架构上主要由本地服务和Hadoop集群两部分构成本地服务包括定时任务、数据更新和web服务端三个模块;Hadoop集上主要包括离线计算模块。
图4-1 系统架构图
在本地的服务主要任务是收集用户日志、收集商品属性关联信息,定时地将这些数据上传到HDFS上用以大数据计算;定时调用离线计算模块以执行MapReduce计算;定时调用数据更新模块将HDFS上保存的最新结果写入Redis中(替换掉原来的旧的结果)。同时向外提供rest接口(Web服务),以让用户可以随时查询相关计算结果。
在Hadoop集群上最主要的模块就是离线计算模块[29],其里面有计算推荐列表和热门列表的实现程序,该模块是本系统最重要的模块。
4.1.2 系统功能模块设计
系统根据功能需求划分成若干部分,包括定时任务、离线计算、数据更新和web服务端模块。
图4-2 基于Hadoop的护肤品推荐系统功能模块图
定时任务模块[30]的主要任务是定时将日志文件和商品属性文件上传至Hadoop集群的HDFS上,用于作为后续的计算数据源;并定时调用离线计算模块使执行MapReduce 计算;计算完成后定时调用数据更新模块。
离线计算模块是本系统最核心的模块,其以用户日志文件和商品属性关联信息文件作为主要输入数据源,利用HDFS作为存储、MapReduce作为分布式计算框架,参考基于内容的推荐模型思想,实现了为用户个性化推荐商品列表的功能,此外也实现了计算网站热门商品列表的功能。
数据更新模块的作用是使新计算的结果同步到Redis数据库中,其中同步的数据包括三部分,分别是推荐列表、网站热门列表和用户浏览日志数据。
web服务端模块:该模块主要功能是对外提供一些rest接口供用户做结果查询处理,比如有推荐结果查询接口、热门列表查询接口、日志信息查询接口等。此外,该模块还处理日志添加消息请求和商品上下架消息请求。
4.2 推荐模型设计
本节将主要介绍选取哪种推荐模型、该模型的原理以及其在本系统中的实现思路描述。
4.2.1 推荐模型选取
比较主流的推荐模型有协同过滤(包括User-Based CF 和Item-Based CF)、基于内容的推荐模型等。
结合实际情况分析,由于活跃用户量远远大于商品数量,所以User-Based CF显然不太适合:由于较频繁地上架新商品,并希望新的商品需要能被立马推荐,而Item-Based CF由于存在物品冷启动的问题,所以也不适合。因此,最终本课题选择参考Content-Based模型思想来实现用户的个性化商品推荐功能。
4.2.2 基于内容的推荐模型
基于内容的推荐系统结构其实现过程[31]包括三步,每步都由一个独立的部件控制。
其中,内容分析器部件对应物品表示步骤,信息学习器部件对应特征学习步骤过滤组件对应生成推荐列表步骤。下面具体分析这三个步骤:
图4-3 基于内容的推荐系统结构图
(1)物品表示
将物品转换成一个特征向量。现实应用中的item都有一些描述它的属性,这些属性有结构化的和非结构化的,对于结构化属性语意比较明确所以可以拿来就用,而对于非结构化的,我们往往需要把它转化成结构化的之后才能使用。下面介绍一下如何将一篇非结构化的文章转化成结构化向量:
假设我们要处理的总的文章集合为D={d1,d2,..,dn},假设总的文章中出现的所有单词种类集合为T={t1,t2,..,tn}了。接下来要将每篇文章均用一个属性(这里的属性就是单词)向量表示,则,例如: dj=(w1j,w2j, ..,wnj)表示成序号为j的文章,其中,w1j,表示成单词t1在序号为的文章中所占的权重。
权重的计算方法有多种,比如简单的有布尔类型的计算方法,即只要有这个属性,则权重就为1,否则就为0;也有记次数的计算方法,比如,这个单词在该文章中出现了几次则它在该文章中的权重就为几;然而信息检索中的tf-idf方式最为常用。
tf-idf的计算方法见公式(4-1):
(4-1)
其中,表示序号为k的单词与序号为j的文章对应的tf-idf值表示序号为k的单词在序号为j的文章中出现了多少次,而nk为含有序号为k的单词的文章总数。
最终,序号为k的单词在序号为的文章中所占的权重计算方法见公式 (4-2):
(4-2)
(2)特征学习[32]
利用一个用户过去喜欢(不喜欢)item的数据,以及步骤一中对各个item属性向量化的结果,来学习出此用户对各个属性的喜欢程度。这是典型的有监督分类问题,解决这个问题的常用方案有最近邻方法、Rocchio、线性分类、朴素贝叶斯算法等。下面以Rocchio算法为例做介绍:
我们已经有了一些用户的历史信息,比如{(item1,喜欢),(item2,不喜欢),...},Rocchio算法最关键的点在于获取一个最优查询向量,这个向量的特点是:它既与用户喜欢的文档最相似、同时又与用户不喜欢的文档最不相似。
在ContentBased中,我们可以类似地使用Rocchio算法来计算出用户u的特征喜欢度,计算方法见公式 (4-3):
(4-3)
其中,表示物品j的属性,和分别用来代表用户u喜欢与否的item集合:B与y分别表示正例、负例样本的相关程度,它们的值由系统给定。
Rocchio算法一个很大的优点是可以很容易地实现根据用户的反馈实时更新用户u的profile值。比如:当用户在搜索引警上输入一个有歧义的单词时比如“苹果”那么搜索第一页的结果必然是令用户不满意的,比如上面可能会有吃的苹果的内容或者Mac 相关的内容,但是根据用户在第一页的点击情况,我们可以反馈更新我们的相关文档和不相关文档,然后根据公式(4-3)重新计算该用户的profile,那么用户第二次搜索这个有歧义的单词时就可以得到优化的结果了。
(3)生成推荐列表
利用之前两个步骤获取的item的特征向量以及用户的喜好profile,进行预测分类。预测分类的核心就是相似度衡量。可以通过多种方式计算相似度,下面以向量夹角余弦为例进行分析,相似度的计算方法如公式 (4-4) 所示。
(4-4)
表示,用户U对Tag(a)的喜好值(即User Profiles中,Tag(a)对应的值)。
表示,物品I中Tag(a)的权重值(即Item tag向量中,Tag(a)对应的值)。
4.2.3 系统推荐模型描述
参考基于内容的推荐模型原理[33],结合实际情况,本系统中的推荐模型设计流程图如图 4-4 所示。其中,输入是用户日志信息文件和商品属性关联信息文件,输出是用户的推荐列表结果。
图4-4 系统推荐模型设计思路描述
(1)物品表示
售卖的是护肤品,商品数量较多,商品的特征也比较多类型、比较容易区分因此公司维护了一个属性库,属性库中存放了所有商品的所有特征属性 (可以动态添加),当要上架一个商品,在前台网站页面展示商品详细信息时,该商品的展示信息只能来自于属性库中的属性。因此,如果要表示商品,则可以将一个商品表示成由若干个属性及权重组成的向量。
(2)特征学习
该步骤的最终任务是计算出用户对各个属性的喜欢度是多少即User profiles。首先,根据用户的浏览日志,得出其对item的喜欢程度(用户对商品的评分计算规则是:每访问一次商品加一定数值的分数,最终累加用户对商品的评分总和得到最终的用户对商品的总喜欢度)。现在已经知道了用户过去喜欢哪些商品了、又知道了各个商品有哪些属性了,因此,以商品为中间介质,让商品的用户评分矩阵乘以它的物品表示向量,则可以得出用户对属性的喜欢度即User profiles。
(3)生成推荐列表
该步骤的任务是为用户生成最终的推荐结果。具体做法是:遍历网站的所有商由于前面已经知道了用户喜欢哪些属性(User profiles)、又知道了各个商品有品,哪些属性(Item Representation),因此,只需要以属性为中间介质,让属性的用户评分向量乘以属性的所属商品向量,即可得出用户对各个商品的喜欢度,最终降序排序并取前K个,即得到了该用户的推荐结果。
4.3 系统功能模块设计
系统从功能上可以分为定时任务、离线计算、数据更新和web服务端这四个模块,下面依次对其进行设计。
4.3.1 定时任务模块设计
定时任务模块的主要任务是定时向HDFS上传日志和商品属性关联信息文件定时调用离线计算模块使执行MapReduce计算以及定时调用数据更新模块
(1)定时向HDFS上传日志和商品属性关联信息文件
由于后面的推荐算法计算需要用到有关用户的历史行为记录日志以及商品属性关联信息,所以在计算之前需要采集、收集和整理好这两部分数据,然后上传至Hadoop 集群的HDFS上。
图4-5 定时上传文件时序图
(2)定时调用离线计算模块
在执行离线计算之前,系统开发人员先将写好的计算程序打包成jar包并上传至Hadoop集群的HDFS上以等待定时任务来调用。定时任务先建立与Hadoop集群的连接,然后调用离线计算模块的程序包,程序包计算推荐商品列表结果以及网站热门商品结果,并将结果写入MySQL存储端。计算任务完成后断开本地与Hadoop集群的连接。
图4-6 定时调用离线计算模块时序图
(3)定时调用数据更新模块
为了提高性能,本系统在MySOL存储的基础上引入Redis存储。由于网站的用户数量巨大,而且每个用户访问网站页面都会产生访问网页推荐模块的请求,因此网站后台如果从Redis中获取推荐数据则可以减少巨大数量的I/0操作,则将显著提高系统的性能。
这里的任务就是定时调用本地的数据更新模块,同步HDFS上的最新结果到Redis 中。
图4-7 定时调用数据更新模块时序图
4.3.2 系统推荐模型描述
离线计算模块[34]是用以执行MapReduce计算的程序。该模块主要包含两部分功能,一个是计算用户推荐商品列表结果的程序逻辑,另一个是计算网站热门商品列表结果的程序逻辑。下面对该模块中的2个功能进行详细的设计。
(1)计算用户推荐列表程序设计
图4-8为计算用户推荐商品列表程序设计流程图,包含了12个主要的步骤。该程序的输入数据为用户日志信息文件和商品属性关联信息文件;用户日志信息文件描述了用户历史访问过哪些商品;商品属性关联信息文件描述了每个商品包括哪些特征属性;输出为推荐列表结果;每个用户对应一个推荐列表字符串。下面依次对各个步骤的任务设计做描述:
①商品表示
该步骤的任务是将一个物品抽象成一个属性向量,其输入数据为商品属性关联信息文件,该文件中描述了每个商品包括哪些特征属性,因此,本步骤的任务是将每个商品中各个属性所占的权重大小按照一定方法计算出来。则最后该商品的表示就为若干个属性以及属性的权重构成的一个向量。
②预处理用户日志
该步骤的输入数据为用户日志信息文件,主要对原始的用户日志做一个预处理操作,剔除掉非法数据、去重等。
③获取用户历史访问商品记录集合
该步骤对预处理过的日志做进一步的处理,以用户Id为主键,将用户访问过的所有商品聚集到一起(可能会包含重复的商品)。为下一步的处理做数据准备工作。
④计算用户评分向量
该步骤的任务是根据用户在网站的浏览日志,计算出其对item的喜欢程度(用户对商品的评分计算规则是:每访问一次商品加一定数值的分数,最终累加用户对商品的评分总和即得到最终用户对商品的总喜欢度)。
⑤分用户评分向量
该步骤的任务是配置分割用户评分向量(在上一步中的输出数据是以用户为主键,每一行表示用户对哪些商品有评分;这一步中将数据变为以商品为主键,每一行表示这个商品被哪些用户评分过)。
⑥合并商品表示向量与用户评分向量该步骤的任务是合并item表示向量和分割之后的用户评分阵。即以商品为主键,合并该商品对应的两部分数据(这两部分数据分别是分割之后的用户评分向量和该商品的tag特征向量)。简单来说就是合并这两路数据:用户过去喜欢什么商品、商品有哪些属性,为后面计算用户喜欢什么属性做数据准备工作。
⑦用户特征学习
该步骤的任务是计算得到用户对属性的喜好程度即User Profiles。前面已经知道了用户过去喜欢哪些商品、又知道了各个商品有哪些属性,因此,在这步中以商品为中间介质,用商品的用户评分矩阵乘以它的表示向量,则可以得出User profiles。
⑧统计属性出现次数
该步骤的任务是计算IDF,即对商品tag信息表里面每个tag出现的次数进行数。并对属性总出现次数取倒数。
⑨合并商品表示向量用户特征向量及属性次数
该步骤的任务是合并三路数据(商品表示向量、用户特征向量、属性次数)为后面的计算步骤提供数据。简单理解就是合并这3类数据:商品有哪些属性、用户喜欢什么属性、各个属性分别出现了多少次。合并后以属性为主键,其它三路数据集合为值部分。
⑩用户特征向量与商品表示向量相乘
该步骤的任务是根据前面三个表格合并后的结果进行重新组合、打散。由于前面已经知道了用户喜欢哪些属性(User profiles)、又知道了各个商品有哪些属性(Item Representation),所以,这步中只需要以属性为中间介质,让属性的用户评分向量乘以属性的所属商品向量,即可计算用户对item的喜欢分数。
⑪计算每个用户和商品组合的推荐值
该步骤的任务是计算每个user和item组合的总喜欢度分数。由于前面计算得到的结果比较分散,所以在这步中以userld:itemld组合的方式为主键,累加主键对应的值部分的分数总和。
⑫计算最后的推荐结果
该步骤首先将前面步骤中的userId:itemId主键拆成以userId为主键,然后将该用户对应的所有商品及喜欢度总分数放到一个集合中并作为主键对应的值部分,然后对该集合中的商品元素按总分数进行降序排序(用户历史访问过的商品不参与排序),最后取前K个,并将结果写入HDFS以及保存进MySQL数据库中。
图4-8 计算推荐列表过程程序设计
(2)计算网站热门商品列表程序设计
计算网站热门商品列表程序设计流程图如图4-9所示,包含了3个主要的步骤该程序的输入数据为用户日志信息文件:其描述了用户历史访问过哪些商品;输出为热门商品列表结果:由一个序号和一个热门列表字符串组成。下面依次对各个步骤的任务设计做描述:
①预处理用户日志
该步骤的输入数据为用户日志信息文件,主要对原始的用户日志做一个预处理操作,剔除掉非法数据、去重等。
②统计商品访问次数
该步骤的任务是对商品的访问次数进行计数。
③找出最热门的前K个商品
该步骤的任务是根据各个商品的总访问次数进行排序(由高到低排序),然后找出总访问次数最多的前K个商品作为最热门的前K个商品,最后将结果写入HDFS和MySQL 数据库中。
图4-9 计算网络热门列表过程程序设计
4.3.3 数据更新模块设计
数据更新模块的作用是使HDFS上的最新数据同步到Redis中,其中同步的数据包括三部分,分别是用户的推荐商品列表结果、网站热门商品列表数据以及用户的历史行为记录日志信息。为了不产生混乱,应该将各部分数据放在Redis的不同db中保存。
(1)更新推荐列表
先从HDFS上获取最新的推荐列表,再将其同步到Redis中。在进行同步操作之前先清空上一次的推荐结果数据。在Redis中推荐列表结果的存储格式为set类型其中,key部分为用户Id,member部分为商品Id,score部分为推荐分数。
(2)更新热门列表
先从HDFS上获取最新的热门列表,再将其同步到Redis中。在进行同步操作之前先清空上一次的热门结果数据。在Redis中热门商品列表结果的存储格式为zset类型,key部分为一个固定的字符串常量,member部分为商品Id,score部分为其被访问的总次数。
(3)更新用户日志信息
先从HDFS上获取最新的用户日志信息,再将其同步到Redis中。在进行同步操作之前先清空上一次的用户日志数据。在Redis中用户日志信息的存储格式为zset类型,其中,key部分为用户Id,member部分为商品Id,score部分为一个固定的数字常量。
4.3.4 web服务端模块设计
web服务端模块是个web-server后台,对外提供rest服务,它实现了各个rest接口的处理逻辑。该模块的功能主要包括推荐结果查询接口的处理逻辑、热门商品查询接口的处理逻辑、用户日志查询接口的处理逻辑、日志添加消息请求接口的处理逻辑和商品上下架消息请求接口的处理逻辑。下面对该模块中的5个功能进行详细的设计。
(1)推荐结果查询接口
当用户向该接口发送Get请求时,后台的处理逻辑是根据该用户的id去访问Redis,并将对应的推荐列表返回给当前用户。
图4-10 推荐结果查询接口时序图
(2)热门商品查询接口当用户向该接口发送Get请求时,后台的处理逻辑是去访问Redis数据库,获取热门商品列表并将结果返回给用户。
图4-11 热门商品列表查询接口处理过程
(3)用户日志查询接口
当用户向该接口发送Get请求时,后台的处理逻辑是根据该用户的id去访问Redis 数据库,并将该用户最近的N条历史行为记录日志返回给用户。
图4-12 用户日志信息查询接口处理过程
(4)日志添加请求处理接口
网站每产生一条新的日志时,都会往该接口发送一个Post请求,并且在请求体中封装好了一定的日志格式。该接口收到这个Post请求后,后台的处理逻辑是解析请求体中的日志格式,并重新按照一定格式拼接成一条新的日志数据,然后将这条日志写入本地文件中。而这个本地文件就是将来会被定时上传至Hadoop集群的HDFS上用做大数据计算的输入数据源文件之一。
图4-13 日志添加信息接口处理过程
(5)商品上下架请求处理接口
当网站有商品上架或者下架操作时,都会往该接口发送一个Post请求,并且在请求体中封装好了一定的格式,比如指明是上架还是下架以及附有商品的id等信息该接口收到这个Post请求后,后台的处理逻辑是先解析请求体,如果是上架,则:根据商品的id去访问公司网站的商品详情展示页面,该页面上展示了该商品包含的特征信息标签,而这些标签都来自于属性库中的标签,因此,解析该商品的详情展示页面依次获取该商品包含的所有标签对应的编号,然后将该商品id与它包含的所有特征信息标签id组成一条一定格式的新的数据,最后调用相关接口将这条数据添加到MySQL的商品属性关联信息表中;如果是下架,则:根据商品d,调用相关接口从MySQL的item tag表中删除这个item对应的tag信息数据。
图4-14 商品上下架请求处理接口时序图
4.4 系统数据库设计
基于Hadoop的护肤品推荐系统需要存储的数据主要有各个用户的推荐结果列表数据、网站热门商品列表数据、属性信息数据、商品属性关联信息数据等。这些数据都存储于物理机器的数据库中,运维人员可以对其进行相应的管理,并对外提供增删改查的操作接口。
4.4.1 数据库概念结构设计
基于Hadoop的护肤品推荐系统的数据库所使用的的对象主要包括系统推荐商品列表、热门商品列表、属性信息和商品属性关联信息.
推荐商品列表中存放了各个用户的推荐列表集合信息,该对象所包含的属性包括用户Id和该用户对应的推荐列表。热门商品列表中存放了网站热门商品列表集合信息,该对象包含的属性包括列表序号和热门列表。属性信息对象维护了公司网站所有商品的所有特征信息标签(可以动态添加标签),公司网站商品详情展示页面上商品的展示特征信息内容只能来自于该对象的标签,该对象中包含了属性编号和属性名称。商品属性关联信息对象中记录了各个商品以及它们所包含的特征信息标签,该对象包含的属性包括itemId和商品所包含的tag列表。
图4-15 E-R图
4.4.2 数据库逻辑结构设计
根据前面进行的概念设计及基于Hadoop的护肤品推荐系统的功能设计,得出本系统的数据存储信息设计有如下表结构。
(1)用户推荐集合表: recommendation_list
用户推荐集合表包括用户Id和该用户对应的前K个推荐商品组成的一个字符串(字符串由K个商品Id和其对应的推荐分数组成)。其中用户Id作为主键,推荐商品组成的字符串可重复。
表4-1 recommendation_list表结构
字段名
|
数据type
|
数据length
|
主键
|
允许为空
|
备注
|
user_id
|
int
|
11
|
是
|
否
|
|
rec_items
|
varchar
|
120
|
|
否
|
|
(2)热门商品表:topk list
热门商品表包括列表序号和前K个热门商品组成的一个字符串(字符串由K个商品Id组成)。其中列表序号作为主键。
表4-2 topk_list表结构
字段名
|
数据type
|
数据length
|
主键
|
允许为空
|
备注
|
list_index
|
int
|
11
|
是
|
否
|
|
hot_items
|
varchar
|
120
|
|
否
|
|
(3)属性信息表:tag
属性信息表包括属性编号和属性名称。其中属性编号作为主键。
表4-3 tag表结构
字段名
|
数据type
|
数据length
|
主键
|
允许为空
|
备注
|
tag_id
|
int
|
11
|
是
|
否
|
|
tag_name
|
varchar
|
64
|
|
否
|
|
(4)商品属性关联信息表:item tag
商品属性关联信息表包括itemId和该商品所包含的特征信息标签组成的一个字符串(字符串由多个tagld组成)。其中itemld作为主键,商品tag属性组成的字符串可重复。
表4-2 item_tag表结构
字段名
|
数据type
|
数据length
|
主键
|
允许为空
|
备注
|
item_id
|
int
|
11
|
是
|
否
|
|
tag_list
|
varchar
|
256
|
|
否
|
|
4.5 本章小结
本章首先从整体上分析了系统的结构,并从功能上将系统划分成了若干个部分并分别对其做详细设计,然后描述了推荐模型的思路,最后完成了数据存储的设计。