推荐系统在现代网站中经常用到,不同类型的运营需要不同的推荐策略,并且推荐策略需要简单易懂,能方便运维人员人工调整。本文以全文搜索引擎为例子讲解如何定制为一个推荐系统。
###基本原理 推荐系统的基本原理是先把相关的产品项分析出来,如
"male age18 1000 1010 1020 ..."
这里的"1000 1010 1020"是产品的ID。当有一个18岁男性用户关注了"1000 1020"这两个产品,就以条件
"male age18 1000 1020"
进行搜索,取得包括这全部条件的文本,然后把"1010"这个产品推荐给用户。
###实时推荐 有些有热度的关联产品只有几天的时间,过了后关联性就迅速减弱,这时需要实时推荐。实时推荐的原理是把每个用户当天(或者最近几天)花长时间浏览的产品记录下来,当新用户也在看相似的产品时,把前面几个看相同产品的用户的关注推荐给新用户
####代码实现 这些功能可以使用一个全文搜索引擎实现,以FTServer使用的引擎为例,当用户关注一个产品时,把产品作为文本内容,把用户作为文本ID,生成搜索索引dailyEngine.indexText(),这个索引相当于一个复合主键(产品-用户),每关注一个新产品,调用一次FavorWhenStay10Sec(),这个函数除了有包括生成搜索索引的代码indexText(),还有一个iBoxDB数据库的**insert()**操作,用于记录用户的关注
private static void FavorWhenStay10Sec(Engine dailyEngine, AutoBox autoDaily, long userId, long itemId) {
try (Box box = autoDaily.cube()) {
box.d("/Favor").insert(new Favor(userId, itemId));
dailyEngine.indexText(box, userId, Long.toString(itemId));
box.commit();
}
}
当有新用户关注了"1055 1058"两个产品时,以这两个产品为全文搜索关键字进行搜索
RealTimeRecommendPrint(engine, autoDaily, new long[]{1055, 1058});
通过dailyEngine.searchDistinct()查找方法,可以取得关注相同产品的用户(生成索引时设置的文本ID为用户ID)
for (KeyWord kw
: dailyEngine.searchDistinct(box, sb.toString(), startId, HowManyUsersAsReference)) {
long userId = kw.getID();
....
}
然后把有相同爱好用户的关注推荐给新用户
for (Favor favor : box.select(Favor.class, "from /Favor where userId == ?", userId)) {
System.out.print(favor.itemId + ",");
}
这里的HowManyUsersAsReference设置返回的用户个数,因为做实时推荐,很多时候不需要取全部相同爱好的用户。
###深度推荐 当有了大量用户关注数据后,就不需要以个别用户组织数据,可以定制各种算法分析产品的关联,也可以人工分析产品关联,然后回到第一节关于基本原理的实现,具体实现代码与直接调用全文搜索引擎一样,把多个关联产品的ID组成一个文本,然后输入全文索引,推荐时当匹配到其中的产品ID,就把文本中关联的其它产品ID作为推荐的内容。