本人于2021年6月毕业,当时的课题是推荐系统的算法探究与系统实现。故参考各方面资料完成了毕业设计与论文的编写。至今也有很多人问我具体系统实现的细节。我把论文贴出来供大家参考借鉴。
终稿论文总查重率5.7%
首先说一下系统的特点:部署在Windows上!Windows上!Windows上!
没有用到虚拟机,没有用到云服务器。
目录
摘要.ii
Abstractii
第一章绪论.1
1.1课题研究的背景和意义.1
1.1.1课题研究背景.1
1.1.2课题研究意义.1
1.2国内外研究现状.2
1.2.1国外研究现状.2
1.2.2国内研究现状.3
2.1JavaEE技术.4
2.1.1Spring框架.4
2.1.2MVC架构.4
2.1.3Maven5
2.1.4Restful5
2.2AngularJS框架.5
2.3数据库.5
2.3.1Redis数据库.5
2.3.2MongoDB数据库.5
2.4埋点日志的采集.6
2.4.1Flume6
2.4.2Kafka6
2.4.3Zookeeper6
2.5.1Scala7
2.5.2SparkSQL7
2.5.3SparkMLlib7
2.5.4SparkStreaming8
2.6商品推荐主要用到的算法.8
2.6.1离线统计推荐算法.8
2.6.2协同过滤算法.8
2.6.3协同过滤LFM隐语义模型.8
2.6.4实时推荐算法.9
2.7推荐系统的常见召回路径.9
2.8本次推荐系统部署环境.10
第三章系统分析与整体结构.11
3.1可行性分析.11
3.1.1技术可行性.11
3.1.2经济可行性.11
3.2系统用户需求分析.11
3.3系统性能需求分析.13
3.4系统的整体结构.13
3.5系统的数据源.15
第四章系统方案的具体设计.16
4.1系统功能设计原则.16
4.1.1微服务.16
4.1.2系统的可靠性.16
4.1.3系统的维护性.16
4.2系统总体架构设计.16
4.2.1前端模块的设计.16
4.2.2后端业务模块的设计.17
4.2.3后端推荐模块的设计.17
4.3数据库设计.17
4.3.1业务数据库:MongoDB17
4.3.2缓存数据库:Redis20
4.3.3系统数据流向.20
4.4离线统计模块设计.21
4.4.3统计推荐之均值推荐.21
4.5离线个性化推荐模块设计.22
4.5.1基于模型的协同过滤算法设计.22
4.5.2模型评估和参数选取.23
4.5.3生成商品推荐列表.24
4.5.4基于物品的协同过滤以及物品间的相似度.25
4.5.5基于物品标签的推荐.25
4.6实时推荐算法设计.25
4.6.1实时推荐算法.25
4.6.2实时推荐算法设计.26
第五章环境部署和系统实现.27
5.1环境部署.27
5.1.1基础环境.27
5.1.2MongoDB环境安装与配置.27
5.1.3Redis环境安装与配置.27
5.1.4Zookeeper环境安装配置.28
5.1.6Kafka安装与配置.28
5.1.7Flume安装与配置.28
5.1.8Scala环境配置.28
5.1.9Jdk环境配置.29
5.1.10Maven环境配置.29
5.1.11Spark环境安装配置.29
5.2成果实现展示.29
5.2.2用户注册页面展示.30
5.2.3离线统计推荐实现.30
5.2.4离线协同过滤基于模型的个性化推荐实现.31
5.2.5基于物品的协同过滤推荐实现.32
5.2.6实时推荐实现以及打分操作的流程.32
5.2.7基于物品标签的推荐.35
5.2.8商品的模糊搜索.36
第六章总结.37
6.1毕业设计总结.37
6.2推荐系统的亮点.37
6.2.1使用高效率的Spring框架.37
6.2.2推荐的多样性.37
6.2.3基于大数据环境下的系统环境的配置.37
6.3推荐系统实现中遇到的问题及解决方法总结.38
6.3.1命名规范.38
6.3.2Windows与Linux命令不兼容问题.38
6.3.3Kafka异常退出.38
6.4推荐系统的不足之处.38
6.4.1更准确的推荐算法.38
6.4.2更高效的实时计算框架.39
6.4.3单机模式下的风险.39
6.4.4用户画像(Profile).39
参考文献.40
谢辞.42
推荐系统的概念最先起源于国外,最早被运用于新闻推荐。亚马逊发现了推荐系统在电商领域的巨大潜力,最先把推荐技术运用在电商系统中。
NetFlix提出了经典的推荐架构。在20世纪末,21世纪初期国内的电商才随着互联网的普及进入国内开始发展。直到现在,国内外的各大电商的推荐系统逐渐完善,电商推荐算法也推逐渐陈出新。给人们网上购物带来极佳的的用户体验。
推荐系统的鼻是祖1994年在国被设计出来的新闻推荐系统。亚马逊率先发现了推荐算法在电商的优势,并率先将推荐系统引入到电商中。为推荐系统的发展开辟出一条道路,对之后后的电商发展产生了很大的影响。
在国外,推荐系统依旧在亚马逊沿用至今,随着技术的不断成熟以及用户体验的要求不断提升。解决冷启动问题[1],运用机器学习训练推荐模型[2]已经逐渐普及。
在2006年Netflix国外举办悬赏寻求可以将推荐准确度提高10个百分点的优秀学者。在此之后,高准确度算法推荐系统就开始出现。但仍然不能达到推荐完全正确;所以提高推荐的准确度就是衡量一个推荐算法是否有效的最好切入点。
也是推荐系统发展路上一直要攻克的难题。
2013年3月27日,Netflix的工程师在官方博客发文,推出了经典推荐系统架构——NetFlix推荐架构[3]。整个技术架构分为三层:ONLINE在线层、NEARLINE进线层、OFFLINE离线层。三层相互独立,互相配合共同完成推荐系统的运行。在线层直接对接用户与系统的交互,用户在交互的过程中会伴随着许多操作,例如评分、浏览等。这些作为前端的日志打点序列分发到离线层的Hadoop和近线层的流失处理平台(类似于SparkStreaming)。离线层一般以天或小时为粒度进行计算;数据存放于HDFS使用Pig、Hive等对数据进行过滤、提取。将最终的数据进行分发完成离线计算和模型训练。模型可以传到在线层供用户实时计算,也可以在离线层提前预计算出用户的推荐列表。还可以将矩阵分解得到用户向量和物品向量。近线层是在线层和离线层之间的桥梁,近线层的计算可能会用到离线数据,也可与在线层的数据相接。这一层的计算结果往往存到一些高速缓存,以备调用。在线层一般会存在一个算法服务调度,这个服务会从高速缓存中获取数据,使用在线层计算将结果快速计算出来。在线层不可以使用复杂的算法,不能读取大量数据,因为要确保数据的快速响应。
2006年,国内书籍电商巨头当当网首次将推荐系统运用,收到广大用户的好评;两年之后,淘宝团队也研发出自己的电商推荐模块加以运用——“i淘宝”
这是淘宝电商推荐系统的雏形;到了2011年,百度也加入推荐技术行列,着重于搜索技术的个性化推荐。并提出了“一人一世界”的口号。
近几年,用户画像逐渐成为推荐系统最火爆的应用。用户画像也能更精确的为每个用户添加标签,给用户精准定位。目的就是为了把握每个用户的兴趣喜好,推广合适的业务给用户。
在当下互联网B/S模式的兴起,Spring开源框架成为各大互联网哪个公司搭建项目的首选。在web端的开发语言中,根据调查结果(图2.1)Java无疑是近10年来开发者的首选。由于其跨平台性、高效的计算性能,以及全球众多开发者在类库和框架方面的开源贡献,Java语言是本次课题项目实现业务系统综合业务的首选,此次选择的是基于Java语言的Spring框架。
在Spring框架是为了简化JavaWeb开发而创建的;传统的企业级应用开发,庞大的EJB使开饭维护工作量异常大;除了写代码逻辑,更重要的是配置组件之间的关系。然而为了解决这一难题。Spring框架诞生,Spring是一个容器框架,帮助开发者注册加载各种组件,实现较EJB轻量级开发。
系统利用当下主流的MVC结构模式结构进行开发,M、V、C分别代表业后端编码的三大构成M(模型)层大体可以分为两类:承载数据的实体类业务处理的处理类。和、V(视图)层是用户直面系统的一层,也是用户和系统交互的一层、C(控制)层把用户和系统的交互操作转换成请求发给相应的模型,根据模型的处理结果向用户返回响应,MVC是如今J2EE应用极其广泛的层次架构。
Maven是Apache基金会开源的依赖控制组件,是现大型web项目采用的jar包依赖以及模块控制的结构,用小段描述信息管理项目的构建,便于开发人员直观的查看项目结构和依赖。
Restful是基于HTTP的一种网络应用程序的设计风格,是一种开发规范,用来写接口时规范命名,使用restful风格开发接口可以使接口名称长度变短,更加简单清爽简介,也便于开发人员直观阅读,看到接口的名称就可以判断该接口的功能。适用于移动互联网厂商作为业务接口的场景,通过发起方式的不同请求完成对数据的增、删、查、改等操作,极大的提升开发效率。
前端框架采用AngularJS,谷歌开源。AngularJS可以实现数据的双向绑定。双向绑定的操作通过检查脏数据完成,但是脏检查机制不是定时进行,而是在数据发生变化时也就是dom元素或者xhr事件的变化会引起底层的digest函数,这个函数会从底层逐步遍,检查所有的watcher是否变化,如果数据变化,那么就会执行指令完成数据变化。从而实现双向绑定。
电商推荐系统的构建选择非关系型数据库;因为在大数据环境下,数据的量级大且有一个特征:关系不一定完整;关系型数据库并不适合大数据环境下的数据存数;所以利用非关系型数据库非常符合本次场景,是大数据环境下业务的需要。
Redis是一种非结构化数据库,是一种作用在内存上的缓存数据库,Redis的读、写性能极高,可作为缓存、消息队列、分布式锁等场景应用。这次毕业设计基于大数据平台商推荐系统就是借助Redis存储和传输实时数据用于实时推荐模块。可以按满足数据的快速读取。
MongoDB也是一种基于内存的数据库,在存储文档信息发挥出色,多用于博客等存储大量信息系统,底层用C++语言实现。是采用C++语言编写的文档型非结构化数据库。基于大数据的电商推荐系统利用MongoDB存储JSON数据格式,占用资源小,且支持单机、集群的使用。对大量的文字数据有较好的支持。
基于大数据环境中的电商数据,日志是反应用户操作最直观的途径。所以需要采集日志并且用消息队列中间件进行数据传输;大数据环境下有成熟的日志捕获组件Flume和消息队列Kafka组件。
Flume在大数据环境下多被用于日志的采集,由Source、Channel、Sink组成;通过管道的形式实现一对一,一对多,多对多端的数据传输;Flume具有可拓展性,且拓展性很强,可以单个Flume单独使用,也可以多个Flume组合使用,采集不同源头或者发送到不同物理位置、不同逻辑位置的文件中保存日志。支持多端多环境下配置捕捉传输日志数据。是专门负责日志数据收集的强大利器。本次毕业设计采用Flume将WebServer的数据采集到本地磁盘进行保存。以备Redis数据可进行快速的读取。
Kafka消息队列可以作为缓存,为系统的传输可靠性提供保障,避免端与端的消息传因各种原因出现遗漏或者丢失。Kafka能与Flumg组合使用,Flume进行数据收集,kafka在下游消费Flume采集到的数据进而将数据广播到KafkaStreaming进行实时计算。
还有一个特殊的框架——Zookeeper,这是基于大数据环境下为分布式应用提供调度的服务,也是Kafka服务的启动依赖;
Spark在网络上被称为大数据技术栈的长子;确实,在大数据环境下,Spark的地位是举足轻重的,Spark是通用的数据处理引擎;适用于多种离线、在线场
景大型数据集的交互式查询Spark于2009年开始在加利福尼亚大学伯克利分校的AMPLab项目中生活。更具体地说,它是由于需要证明Meso的概念而诞生的,这也是在AMPLab中创建的;2014年被加州大学开源捐赠给Apache基金会,随后其火热程度就如它的名字一样以星星之火迅速燎原不到一年就成为Apache的顶级项目Spark技术栈包括可用于可以实现高吞吐量的,具备容错机制的实时流数据处理的SparkStreaming、处理结构化数据的SparkSql、机器学习实现库SparkMLib等。Spark结构图如图2.2所示。
Scala是以利于Jvm的一种面向对象加面向函数(可以进行函数式编程)的语言,是编写Spark框架的的语言。Scala的优点是面向对象,支持函数式编程,能带来更高层的并发模型。
SparkSQL专注于处理结构化数据,可以作为Sql在数据库中获取数据。还有两个用于交互式计算的DataFrame和DataSet。
基于协同过滤的推荐需要借助机器学习来完成,用Spark的机器学习实现库组件SparkMLib可以帮助我们更好的结合机器学习内容完成协同过滤算法的实现。
SparkStreaming是流式计算框架;它被用于大数据的流式处理实时计算。推荐系统的实时需求的实现就要用到SparkString处理消息队列Kafka中的数据,进行数据的快速处理和计算。
协同过滤算法是比较著名的商推荐算法,国内外研究者颇为喜爱,它诞生较早,通过对使用者历史动作的数据挖掘进而分析用户的偏好,基于不同的偏好对适用人群进行区分。可以从多个角度进行协同过滤推荐:基于用户、基于商品、基于隐语义模型。
LFM(laterfactormodel)是一种基于模型的矩阵分解的召回算法,输入UI点展矩阵,输出是P和Q两个矩阵。本项目中是将评分矩阵拆解为用户特征矩阵和商品评分矩阵。
建模公式如式2.3所示:
实时推荐满足的是更快地更新要求,准确性的标准可以略微降低。但是实时算法不能太过复杂,每次读取的数据也不能大量。因为在实时算法面前短的时延才是标准。
推荐系统面对的主要问题就是如何从海量数据中挑选出用户的兴趣爱好且还要满足低时延性能要求(例如NetFlix的指标是250ms返回,今日头条指标是200ms返回结果)。当今推荐系统往往存在三个步骤:召回,排序,调整[4]。
排序环节一般利用机器学习算法:逻辑回归或者二分类算法等得到的结果降序排序就会得出用户的喜好列表,此时的数据量降为千或百。完成了精细的个性化功能。
推荐中的常见的召回路径有以下几类:
I2I、U2I、U2I2I、U2U2I、U2tag2I,I代表物品Item,2谐音为to,相当于图中的边,U代表用户,如图2.4所示。
3.U2I2I:可以看做U2I+I2I的方法结合。根据用户的喜好找到喜爱的商品,在找到与这个商品相似的另一个物品。这个新找到的物品推荐给用户。
4.U2U2I:看做U2U+U2I的方法结合,U2U可以通过行为找到,也可以根据标签找到。把第二个用户的喜爱物品推荐给第一个用户。中间的桥梁通过U2U实现。
5.U2tag2I:这个是把U2I2I更泛化的一种召回路径,tag表示的就是用户喜好的商品的标签,通过标签的相似度查找标签相似的物品,将结果推荐给用户。
在大数据环境中,Linux是具有先天优势的;开源,拥有众多的发行版,是广大程序员的首选;但是随着大数据技术栈的发展,时至今日,Apache各大主流框架组件已经支持Windows环境;例如Kafka,Zookeeper等;以kafka为例,可以发现,后续大数据组件版本的根目录结构中多出了/Windows,其文件目录中的执行脚本也从.sh换成了在Win环境中的执行脚本.bat文件。所以,本次项大
数据环境决定尝试部署在Windows环境下,同时这也是现阶段对该类的现阶段研究的一个变化。
本毕业设计实现的推荐系统要明确电商中推荐算法的运用以及推荐系统的完整开发与上线部署,对用户的需求进行分析,需求合理可执行,方可对系统进行开发。
该系统在当前环境下技术可实现,推荐系统采用B/S架构,B/S架构又称浏览器/服务器架构,他的优点是容易维护,只需要浏览器就可以发起请求操作。不需要繁杂的安装系统等,适合本次推荐系统的开发选型。前后端分离技术,部署上线并不困难,即使未来有需求改为C/S结构,那也只需要构建C端的界面代码及配置项,无需较大改动。将推荐系统开发完毕可以利用Tomcat将打包的war文件部署到服务器实现网络访问。
接下来介绍本系统的各部分需求。
(4)用户退出:在用户浏览尚品后要可以做到安全退出,防止其他非法人员盗用信息。
(5)推荐页面的展示:系统要把每个用户的推荐列表在页面上进行展示
通过程序运算将推荐列表进行可视化展示。
(6)埋点数据采集:系统前端要能捕捉到用户打分的行为传到后端,后端要将埋点日志进行捕捉并本地保存。
(8)埋点日志的处理:系统后端将前端穿过来的日志进行格式处理,识别日志文件中的用信息。并将其中有用的数据截取出来,传到相应的推荐模块计算推荐结果或者推荐列表。
(9)统计推荐:推荐系统要能准确推荐出后台统计出的物品评分历史,准确找到评分最多的物品列表。
(10)基于物品标签的推荐:推荐系统要能根据物品的标签内容,推荐出标签相似度最高的其它物品。
(11)实时推荐:推荐系统要将用户的实时打分数据进行处理,系统要快速处理给出响应并更新推荐列表,实时的反馈给用户。
(12)基于模型的协同过滤推荐:系统要实现基于模型的协同过滤,实现个性化推荐。
整个推荐系统的用例图如图3.1所示。
(1)数据存储部分:业务数据库要满足频繁的增删查改的需求,而且数据多为非结构化数据,缓存数据库需要满足高效,实时计算的要求。
(3)并发量:系统要同时支持多用户同时在线,满足并发处理多用户的推荐需求。
综合以上系统结构用户需求以及性能需求,毕业设计推荐系统整体结构设计如图3.2所示,离线推荐模块包括四个详细的离线推荐:分别为离线统计推荐服务、基于隐语义模型的协同过滤、基于物品的协同过滤、基于物品标签的相似度推荐;实时推荐模块的结构在图的右侧由Flume、Kafka、SparkStreaming相接组成。
这些模块的推荐结果与业务数据库MongoDB相连接;前端可视化通过Spring后台的处理从MongoDB拿到结果后展示给用户。用户的操作通过前端再传到后台,通过日志采集服务进行监控日志文件,传输到Kafka消息队列进行日志数据处理,再通过SparkStreaming实时推荐服务结合业务数据库的结果把数据传输到Redis缓存数据库,供实时推荐列表的快速刷新。
推荐系统的基础数据源于学者在GitHub上开源数据集亚马逊商品集[5]。共分为两个部分:物品信息和用户评分信息。
结构如表3.4所示:
表3.4物品信息表结构
物品ID
物品名称
物品种类向量
物品图片URL
物品标签
160597
白鹿原
832,519,1
小说|文学艺术|图书音像
66003
诺基亚N1280
1128,640,304
手机|手机通讯|手机
…
商品信息共487条。
评分信息结构如表3.5所示:
表3.5评分信息表结构
用户ID
分数
452794
4.0
1264089600
452754
1.0
1351267200
452796
5.0
1381766400
系统采用微服务架构,利用Maven自动控制jar包依赖,各部分相互独立,松耦合。每个推荐模块相互独立,就模块而言互不干涉。
微服务设计理念有强调,系统中加用日志和监控能使系统变得更加健壮。还有要考虑到消息在传输过程的准确性,避免网络拥塞,消息缓存队列是必要的也是必须的。系统的各组件,都已经比较成熟,开源社区为系统的可靠持续运行提供强大的后盾支持。
本系统目前部署在单节点伪分布式下,遇到问题可以根据日志快速定位并回滚。当前只存在单机部署,维护方便快捷。
前端展示运用AngularJS编写,完成对数据可视化视图的构建,利用webpack打包并将前端项目一同放入后端项目文件,将请求与操作进行绑定,定义路由,请求方法等,规定渲染流程。
前端模块具体包括:
1.home:推荐系统首页,将推荐线结果进行展示。
3.register:用户注册页面,完成注册模块的构建。
4.tags:定义tags标签,这个标签要js实现商品的标签
5.star:定义打分,需要实现鼠标滑动打分的效果以及绑定打分的数据与操做
6.mdetail:商品详细信息页,定义商品的可视化结构,要包括标签、评分、详细信息等信息。
主要采用Java写明Pojo实体类,controller控制层,service业务层;接收前端传来的数据,根据对应的请求进行restful操作匹配作出对应的处理。
后端的请求处理主要包括:
2./rest/user/register:用户注册请求
3./rest/user/forget:用户忘记密码请求
4./rest/product/most:获取基于模型的推荐列表
5./rest/product/reating:获取商品的评分
6./rest/itemcf/{pid}:获取根据物品协同过滤的推荐列表
7./rest/content/{pid}:获取基于标签的推荐列表
8./rest/detials:商品详情页请求
9./rest/search:商品模糊查询请求
主要采用Scala开发编写Spark程序,根据推荐方式方法的不同,分成多个对应模块,离线推荐、实时推荐;离线推荐包括基于统计的离线推荐,基于隐语义模型的协同过滤离线推荐、各个模块相互独立,松耦合。
推荐模块具体包括:
1.统计推荐模块
2.基于隐语义模型的协同过滤推荐模块
3.基于物品的协同过滤推荐模块
4.基于物品标签的推荐模块
5.实时推荐模块
主业务数据存放在非关系型数据库MongoDB。
具体数据表如4.1—4.10所示:
1.Rating表结构如表4.1所示
表4.1Rating表结构
字段名称
类型
字段含义
uid
Int
用户id
pid
物品id
score
timestamp
Double
评分
2.Product表结构如表4.2所示
表4.2Product表结构
pname
String
imageUri
categoraies
tags
图片保存链接
分类
商品标签
3.User表结构如表4.3所示
表4.3User表结构
username
用户名
password
4.AvgRating表结构如表4.4所示
表4.4AvgRating表结构
avgrateing
物品平均得分
5.BaseOnContentProArr表结构如表4.5所示
表4.5BaseOnContentProArr表结构
list
Seq[Recommendation]
基于内容的推荐列表
6.ItemCFProArr表结构如表4.6所示
表4.6ItemCFProArr表结构
Seq[Object]
基于物品协同过滤的推荐列表
7.ProductList表结构如表4.7所示
表4.7ProductList表结构
Seq[Seq[Object]]
商品的推荐列表
8.RateXProduct表结构如表4.8所示
表4.8RateXProduct表结构
num
商品被评价总数
9.UserList表结构如表4.9所示
表4.9UserList表结构
用户推荐列表
10.StreamRecs表结构如表4.10所示
表4.10StreamRecs表结构
实时推荐列表
缓存数据库的存在为实时推荐获取商品列表提供了快速支持,Redis中保存了已经注册的用户推荐列表;格式如下:
2)"userId:1985105"
8)"userId:4867"
数据流向图如图4.11所示:
离线推荐用数据库商品的直接属性进行计算,例如商品标签,商品名称,商品评分等,计算结果作为前端可视化数据的支撑。
如果按照分类划分,仅使用SQL进行的统计推荐和利用机器算法的协同过滤推荐都属于离线推荐。
根据数据库中已经存在的所有商品评分信息,使用sql统计出被评分最多的商品。这个统计仅仅是做出热度比较高的商品,不对评分的高低做判断。实现sql语句如4.12所示:
在数据库中找到每个商品获得的所有评分,求平均值,根据平均值构建推荐信息。实现sql语句如4.14所示:
统计商品的平均分仅需要根据商品ID聚合,使用系统函数(图中的AVG函数)计算商品ID对应的平均法再降序排序,将SQL代码注入到SparkSession.sql()函数中实现
前边有说到,离线统计是把所用有用户的评分结果进行计算法处理,每个人都会看到看到相同的推荐列表。然而,个性化离线推荐就要体现出用户和用户之间的不同。每个人的看到的离线列表都是根据自己的评分喜好计算而出,不同用户的喜好不同,对商品的评分不同,那么他所看到的列表热度结果也就不同。协同过滤不可以直接用商品直接属性,需要利用统计离线推荐结果生成矩阵。我们要用ALS训练LFM(隐语义模型[9][7])。
ALS算法交替最小二乘法的原理为矩阵分解技术,矩阵分解就是把一个矩阵分解成两个或者多个矩阵的乘积,意义层面的解释就是通过隐含特征(latentfactor)将用户的兴趣与item联系起来。主要思想如图4.15所示。
目标函数公式如式4.16所示:
优化目标函数公式如式4.17所示:
在原始的评分矩阵中,不可能保证每个用户对每个物品都有过评价评分。用户和物品之间还是没有联系的,得到的矩阵是稀疏的缺少特征的。矩阵分解的优点可以将高维的矩阵映射成两个低维矩阵的乘积,能解决数据的稀疏问题,自定义隐特征数量,预测的精度高,高于基于统计的协同过滤和基于内容的推荐。矩阵分解也有一定的缺点,第一个缺点。在隐语义模型中,你无法解释这些个隐因子的具体含义;就不能将隐空间的维度与现实中的概念一一对应。第二个缺点就是模型训练比较费时,模型的训练需要迭代式进行,数据量大的术后天粒度的话只能是按天粒度进行训练。
使用ALS算法可进行显式模型训练与隐式模型训练,进行训练模型时需要传入四个参数。若进行显式训练,则使用ALS.train(ratings,rank,iterations=5,lambda_=0.01);如果要进行隐式训练,则参数为ALS.trainImplict(ratings,rank,iterations=5,lambda_=0.01)。上式中,参数ratings指训练模型数据源,rank指的是当进行矩阵分解时,将原矩阵分解成X(m*rank)矩阵和Y(rank*n)矩阵,Iterations指ALS算法的迭代次数,lambda为正则化项系数,默认为0.01。
ALS训练隐语义模型的过程中公式中的三个参数仅仅凭借经验或者查阅资料固定填写。虽然可能出较好的结果,但是这样的参数集并不一定是针对我们研究的问题的最优解。所以有必要采取模型优化的步骤对模型进行优化。可以计算方根误差来评判模型的优劣。公式如式4.18所示:
通过RMSE计算[8],可以反复调整参数的取值范围,最后保留值最小的一组参数作为模型的参数最优解。
程序代码实现如图4.19所示:
图4.19RMSE优化参数代码
只有计算出来模型才能通过模型构建商品列表进行推荐。构建推荐列表的主要思路步骤如下:
1.得到用户和商品的二元组(用户ID,商品ID),完成这个操作只需将用户表中的Id和商品表的Id做笛卡尔积。
2.用ALS训练出来的模型给二元组预计算评分。
3.将最终的记过排序后保存到数据库。
最终结果形式如图4.20所示:
矩阵R表示用户对物品的兴趣度,矩阵P表示用户对物品的偏好度,Q表示物品属于哪个类别的概率如图4.21所示。隐语义模型及时通过将矩阵R分解成P和Q的乘积,通过P矩阵物品类别将用户User与物品Item联系起来。
协同过滤推荐针对的对象不同可以分成两种:基于用户的协同过滤和基于物品的协同过滤;由于此时用户群体非常少,基于用户的协同过滤[7][8]不够明显,所以暂且不讨论基于用户的协同过滤,下里面来讲述基于物品的协同过滤[9][10][11]。
基于物品标签的推荐[15][16]需要利用物品的初始标签,对标签进行分类从而进行同类推荐,这个部分会把商品中属于同一类的物品进行筛选展示。实现思路为在Spark单例中实例化分词器,定义HashTF工具把文字信息处理成向量信息,运用TF_IDF进行特征矩阵的获取。
初步计算备选商品的推荐优先级公式4.23的如下:
公式的意义如下:基础评分项*评分(权重系数)从而调整推荐力度+,除以sim_sum做平均,结果就是推荐优先级得基础分数;后边的偏移量一个是鼓励项,一个是惩罚项;鼓励项:最近的评分都是高分,看了买了还给了高分,说明最近的行为很能代表自己的喜好;如果最近将某个商品拉黑删除等,说明用户不喜欢这个商品。这个商品的类别就不能代表用户的喜好。
以下环境作为本次毕业设计系统部署的开发环境参考:
操作系统如图5.1所示:
1.安装MongoDB:到MongoDB官网下载社区免费版MongoDBmsi安装程序,
将下载到本地的msi安装程序运行,按照个人需求安装在目录,以下简称为:%MONGODB_PATH%。
2.创建数据与日志文件夹:在%MONGODB_PATH%中找到data文件夹在内部创建db和logs文件夹以存放数据和日志信息。
3.配置环境变量:在系统环境变量中加入%MONGODB_PATH%
4.启动mongodb服务:输入指令mongod--dbpath%MONGODB_PATH%\data\db;
1.安装Redis:到Redis官方github仓库下载现阶段稳定版本的msi。将下载的msi文件安装运行,按照个人习惯安装在指定目录,以下简称%REDIS_PATH%。
2.将%REDIS_PATH%添加到系统的环境变量中。
3.启动Redsi临时服务:输入指令redis-server.exeredis.windows.conf
4.创建Redis连接:输入指令redis-cli。进入redis说明redis环境已经配置完成
1.解压Zookeeper压缩包:到官网下载Zookeeper安装包,根据个人习惯解压文件到指定路径,以下简称%ZK_PATH%,将%ZK_PATH%添加到系统环境变量中
2.复制%ZK_PATH%\conf\zoo_sample.cfg文件,重命名为zoo.cfg;修改文件内容,将dataDir和dataLogData的路径修改为自定义路径。
3.运行zkServer.cmd可执行脚本,运行zkCli.cmd脚本。提示连接到2181端口和出现“WelcometoZookeeper!”字样便证明环境配置成功。
1.官网下载Kafka安装包,并根据自己的习惯解压到自定义路径,以下简称%KAFKA_PATH%,将%KAFKA_PATH%加入到系统环境变量中。
2.进入%KAFKA_PATH%\conf目录编辑文件server.properties,将log.dir修改为自定义路径,建议为%KAFKA_PATH%\kafka-logs;编辑zookeeper.connect=localhost:2181
3.创建topic测试kafka安装成功:在%KAFKA_PATH%下运行指令
.\bin\windows\kafka-topics.bat--create--zookeeperlocalhost:2181--replication-factor1--partitions1--topictast;
4.运行指令查看主题
.\bin\windows\kafka-topics.bat--list--zookeeperlocalhost:2181;
如果显示列表中存在一个tast主题说明kafka环境配置成功。
Flume安装包下载:到Apache官网下载Flume安装包,根据自己的习惯解压到指定路径%FLUME_PATH%,将%FLUME_PATH%添加到系统环境变量中。
Scala安装包下载:官网下载Scala安装包;根据自己习惯将安装包安装在指定路径,以下简称%SCALA_PATH%,注意此路径中不能包含空格。将%SCALA_PATH%添加到系统变量中。安装完毕在cmd命令行输入scala显示版本信息即为正确配置环境。
官网选择合适的JDK版本,建议选择稳定且普及率高德JDK8;根据个人习惯将压缩包解压至指定路径,以下简称%JAVA_HOME%;将%JAVA_HOME%添加到系统环境变量中。输入命令java-version有版本信息输出说明环境配置成功。
Maven官网下载安装包,根据个人习惯,将安装包安装到指定目录,以下简称%MVN_HOME%,将%MVN_HOME%添加到系统环境变量。cmd输入指令mvn-v查看Maven版本号,有版本号正确输出便说明环境正确安装成功。
下载Spark安装包,根据个人习惯将安装包解压安装在指定目录,以下简称为%SPARK_HOME%,将%SPARK_HOME%添加在系统的环境变量在cmd中输入spark-shell,显示有正确版本号输出,那就说明环境正确安装。(Spark环境是依赖于JDK8以上版本+Scala环境,安装配置Spark环境时确保JDK与Scala环境已经正确安装)hadoop报错提示在单机环境下运行时可以忽略。也可以自行安装Hadoop环境搭建高可用集群。
用户注册界面如图5.3所示,若注册时改用户名被抢先注册,那么系统会提示注册失败,请更换用户名注册。
基于模型的协同过滤需要用到用户的历史数据进行计算,用户打分的行为数据,定义新的样例类,将数据加载到定义的RDD中,提取所有用户的商品打分数据,将数据转换成mllib规定的规范格式进行隐语义模型的训练,规范中要具体三个参数:隐特征个数、迭代次数、正则化系数。RDD调用cartesian函数得到笛卡尔积;此时就拥有了一个稀疏的评分预测矩阵;接下来对矩阵进行分解,将稀疏额矩阵变为稠密矩阵。将数据集切分,运用Mllib中ALS.train训练模型,getRMSE得到最优模型参数。得到了模型就可以将矩阵最优分解,再做笛卡尔积;就能得到商品两两的相似度;此时还要过滤掉自乘的结果,因为自乘的结果相似度为1。计算出物品的相似度矩阵。挑选出相似度最高的物品。组成基于模型的协同过滤推荐列表如图5.5所示。
基于物品的协同过滤用到了第二章介绍的U2I2I召回路径:分为两步:U2I和I2I;U2I根据用户找到喜爱的物品;I2I根据物品找到相似物品;I2I这个步骤通过同现相似度完成,使用商品之间的同现相似度计算出推荐商品,具体实现步骤为:加载数据到spark,按照pid做groupby对评分进行统计,新加一列sum存放评分个数。此时数据应为pid|num;再将评分按照uid两两匹配,统计商品被同一个用户打过分数的次数,此时的结果中油两个pid;将这两个pid做groupby;统计出uid的个数;那么就算出了对两个商品同时评分的个数。将这个序列倒序输出,就得到了基于物品U2I2I的协同过推荐列表如图5.6所示。
当我们对一个商品进行打分操作时,评分的数据会在控制台看到,并且以埋点日志的方式存到本地文件;Flume检测到本地文件变化,就会将日志预处理传送给Kafka消息队列,KafKa消息队列将数据传到SparkStreaming;通过计算运行将处理后的结果保存到Redis中。操作过程步骤如图5.7-5.10所示。
以上就是一个完整的物品打分数据流;此时实时推荐结果已经更新。图5.11与5.12展示了用户对商品进行评分后实时推荐的变化。
打开《这就是你给我的爱》物品详情页;可以找到下面对于这本书的标签:书、少儿图书、教育类、励志、鸡汤、好看、内容不错。基于物品标签的推荐的实现是通过Mlib中的Tokenizer将物品的标签通过“|”分词,实例化一个HashingTF工具增加一列向量表示这个物品的标签,训练idf统计向量出现的频次,把这些特征转换成和和模型协同过滤推荐一样的RDD,两两配对商品计算余弦相似度,过滤掉自己本身,得出的变标签相似列表。
我们继续查看它基于标签的的推荐列表,打开第一本书:《30年后你拿什么养活自己》如图5.13所示,查看标签如图5.14所示,发现相似度很高,标签有书、励志、鸡汤、好看这四个是和《这就是你给我的爱》重合如图5.15,5.16所示。所以可以得出结论。按照物品标签推荐也是非常准确的。
在商品首页的导航栏中,还新增了商品信息模糊搜索查询,输入查询的物品名字,即可模糊搜索到数据库中含有该名称的物品;并直接跳转到详细页面展示,如下图如图5.17所示。
搜索“白”,可以找到伊丽莎白化妆品,清除白噪声耳机;白岩松的书。这部分的具体实现直接是在Spring的控制层写了sql语句,由于不涉及到对数据评分的变化,所以没有归纳到推荐模块中,直接从Spring返回模糊查询结果。
系统使用Spring构建整体框架使开发成本变低,后续可以转为SpringBoot更轻量级的架构,能降低项目的成本投入以及维护成本,并提高系统运行效率。
系统中共多个推荐模块:实时推荐满足了系统推荐的实时性、统计推荐了反映了商品库中信息的总览,将所有用户的地对商品的评价进行总览、基于商品协同过滤实现了个性化推荐,让每个用户都要自己独特的推荐列表、基于每个模块都采用不同的推荐算法进行实现,使我们能从更多角度查看推荐的结果。
本次系统创新的部署在Windows环境下,虽然大部分组件都支持在Windows环境下运行,但是windows和Linux存在本质区别;命令的启动方式以及参数的位置都需要注意,尤其是Flume-ng启动时,不仅要调整参数位置,更重要的是启动命令中包含“-tail”指令,这个指令是在Linux的内置shell指令,在Windows中并不能被识别,这是就要在Windows本地函数文件中添加一个可执行文件,使操作系统可以识别到这个命令并且正常运行。
在Windows下启动kafka产生的offset文件在关闭kafka后并不会自动删除,如果想重启kafka,系统不会把上次的本地文件自动删除。需要手动删除,否则会启动异常。
在本次毕业设计中,也有许多不足的地方。例如样本的数据不够特别全,并不是一个完整的成熟的电商商品数据库,等待笔者自己提升技术能力后加以完善等。
迄今为止没有任何一个推荐算法能满足用户全体的兴趣爱好,也就是说推荐系统存在就必然会存在的问题:提升推荐准确度。推荐算法不可能做到符合每个人的兴趣,这正如一句话所说:“一千个人眼中就会有一千个哈姆雷特”[20]。每个人都有各自的看法和观点。做到完全符合每位用户的喜好,这是推荐系统发展的最终极目标。是推动推荐系统发展的动力源头。
Flink框架摒弃了批处理的思想,可以达到比spark更高的实时要求。由于我现在能力有限,毕业设计采取现学习资源比较成熟的spark。
我们知道在当数据量级变大时,必要的数据冗余是保证节点在遇到宕机等突发情况下恢复正常的保证。只存在一个单一节点在部署上线后,再服务器挂掉后容易发生数据的丢失。所以正式部署上线后,数据的复制是很有必要的需要将数据定时同步到其他多个节点。确保在某个机器宕机后数据不丢失。
当下的主流电商系统都在构建用户画像,通过数据建立描绘用户的标签。逐渐把用户画像运用在推荐系统中,只要用户画像画的够准,那么推荐的准度就会更高。所以接下来的研究趋势可以适当加入用户画像的构建[21],从而更加提升推荐系统的综合准确度。
供网友参考借鉴。
论文主要是理论知识的沉淀,系统实现则是对动手能力的考验!