/*版权声明:可以任意转载,转载时请务必标明文章原始出处和作者信息 .*/
搜索引擎设计实用教程(4)-以百度为例
之四:相关提示功能
中科院软件所 malefactor
2005年11月
相关提示也是几乎所有搜索引擎提供的一个附加功能,所谓相关提示,就是对于用户提交的查询进行分析,然后根据其它用户相似的查询给予用户提示,比如我输入查询”大长今”,检索系统会提示其它象”大长今主题曲”,”大长今下载”等等相关的一些其它用户查询.
那么搜索引擎是根据什么原则对于其它用户的查询进行选择来提示用户相关查询呢?我们还是以百度为例子来看看怎么实现这个功能.要实现这个功能主要解决如下三个问题:
问题一.从哪里获得其它用户的查询信息?这个问题对于搜索引擎来说不是难事,因为搜索引擎都有用户查询LOG的功能,在一段时间内每一个用户提交给搜索引擎的查询都被记录在LOG文件里面,所以从这个文件里面可以获得其它用户的查询信息.这个LOG还可以用作其它功能的基本素材,比如搜索排行榜或者搜索风云榜,就是根据这个LOG文件,对用户查询归类,相同的归为一类,然后统计一段时间内这个类别的出现次数,按照降序排列,选择前列K个作为输出即可.
问题二.搜索引擎拿到用户的查询比如”大长今”,用户查询LOG里面有成千上万的不同查询,那么选择哪些作为提示呢?这里面牵涉到一个字符串相似性计算的过程.
问题三.假设已经从查询LOG里面选择了一批用户相关查询信息,按照什么顺序输出呢?为什么”大长今主题曲”排列在”大长今下载”前面呢?这里面牵涉到排序原则的问题.
我们一步步分析看看百度是如何解决上面的第二和第三个问题的.
首先,百度在计算字符串相似性的计算过程是首先对于用户查询进行分词,然后对于分词后的结果来进行相似性计算的.怎么证明这一点? 第一个证明:首先用”新闻”作为查询,看看百度提示的相关词汇是什么,然后将查询修改为”新闻新闻新闻”,再看看提示的相关词汇是什么,提示是完全一样的,基本说明是分词后进行计算的. 第二个证明: 首先用”娱乐新闻报道”作为查询,看看百度提示的相关查询是什么,然后人工分好词”娱乐 新闻 报道”,再看看提示的相关查询是什么.,提示仍然是完全一样的,我们再颠倒一下词汇顺序,用”新闻娱乐报道”作为查询,再看看相关查询是什么,完全没有变化.所以得出结论:百度在计算字符串相似性之前首先要对用户查询进行分词,当然查询LOG里面的查询也要首先进行分词.
第二步,怎么计算相似性并排序输出呢? 如果用户输入查询只有一个单词,那么处理起来好像比较简单,只要用户查询LOG里面包含这个单词的字符串都被纠出来,然后根据用户总共查询这个字符串的次数进行排序,选择前列K个作为相关提示就可以了. 好像很简单,但是问题真的这么简单就被解决了么? 并非如此.
如果用户输入的查询比较长,问题就出来了,比如我们用“清脆的鸟叫声”作为查询,百度返回的相关提示中,前列1-35个相关查询包含“鸟”和“叫声”,这几个查询排序原则是按照用户查询次数多少排列的,在36-40的相关查询仅仅包含“清脆”一个单词,排列顺序和用“清脆”查询时候顺序相同,说明也是按照用户查询次数多少排列的;41-100的相关查询仅仅包含“叫声”,第41个查询”动物的叫声”是所有100个查询用户查询次数最多的一个. 为什么包含”清脆”的查询排列在包含”叫声”的查询前面而不是反过来呢?
在给个例子,用“咆哮小老鼠”作为查询,排在最前面的是匹配了“咆哮,小,老鼠”三个词汇的相关查询,次之是匹配了“咆哮,老鼠”的相关查询,再次是匹配“咆哮,小”的相关查询,最次是匹配“小,老鼠”的相关查询,总共输出92个相关查询,对于只有一个匹配的查询没有输出。那么为什么是“咆哮,老鼠”》“咆哮,小”》“小,老鼠”呢?原则是什么呢?
多次实验后,发现里面其实有一个匹配单词的权重设置问题,拿”咆哮小老鼠”做例子,切分后是<咆哮,小,老鼠>, 假设用户查询LOG里面有两个查询,一个是”咆哮老鼠论坛”,切分后是<咆哮,老鼠,论坛>.匹配的有两个单词(咆哮,老鼠), 另一个查询是”咆哮小”,切分后是<咆哮,小>,匹配的也有两个单词(咆哮,小),怎么给这两个查询排序呢? 假设每个单词都有一个权重设置,比如 Weight(咆哮)=a Weight(小)=b Weight(老鼠)=c . 我们计算”咆哮小老鼠”和”咆哮老鼠论坛”的相似性等于重复单词权重之和,也就是等于a+c,而另外一个查询的相似性等于a+b,然后按照顺序输出就行了.所以这里面关键是如何设置单词的权重.
那么单词权重怎么衡量呢,作为搜索引擎很容易获得的一个单词权重评价因素是IDF,所谓IDF,就是说如果一个单词如果在很多文档中都出现,那么这个单词重要性就很低,比如说”的”,几乎在每个中文网页都出现,那么这个单词的IDF值就非常低.具体计算IDF的公式是
IDF(word)=log(N/DF(word)),
这里,DF(word)指的是包含单词word的文档数目个数,N指的是文档集合的总的文件个数,我们假设百度索引了6亿个网页,那么这里N=600000000.
我们用IDF来解释百度的相关查询排序因子.首先来解释“清脆的鸟叫声”这个查询的相关查询排序,我们分别用“清脆”“鸟”“叫声”来作为查询,看看有多少网页包含这些词,百度返回结果是:
清脆:找到相关网页约2,390,000篇
鸟: 找到相关网页约14,000,000篇
叫声:到相关网页约3,370,000篇
把这些数值带入上面的公式计算得出IDF权重 IDF(清脆)=2.39975335 》IDF(叫声)=2.25052135 》IDF(鸟)=1.63202321. 所以前列匹配了“鸟”和“叫声”的权重最大,都包含这两个查询按照用户查询数目多少输出,其他的按照包含”清脆”或者”叫声”的顺序输出.
对于查询“咆哮小老鼠”来说,我们看看是否成立:
百度返回结果:
咆哮:找到相关网页约2,090,000篇
小:找到相关网页约29,600,000篇
老鼠:找到相关网页约11,900,000篇
IDF(咆哮)=2.45800496
IDF(小)=1.30685954
IDF(老鼠)=1.70260429
所以权重是 咆哮>老鼠>小
我们看到前面分析输出顺序是: <咆哮,老鼠> > <咆哮,小> > <小,老鼠>
我们根据上面单词的权重可以看出:<咆哮,老鼠>=IDF(咆哮)+IDF(老鼠)=4.15
<咆哮,小>=IDF(咆哮)+IDF(小)=3.75
<小,老鼠>=IDF(小)+IDF(老鼠)=3.01
所以百度的顺序按照这个顺序输出。
再看个例子:查询“娱乐新闻报道”百度返回结果:
娱乐:找到相关网页约31,600,000篇
新闻:找到相关网页约93,500,000篇
报道:找到相关网页约17,000,000篇
IDF(娱乐)=1.27846417
IDF(新闻)= 0.80733964
IDF(报道)=1.54770233
我们可以预测:
包含《娱乐,新闻,报道》的相关查询排名最高,次之是《娱乐,报道>,再次是《新闻,报道》,可以看出百度的排序果然是如此。所以我们的推理基本上是正确的.
最后归纳一下相关查询的算法流程:
(1) 用户输入查询,分词;
(2) 计算用户查询和历史用户查询的相似性,相似性计算是通过计算两者重复单词的权重之和来计算的
(3) 每个单词的权重用单词的IDF来计算,大的排序原则根据这个权重进行排序输出,如果两个历史查询包含相同的重复词汇集合,那么查询权重相同,则按照用户查询次数有高到低排序输出。
后台作业:为了加快查询反映速度,搜索引擎不会每次用户查询都重新计算相关查询,可以在后台算好以后存储在数据库里面,用户查询的时候直接查找数据库输出,那么后台如何处理呢?
(1)对于最近一段时间(比如一个月或者一个星期)用户查询LOG进行统计分析,选择列在前列比如1千万条最频繁的用户查询,
(2)然后对于每个查询分词,按照倒排文档进行存储,比如“新闻报道 10000”,则在索引里面登录 “新闻--》新闻报道 10000” “报道-->新闻报道 10000”,其他查询都是如此处理进入索引。
(3)对于用户查询,在索引里面查找最相似的历史查询,并按照上面介绍的方法计算权重,按照权重输出;
(4)当然,为了更加加快查询速度,第三步骤的工作也可以预先算好,存储在数据库里面,用户查询直接在数据库里面存取。这个数据库可以每隔一段时间更新一次以反映最新的情况。