推荐
怎么做推荐呢?实际开发过程中,我们一边学习推荐相关的知识,一边先按直觉做了几个 demo。
在第一个版本中,用模糊查询实现。根据用户的相关信息到数据查询。大概是因为逻辑判断太多了,速度非常慢。
第二个版本,尝试优化查询语句,建立索引。
第三个版本。因为前面已经通过多元回归计算出了用户的工资区间(虽然很不准确就是了),我们拍脑袋觉得对于一份工作来说,工资是很重要的,于是直接按工资区间到数据库查询…
前两个版本,模糊查询的推荐结果还不错,至少能一眼看出与用户的信息有关。但是速度实在太慢了。
第三个版本,因为前面做的预测结果本来就不准,所以效果更差劲…而且这个思路太想当然了。
但至少现在已经有这样一个功能模块了!!于是接着尝试真正的推荐。
我理解的推荐
因为水平不到位,不能从比较宏观的角度解释,下面都只是我在这个项目中的感受。所以,推荐以「推荐 Job」为例…
我理解的推荐,就是为用户建立一个模型——「我最喜欢的 Job」。系统不断优化这个模型,试图找到用户心中最中意的那个 Job。(这只是个理想化的模型,实际的系统当中可能并不存在)然后从系统中找出与这个模型最匹配的 Job,推荐给用户。
那么问题来了,计算机怎么判断用户是不是中意某个 Job 呢?
我们看看协同过滤算法中的基于用户的推荐算法。
基于用户的推荐算法
最简单的一种,如下:
1 | 小明 喜欢 A、B、C。 |
我们发现小红的喜欢和小明的喜欢重叠度很高,小明可能也会喜欢 D,所以把 D 推荐给他。
但是这种判断的粒度太大了,再细一点可以这样:
1 | 小明 非常喜欢 A |
在计算机中,可以简化为这样的三元组 < 用户 ID, 物品 ID, 用户偏好 >
表示:
1 | 用户 JobID 偏好值(权重) |
那么这个偏好值怎么来呢?
肯定需要严格的算法…
我们可以粗略举个例子来理解,比如用户点击一次某个职位,我们假定他是被这个职位所吸引,把他与这个职位的权重相应增加。
这样在计算机内部就得到用户与 Job 的关系。
用这样的数值来量化之后,我们就可以通过做一些矩阵运算,根据用户自己的列表和别的用户的列表,把口味相似的用户关注的职位推荐给用户。
好了!暂且到这一步。
我们回过头来看,基于用户的推荐算法,需要满足两项。
- 用户(使用推荐功能的用户)的喜好
- 别的用户的喜好
这就是冷启动需要解决的问题。
它不仅需要用户自己有信息,还需要别的用户有信息…
考虑到我们做的这个小项目根本不可能有那么多用户,测试起来也麻烦,看来这个方式不合适…
基于内容的推荐算法
基于用户的推荐算法,是通过比较各个用户的喜好,把别的用户关注的东西推荐给有共同喜好的用户。
而基于内容的推荐算法,就是把用户的喜好直接与 Job (物品)比较。
还是看个最简单的:
1 | 小红 喜欢 哲学书籍 |
所以把《大问题》推荐给小红。
同样,我们可以更细粒度一点:
1 | 小红 非常喜欢 哲学书籍 |
我们优先推荐《大问题》给小红…
而在计算机内,可能是这样表示的:
1 | 用户 标签 权重 |
通过计算向量距离,得出用户和 Job 的相似度,生成推荐。
基于内容的推荐需要解决两个问题。
第一个仍然是冷启动,用户需要打上标签。我们考虑过根据用户的行为——历史记录,点击记录等来生成用户标签。
不过都没时间做…(太真实了)
其实提到这个场景,我想到的是各种信息流 app,注册时让用户选择一堆感兴趣的话题,相当于打上标签。于是我也模仿这样做了个…
我们只做到了用户和某个标签产生联系,如标签 Hadoop
, Java
…
存在数据库里 :
1 | 用户 ID 标签Id 有无 // 标志用户有没有选择某个标签。。。 |
第二个问题就是提取出 Job 的标签,并且提取权重。
这个是重点也是难点…
从抽象的角度来看,Job 其实也只是一串文本描述的一样物品。
粗略地做,我们可以进行简单的词频统计…
常用的更标准的方式是使用 TF-IDF。
比较
SQL 模糊查询是基于元数据的推荐。比如推荐书,紧紧按出版年份来推荐是不太合适的。(大多数情况下)
而协同过滤,是基于标签,更合理些(理论上)。
我们做出来的效果,感觉模糊查询似乎看起来科学点…至少能在推荐的结果找到我们的输入的信息。
通过后面的方式得到的推荐结果(因为我们技术不到位的原因)看起来有点没头没脑…