史上最简单的推荐系统设计

jopen 8年前

推荐系统听上去是高大上的东西,在互联网多个场景中有广泛应用


场景1:你在google或百度的广告后台,输入一个关键词提交竞价,那么系统就会推荐很多认为你可能需要的关键词。

场景2:你在小游戏网站玩一款小游戏,旁边会提示你可能喜欢玩的其他小游戏。

场景3:你在电子商务网站下订单完成购物,底下有一栏推荐你购买的其他产品。

类似场景是不是很熟悉?


现在推荐系统也被定义为大数据的一种典型应用,很多公司给出高薪,不惜代价,要挖能实现推荐系统,机器学习的算法达人。


听上去很动心是不是,然而,抱歉,我教不了你出去混高薪的那些招,原因很简单,我也不会。 我的水平很low,没办法在算法上和数据挖掘技巧上指导别人,但我有很low的方法,而且在使用中,居然是管用的,如果你已经研究过多款成功的推荐系统,或者自己在以前的学习过程中掌握了非常强大的推荐算法,请忽略此文,以免耽误您的时间;但换过来,如果您是一个小公司的创业者,一个正在努力提升的基础程序员,一个公司还没有搭建推荐系统并且给出了很高的条件找不到合适人才正在发愁的老板,也许这篇文章可以帮到你。


应该是2005年的时候,我对十年前的具体时间记得不是很准确,也许是2006,反正就是那段日子里,百度当时还很弱小,公司内的系统也不复杂,很多东西做的也不是很高大上,嗯,也正是因此,我才有机会去尝试一些很low但是有用的东西。 当时想试着把商业关键词聚合起来,把关键词的关联和分类做出来,但是我完全没经验,就去请教与我配合的工程师,张怀亭(现在是跟谁学的联合创始人,CTO)。他说他以前研究生课题就是这个,然后给我看了一篇他写的论文,然后,我发现,我完全看不懂! 只好死皮赖脸的去请教,虽然算法看不懂,又听不懂,但不断追问下好歹明白了几个最基本的概念,第一,相关推荐的数据基础是共同推举数,所谓共同推举数就是,有多少人共同选择了A和B,共同推举越高,显然相关性越高。第二,如果单纯以共同推举数为推荐的依据,可能会出现一些非常不合理的结果,比如推荐关键词时,相关度未必很高的热门词会占主要位置,推荐游戏时也会出现一水的热门游戏,而不是高度关联的游戏。所以不能完全依赖于推举数。基于这些粗浅的理解,我忽略了其他不懂的部分,用简单粗暴,毫无技术含量的方式做了一套关键词的关联和推荐模型,跑出来看结果还可以,代码量,哦,一个下午。


我们以商业关键词的关联为例来说明,每个广告主会选择多个关键词,我认为这是我们的数据源,数据结构只取最简单的,广告主id,关键词。 当然,如果我们做电商,可以用消费者购买清单,如果做游戏,可以用玩家玩过的游戏清单,其思路完全一致。


第一步,数据准备

数据源 广告主的竞价记录数据表,忽略价格等其他因素,只取广告主id,关键词 两个字段。

遍历该数据,整理出两个新的结构

结构1:关键词热度表

关键词,总推举数

结构2:广告主热度表

广告主,总提交词数


第二步 关联度计算


遍历广告主表,

将该广告主的所有提交关键词拿出来,做彼此的加权累加。

(这个地方我简单解释一下,如果一个广告主提交了100个关键词,就是100*99的循环,让每两个关键词都进行关联度权值的计算,这个程序员应该都会吧)

(权值的计算,我承认我是拍脑袋的,根据实际,通过对结果的检查和反思,这里可以改,我们假设目前计算关键词A和关键词B的权值,在每个自循环最内进行权值的累加计算, 权值(A,B)=权值(A,B)+1/(B的共同推举数开方*当前广告主提交词数的开方), 也就是降低热门词的权值,以及,一个广告主如果提交了太多关键词,也降低相关权值。请注意这里还有一个权值(B,A)=权值(B,A)+(1/A的共同推举数开方*当前广告主提交词数的开方),权值(A,B)并不等于权值(B,A),这里需要特别说明一下。)


第三步,结果汇总并优化

数据结构为,关键词1,关键词2,权值。


一对关键词会出现A,B,权值(A,B)和 B,A,权值(B,A),这是有意义的。


下面说几个问题


第一,遍历循环会不会太大,比如一个广告主提交了5万个关键词,是不是要执行25亿次的循环? 对不起,一个广告主如果提交了太多关键词,我认为这些词彼此关联性并不大,如上面公式所示,所以,提交超过1000词的直接忽略掉,算都不算。这样计算量就极大降低了。 嗯,偷懒就是这么有借口。


第二,最后结果及中间数组内容会不会太大,会的! 这里我要提及一个特别重要的原则,那就是,实际我们并不需要完全保留每两个词之间的相关性,当我去看特定词的时候,系统给出推荐几十个已经足够了,所以,我其实只要保存 每个关键词的top100相关词就可以,不用所有的结果都存下来。而中间数据,我用了一个简单粗暴的方法,就是每执行一些记录,就把当前的所有关键词的top词表记录到一个临时表,然后清空内存重新统计,到最后把这些top相关词的临时表按照关键词排序再跑一遍做累加就可以了。


so,其实就是这么简单。


没有算法,没有高逼格的技术,就是最基本的循环,计算,然后写入数据表。


下面留一下思考题,都是之前我处理过的,当然,都是用比较简单粗暴的方式处理完的,有兴趣的童鞋可以想想


1、以小游戏网站为例

数据结构如下

游戏A,游戏B,相关权值


目前已知有5万款小游戏,平均每款有50条记录,也就是数据表有250万条记录。

用户中心,某玩家登陆后,检索出他历史玩过的小游戏清单,取最新的20条,基于这20条他玩过的最新小游戏,系统推荐一些其他游戏给他。

SQL 如下

select sum(权值) as 新权值, distinct(游戏B) from 数据表 where 游戏A in (检索出来的20个历史游戏列表) group by 游戏B,order by 新权值 desc limit 0,10.


(好几年没写SQL了,也没测试环境,战战兢兢,不知道写错没。)


请问,这样一条SQL,数据索引应该怎么设计,系统开销是多少,单台普通的数据库服务器大概可以支持每秒钟多少并发。 如果能正确理解数据索引,这个问题是可以估算出来的。


2,基于今天分享的内容,商业关键词的关联和推荐做好后,我希望对商业关键词做行业分类,请问下一步应该怎么做?



来自:http://mp.weixin.qq.com/s?__biz=MzI0MjA1Mjg2Ng%3D%3D