基于协同过滤的酒店推荐系统

基于用户喜好的酒店推荐系统

概论:

基于用户喜好的酒店推荐系统是一种根据用户历史浏览数据猜测用户对于酒店的偏好类型,并根据用户的偏好类型给用户推荐类似酒店的系统。在本系统之中,以全国30个主要城市的部分酒店作为系统的数据集以展示所搭载的推荐算法的效果。

平台:

基于java-spring搭载的web平台。

系统各个子部分:

Html+js+css构建web服务器前段,以作为和用户交互的界面。
Java-spring构建web服务器后台,以处理前端发回的请求。
Python构建酒店数据爬虫,以作为服务器数据库的数据来源。

文档说明:

Data.py 是酒店信息爬虫,抓取酒店信息给系统初始化数据库用的.
Testweb 是java-spring 项目工程,利用IntelliJ 导入工程之后Run,然后打开浏览器输入
localhost:8080即可访问推荐系统.

推荐算法:

基于协同过滤的酒店推荐算法,系统会记录用户的历史选择(用户点击进入酒店详情页,这一动作会被系统记录下来),然后在服务器后台动态更新数据库作为计算推荐系数的重要参数。
本算法基于 用户历史数据(用户相似性)以及 酒店数据(酒店相似性)联合计算抽象距离

算法概述

假设有N家酒店,刚开启服务器时,所有的酒店都未被访问,系统没有任何先验知识,因此在主页面的推荐栏目只会出现六个处于数据库末端的酒店信息,当用户通过搜索城市:例如 南京,之后跳转至搜索结果页面,系统会动态给出位于南京的酒店包括他们的价位等缩略信息,如果用户点击“立即订阅”,可以进入到这家酒店的详情页进行更详细的了解,包括房型选择,附近交通等信息。当然此时系统就会记录下这一动作,动态更新数据库,表明用户点击了解过该酒店的具体信息,这时重新载入主页面,在推荐酒店栏目里就会更新推荐酒店信息。

算法实现 : 最终推荐系数 = 基于酒店相似性推荐 + 基于历史用户相似度推荐

酒店相似性算法概述

在系统的数据库中动态维护一个关于酒店信息的数据库,每一个酒店都会有一个特征值表征该酒店的类型,在初始阶段没有用户历史数据的时候,没有一家酒店是被访问过的,因此在推荐系统的推荐名单上各个酒店都是等价的。但是一旦有用户点击某一家酒店(可以是通过搜索然后点击酒店,也可以是在推荐列表上点击酒店 ,这些动作都会被记录下,只要用户进入酒店详情页) 当这家酒店被访问过,那这家酒店的被访问次数从初始的0更新至1,这时候在所有酒店中只有这一家酒店被访问次数不是0,那么其余酒店和这家被访问过的酒店的特征值向量差就能够计算出来(特征值越接近代表酒店越近似).

1
2
3
那么编号为K的这家酒店 和 用户偏好的酒店类型的抽象距离 就是 
∑编号J酒店的被访问次数 * (编号K酒店的特征值-编号J酒店特征值)
其中J 属于 [1,N].

这样我们就得到了每家酒店和用户偏好的酒店类型的抽象距离,很显然,抽象距离越远就说明这家酒店和用户期待的酒店就越不类似,也就越不该被推荐。

1
2
3
4
因此我们给每一家酒店计算一个推荐系数,推荐系数越高,就越应该被推荐。
于是我们构建了
编号K酒店的推荐系数 = ∑ 1 / (K 酒店到 J酒店的抽象距离)
其中J属于[1,N]

然后我们让每次主页面被加载时,先在后台计算各个酒店的推荐系数,然后根据推荐系数对于各个酒店进行排序,把推荐系数位于前6名的酒店信息动态更新在主页面的推荐栏目里面。

特征值如何理解和计算:

特征值是对于一个酒店的模型预估,也就是用一个特征值表征一个酒店的信息,这其中包括酒店所在的大区域位置(华中,华南,华东) 酒店的小区域位置(比如南京和杭州都属于华东,但地理位置还是有很大差异),酒店的价位,酒店的支持的房型,以及酒店适合的功能人群(比如居家出游,情侣出游等等).
那么如何将这些信息动态的用一个特征值去表征呢?很显然,一个用户在选择酒店时,首先会有一个区域认知,假设用户计划南京三日游,他搜索南京的酒店,你就不能给他推荐杭州的酒店,即使两家酒店同名,同价格,同类型,因为地域是第一要素,因此地域在特征值中占据比重应该最大;其次,现在用户选择了一个南京 ¥ 200/day的酒店,我给他推荐了南京 ¥500/day的酒店,这也会是无效推荐,因为用户期待价位 200 即使你推荐的酒店在南京,但是500一天,两者价格差过大,因此价格也是一个影响特征值的因素,并且权重应该仅仅低于地域,房型和酒店类型以此类推。所以到现在我们基本得出一个结论,对于酒店的特征值,各个因素的权重大小:

各因素权重排序:
                    地域 > 价格 > 房型 > 类型

我大胆的引入一种特征值计算算法:
特征值利用12bit的数据进行展示,对于地域进行分层标志:
高3位 从 000 到 111 标志着8中大地域选型: 华东 ,华中 , 华南 , 华西 , 华北等……
然后2位 从00 到11 在一样的大地域下进行小地域划分,比如华东南部,北部,东部等…..
接下来2位标志价格档次:150以下 实惠档, 150-200 经济档, 200-350 舒适档,大于350豪华档.
接下里5 位 标志 用 0 | 1 标志是否为某个类型 ,是否为情侣酒店,是否为居家酒店等等……
这样就很好的利用特征值表征了一家酒店的信息已备之后计算推荐系数使用。

注意: 这里的12bit可扩展,只是在这个demo里面12bit已经能达到不错的效果,之后可以引入其他因素去评价一家酒店,因此可能会扩展至24bit,36bit等等。

用户相似性算法概述

假设历史用户有N个,换句话说曾经有N个人访问过这个网站并留下他们的浏览酒店痕迹,现在一个新用户进入,点击查看了他感兴趣的酒店 i ,那么算法就去搜索在历史用户中有哪些用户曾经点击进入过酒店i,把这些用户都找出来,然后把这些用户访问过的除了i 酒店之外的酒店推荐系数上涨。
完成这一动作后,这个新用户又点击了第二家酒店 j,同理去历史数据中找到 曾访问过 j 酒店的用户,
恰好有那么几个用户刚好都访问过i 和 j两家酒店,那么这几个用户曾经访问过的酒店的推荐系数就会
上涨2次。以此类推,如果新用户和历史用户中的一个用户相似度为x(他们访问过的酒店有x家都是相同的,那么这个用户和新用户的相似度x 将直接导致该用户访问过的酒店推荐系数上涨x次,换句话说,历史用户信息中与当前新用户的相似程度越高(访问过的酒店重叠率越高),那这位历史用户的
历史浏览信息对于被推荐酒店名单的影响率越大,当x很大,相似度很高时,甚至可以用该历史用户的历史浏览信息直接作为新用户的推荐。

github 有文件大小限制:整个项目文件有酒店的信息,有600M,无法上传,之后我再单独将源码上传,现仅一个技术说明文档。