有个做母婴站的运营跟我聊过一件事。她写了一篇关于婴儿湿疹护理的文章,自认为很全面,症状、原因、护理方法、用药建议都覆盖了。发出去之后,排名一直卡在第三页。她去分析排第一的那篇,发现人家写的字数比她少,覆盖的面也比她窄,就集中在“保湿”这一个点上。她想不通,我写得比她全,凭什么她排前面。
问题出在她对“相关性”的理解上。她觉得覆盖的面越广,相关性越强。搜索引擎的判断标准不是这样。搜索引擎算的是:你页面里的每个词,跟查询词的匹配程度有多高,这个匹配程度有没有被过度稀释。她那篇面面俱到的文章,每个点的篇幅都不长,核心词的权重被摊薄了。人家那篇只打一个点,但那个点打得足够深,核心词的权重高度集中。在TF-IDF和BM25的算法框架里,后者的得分更高。
TF-IDF是信息检索领域最经典的权重计算方法。它的全称是词频-逆文档频率。拆开看,它算两件事。
词频,就是某个词在你这个页面里出现了多少次。出现得越多,说明这个页面越侧重这个词。但这只是一半。逆文档频率,是这个词在整个文档集合里有多稀有。一个词如果到处都出现,比如“的”“是”“在”,它的区分度就低,权重就低。一个词如果只在少数文档里出现,它的区分度就高,权重就高。
把这两个乘起来,就是TF-IDF值。它的直觉是:一个词在你这篇文档里出现得多,同时在整个语料库的其他文档里出现得少,这个词对你这篇文档的辨识度就高。你页面里高TF-IDF值的词,就是搜索引擎判断你页面主题的核心依据。
这个逻辑听起来简单,但它推翻了一个流传很久的SEO概念:关键词密度。
早年做SEO的人,会算关键词出现的次数除以总字数,得出一个密度值,然后反复调整,试图找到一个“最佳密度”。这个做法在TF-IDF的框架里是没有意义的。因为TF-IDF不看绝对密度,看相对权重。一个词出现了十次,但如果这个词在整个语料库里是高频词,它的TF-IDF值可能很低。另一个词只出现了三次,但这个词在语料库里极其稀有,它的TF-IDF值可能很高。你盯着密度调,调的是没用的指标。
关键词密度这个词之所以过时,是因为它只看了TF的一半,没看IDF。它假设所有词的区分度是一样的,这跟实际情况完全不符。你在一篇关于婴儿湿疹的文章里把“婴儿”这个词堆到很高的密度,没有用,因为“婴儿”在母婴领域是高频词,IDF值低。你真正该关注的是那些在母婴领域里稀有、但在你这篇文章里集中出现的词。比如“特应性皮炎”“皮肤屏障”“丝聚蛋白”,这些词的IDF值高,你合理使用它们,你的页面在这个主题下的辨识度就上来了。
但TF-IDF有一个缺陷,它假设词频是线性增长的。一个词出现十次,权重就是出现五次的两倍。这个假设不符合直觉。一个词出现十次和出现二十次,对页面主题的贡献差距,远没有两倍那么大。边际效应是递减的。你在一篇文章里把某个词从五次提到十次,可能有用。从十次提到二十次,效果就微乎其微了,甚至可能起反作用。
BM25就是来修这个缺陷的。
BM25的全称是Best Matching 25,它是TF-IDF的改进版。它在两个地方做了调整。第一,它给词频加了一个饱和函数。词频增加,权重也增加,但增加的速度越来越慢,最后趋于平缓。这个函数里有一个参数叫k1,控制饱和的速度。k1越大,饱和越慢。k1越小,饱和越快。这个设计的意思是:一个词出现到一定程度之后,再多出现几次,对相关性的贡献就很小了。你不需要无限堆词。
第二,它引入了文档长度的归一化。这个参数叫b,控制长度归一化的强度。b的值在0到1之间。b越大,长文档的惩罚越重。b越小,长度的影响越小。这个设计的意思是:一篇长文档里出现五次某个词,跟一篇短文档里出现五次某个词,前者的权重应该更低。因为长文档有更多的空间来容纳这个词,它的出现可能是偶然的。短文档里出现五次,说明这个词对这篇文档确实重要。
这两个调整,让BM25比TF-IDF更贴近真实的搜索场景。它不再假设词频无限线性增长,也不再忽略文档长度的影响。它的评分更稳,更不容易被堆词和长文稀释。
BM25对SEO的实战启示是什么?
第一个启示:不要堆词,但也不要怕重复。BM25的饱和函数告诉你,词频从一次到三次,权重提升明显。从三次到五次,提升变缓。从五次到十次,提升很小。你把核心词在页面里自然出现三五次,权重就到位了。再多,收益递减。你不需要为了密度去硬塞关键词,那样反而破坏可读性。
第二个启示:页面长度要控制。BM25的长度归一化告诉你,长页面里的词频权重会被稀释。你写五千字,核心词出现十次,单次出现的权重可能不如一篇两千字的文章里出现五次。这不是说长文不好,是说长文需要更高的词频来维持同样的权重。你写长文,就得确保核心词在关键位置反复出现,否则你的长文在相关性评分上会吃亏。那些什么都写的“大全型”页面,往往就是这个毛病:面面俱到,每个点都浅,核心词的权重被长度稀释了。
第三个启示:稀有词比高频词更有价值。TF-IDF的IDF部分在BM25里依然保留。一个词在语料库里越稀有,它的权重越高。你在文章里合理使用行业术语、专业词汇、长尾表达,比反复用那些通用词有效得多。一个母婴站,你写“婴儿护肤”,不如写“婴儿皮肤屏障修护”。“皮肤屏障”这个词的IDF值更高,你的页面在这个细分主题下的辨识度更强。
第四个启示:标题和开头段落的权重更高。BM25本身不区分位置,但搜索引擎在BM25的基础上加了位置权重。标题里的词、开头段落里的词、H2/H3里的词,权重比正文里的词高。因为位置本身传递了重要性信号。你在标题里放核心词,在开头段落里自然出现核心词,在H2里覆盖核心词的变体,这些动作的性价比比在正文里堆词高得多。
第五个启示:语义变体比精确匹配更安全。搜索引擎早就不只看精确匹配了。你写“婴儿湿疹”,搜索引擎知道“婴儿湿疹”和“宝宝湿疹”“婴幼儿湿疹”是同一个概念。它在计算相关性的时候,会把这些变体纳入考虑。你不需要在每个地方都写一模一样的词,自然使用变体,反而让内容更可读,同时覆盖了更多的查询表达。BM25的框架本身不处理语义,但搜索引擎在BM25之上加了语义层。你的内容如果只盯着一个精确词反复写,语义层的得分反而低。
再说一个更深层的点:BM25的参数k1和b,搜索引擎是可以调的。
不同的搜索引擎,不同的语言,不同的内容类型,k1和b的最优值不一样。k1控制词频饱和的速度,b控制长度归一化的强度。搜索引擎会根据场景调整这两个参数。比如短文本场景(标题、摘要),k1可能调小,让词频快速饱和。长文本场景(文章、文档),k1可能调大,让词频有更多的作用空间。b的值也类似,短文本的b可能调小,长文本的b可能调大。
这个可调性对SEO的启示是:你没法用一个固定的公式去优化所有页面。标题的写法、正文的写法、产品描述的写法,遵循的规律不一样。标题短,词频饱和快,你放一两次核心词就够了。正文长,词频饱和慢,你需要在关键位置多次出现核心词。你拿标题的写法去写正文,正文的权重上不去。你拿正文的写法去写标题,标题就臃肿了。
TF-IDF和BM25还有一个共同的局限:它们只算词,不算语义。
它们不知道“苹果”是一家公司还是一种水果。它们不知道“银行”是金融机构还是河岸。它们只看词的表面形式,不看词的上下文。这个局限在早期的搜索引擎里是致命的,因为用户搜“苹果”,搜索引擎可能给你一堆水果页面。现代搜索引擎用词向量、BERT、神经网络来解决这个问题。语义匹配已经取代了单纯的词匹配,成为相关性判断的核心。
但这不意味着TF-IDF和BM25过时了。它们是底座。语义模型是在这个底座上加了一层理解能力。底座不稳,上层再花哨也没用。你的页面如果连基本的词匹配都做不好,语义模型也救不了你。你连核心词都没覆盖,搜索引擎凭什么判断你跟这个查询相关?语义理解是在你已经有基础相关性的前提下,帮你加分。基础相关性都没有,加分从何谈起。
所以实操中的策略是:先把TF-IDF和BM25层面的相关性做扎实,再考虑语义层面的优化。核心词该出现的出现,该在标题出现的在标题出现,该在H2出现的在H2出现。稀有词该用的用,不要只堆通用词。页面长度控制好,不要让核心词的权重被稀释。这些基础工作做完,再去考虑语义变体、上下文理解、意图匹配。顺序不能反。
最后回到那个母婴站的例子。她那篇面面俱到的文章,问题不在于内容不好,在于相关性信号被稀释了。她后来改了一版,把文章拆成三篇,每篇聚焦一个细分点,核心词在标题、开头、H2里集中出现,正文里自然使用行业术语。三篇的排名都上来了,总流量比原来那一篇高了好几倍。
这个案例说明的东西很朴素:搜索引擎算相关性,算的是信号强度。你信号分散,强度就弱。你信号集中,强度就强。TF-IDF和BM25是量化信号强度的工具。你理解这两个工具在算什么,你就知道该把力气花在哪。你不知道它们在算什么,你就在关键词密度这种过时指标上打转,怎么调都调不对。