从对推荐一无所知到做过几个推荐系统,再到完成一个推荐系统生态框架的设计,觉得是时候沉淀下来一些知识,然后继续找好吃的。《推荐系统随便谈》系列将从最简单的推荐系统说起,并随着业务需求增多和认识深入来复杂化系统设计,中间偶尔分享一些其他人的设计思路。
推荐,大家最熟悉的就是亚马逊的“看了这件商品的用户还看了”,“购买了这件商品的用户还购买了”,例子够简单易懂吧。实际上推荐可以认为是搜索的补充,搜索是用户的一种主动行为,目标十分明确,只是不知道答案,需要搜索引擎告诉我。而推荐目的在于用户不知道自己明确的需求时,告诉用户你可能喜欢某些东西。OK,有构建搜索引擎或推荐引擎经验的同学可能会发现他们的联系其实非常密切,后文再说这些复杂的地方。
回到亚马逊的例子,实际上我们可以简单地建立起一个类似亚马逊的推荐引擎,这里咱们说是《推荐系统随便谈》系列的v1.0系统把。只需要统计每个商品与其他商品的同时被购买或浏览次数,按多到少排序,就可以得到某个商品的共同购买列表(商场大妈都会啊!)。是的,咱们小白最粗暴的解决方案就是从表面上学人家这样搞。。
item_co_occurrence = {} item_co_occurrence["A"] = {} item_co_occurrence["A"]["B"] = 2 item_co_occurrence["A"]["C"] = 1 item_co_occurrence["A"]["D"] = 3 item_co_occurrence["B"] = {} item_co_occurrence["B"]["A"] = 2 item_co_occurrence["B"]["D"] = 1 item_co_occurrence["C"] = {} item_co_occurrence["C"]["A"] = 1
如果你真这样做,那么问题就来了。。。大妈神气地对经理说,我算出来的结果是,买了XXX的用户还购买的最多的商品是塑料袋!妈蛋,坑爹么这是@&#¥%.....如果简单的统计共同出现,那么很容易会被热门物品或者常见并没有作用的物品占据了你的候选推荐前几位。
稍微聪明的同学会说,我得加个预处理,把你说的热门物品或者常见且没有作用的物品,比如装东西的塑料袋给删了。看起来是正确的,但是你要怎么删才合理?
这时候搞过搜索引擎的同学站出来说,我们做文本处理时关键词提取的思想好像可以复用?“常见且没有作用的物品”其实就是“停用词”,“热门”但对整体没有贡献的物品也一样可以通过tf-idf来计算得到。是的,百度一下tf-idf,你会发现次数计算只是其中一个步骤而已。所以实际上计算两两物品相关信息时可以采用更加科学的方法,如互信息,类tf-idf,余弦距离等,当然也需要考虑自身数据是否有特殊分布。
经过预处理和多次调整计算公式,大妈信心满满的把工具给了苦逼码农,说:我跑出来效果不错,拿去用吧!但是码农实际使用时发现确实肉眼看效果还可以,但是我一个事务,或者说一个交易可能有10+个商品,我这样搞单机怎么跑那么多的东西啊!!大妈摔桌子(╯‵□′)╯︵┻━┻说:妈蛋,做个东西又要效果又要效率!!那你就搞几台破机器一起跑啊。大妈一言道出真谛,让码农想起了Hadoop神器!!把大妈的程序用Map-Reduce过程来改造,map过程枚举,sort按字母序排,reduce过程merge计数。
恩,第一版推荐系统完成!虽然效果和性能都非常锉,但是感谢大妈指导!大家期待下大妈用更好的方法来解决问题把。