老周在城西开了一家叫“百味轩”的小馆子。他手艺好,招牌红烧肉一绝,可最近客人们来得越来越少。老周想不通:我做的菜这么好吃,为什么留不住人?直到一位老熟客点破了他——“您天天就给我上红烧肉,再好吃也腻了,我想吃点别的。”老周这才明白:一桌好菜,不能只有一道最合口的招牌,还得有荤有素、有冷有热、有主菜有惊喜,否则再好的手艺也会把人吃跑。 这个道理放到推荐系统上,就是“推荐多样性”问题。一个只会猜测用户最想点什么、然后就拼命推什么的系统,很快会把用户困在越来越窄的“信息茧房”里。本篇文章我们跟着老周一起,把“一桌好菜”的点菜哲学,拆解成推荐系统里可度量的指标、可实现的重排算法、可落地的工程方案与可验证的评估体系。

岗位关联

对 AI 从业者而言,掌握推荐多样性是通往高价值的“重排与策略优化”方向的关键技能,也是区分初级“调参工程师”与高级“推荐架构师”的一道分水岭。学会它,你才能做出让用户“吃得好也吃不腻”的产品。

目录
  1. 可视化演示
  2. 多样性概述
  3. 度量指标
  4. 核心算法
  5. 影响因素
  6. 优化策略
  7. 评估体系
  8. 工程案例
  9. 挑战展望
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

以星座网络呈现推荐项目按品类分布的多样性,随着推荐列表扩展,项目覆盖更多品类,多样性指数与覆盖率同步提升,直观展示多样性优化效果。

本节配有交互动效(进入视口后自动加载,约 3KB)。

多样推荐 品类1 品类2 品类3 Diversity 覆盖更多

多样性概述

老周被客人点醒后,开始琢磨“一桌菜”的哲学。他发现,真正让人念念不忘的宴席,从来不是十道红烧肉,而是有一道最贴心的主菜,配上几道层次分明的配菜,最后再来一道意想不到的甜品。好吃(相关性)是留住客人的底线,但丰富(多样性)才是让客人回味的原因。

推荐系统也是一样。如果只优化“用户最可能点击什么”,系统会像一个只做红烧肉的厨师,把用户喂到腻为止。学术界把这个问题概括为“相关性”与“多样性”的矛盾:相关性回答“这是不是用户想要的”,多样性回答“这一屏内容是否让用户有选择感、有新鲜感”。两者看似冲突,其实是互补关系——相关性保证基础体验,多样性保证长期吸引力。

从技术上看,最常见的处理方式是把两者加权融合成一个综合得分,再按得分排序:

老周在菜单上写下八个字:“投你所好,添点新意”,这就是推荐多样性最朴素也最核心的表述。理解了这个矛盾,后面的指标、算法和工程方案,都只是把这句话翻译成代码。

Score(i)=α⋅Rel(i)+(1−α)⋅Div(i)\text{Score}(i) = \alpha \cdot \text{Rel}(i) + (1 - \alpha) \cdot \text{Div}(i)
这个公式就像一个点菜清单:相关性是“这道菜合不合口味”,多样性是“这道菜和桌上已有的菜重不重复”,最后用一个权重 α 决定你更在意哪一个。
  1. 相关性得分$\text{Rel}(i)$ 表示物品 $i$ 对当前用户的匹配程度,通常来自 CTR 预估或向量相似度。
    Rel(i)\text{Rel}(i)
  2. 多样性贡献$\text{Div}(i)$ 表示把物品 $i$ 加进列表后,整体列表增加的“新鲜感”,比如它是否与已选物品足够不同。
    Div(i)\text{Div}(i)
  3. 权衡权重$\alpha$ 在 0 到 1 之间取值,越接近 1 越看重相关性,越接近 0 越看重多样性。
    α∈[0,1]\alpha \in [0, 1]

度量指标

老周想验证自己的菜单改革有没有效果,他得先回答一个问题:怎么量化“这桌菜够不够丰富”?数食材种类?数烹饪手法?还是看客人点没点以前没尝过的菜?没有度量,就没有改进。

推荐系统同样需要一把尺子。工程上把多样性分为两个层面:一是“单次推荐列表内部”的多样性,叫列表内多样性,衡量用户一屏看到的内容之间有多大差异——菜都长得差不多,就是同质化的信号;二是“整个系统层面”的多样性,叫覆盖率,衡量系统总共能触达多少不同物品——如果一个平台上只有头部爆款被推荐,纵使每次列表内部有点变化,整体依然贫瘠。

最常用的列表内多样性指标是 ILAD(列表内平均距离),它把推荐列表中所有物品两两配对,求它们的平均“不相似度”:

老周的账本上有了“每桌菜品差异分”,推荐工程师的报表里有了 ILAD 和覆盖率。有了数字,才知道哪桌菜、哪个策略环节出了问题。度量是一切优化的起点。

ILAD=2n(n−1)∑i=1n∑j=1i−1(1−S(di,dj))\text{ILAD} = \dfrac{2}{n(n-1)} \sum_{i=1}^{n} \sum_{j=1}^{i-1} \left( 1 - S(d_i, d_j) \right)
ILAD 就像老周数一桌菜里“任意两道菜的重合度”:两道菜越像,距离越小;一整桌菜风格越是千篇一律,ILAD 就越低。
  1. 配对数$n$ 是列表长度,$n(n-1)/2$ 是任取两道菜的组合数,前面的 $2/[n(n-1)]$ 就是这个组合数的倒数,用作求平均。
    2n(n−1)\dfrac{2}{n(n-1)}
  2. 物品相似度$S(d_i, d_j)$ 是物品 $i$ 与物品 $j$ 的相似度,可以由类目、标签或向量内积计算。
    S(di,dj)S(d_i, d_j)
  3. 距离转换$1 - S(d_i, d_j)$ 把相似度翻转为“距离”,越相似距离越小,越不同距离越大。
    1−S(di,dj)1 - S(d_i, d_j)
  4. 双重求和$\sum_{i=1}^{n} \sum_{j=1}^{i-1}$ 遍历所有 $i > j$ 的物品对,确保每对只算一次。
    ∑i=1n∑j=1i−1\sum_{i=1}^{n} \sum_{j=1}^{i-1}

核心算法

老周给店里立了一条规矩:给客人加菜时,先选一道最合口的主菜,之后每加一道,都要在心里问一遍——“这道菜和桌上已有的菜重不重?”如果已有红烧肉,再上一碗红烧肉就败兴;换成清蒸鲈鱼,反而衬得满桌生辉。这条“加菜规矩”,在推荐系统里叫 MMR(最大边际相关)。

MMR 的核心思想是贪心:每次从候选物品中挑一个“既相关、又与已选集合最不相似”的物品加入推荐列表,直到凑满一桌。它的选择标准写成公式是:

除了贪心的 MMR,还有更全局的 DPP(行列式点过程),它一次性从候选集里选出一个子集,让子集内部的相关性和差异性达到整体最优,类似老周不只盯着加一道菜,而是通盘设计整桌菜。在工程里,这类算法通常放在“重排”阶段,对精排结果做最后一道把关。那条“加菜规矩”被写成了可执行的数学公式,从此后厨不再凭感觉做菜。

MMR=arg⁡max⁡di∈R∖S[λ⋅Sim1(di,q)−(1−λ)⋅max⁡dj∈SSim2(di,dj)]\text{MMR} = \arg\max_{d_i \in R \setminus S} \left[ \lambda \cdot \text{Sim}_1(d_i, q) - (1 - \lambda) \cdot \max_{d_j \in S} \text{Sim}_2(d_i, d_j) \right]
这个公式就是老周心里的那杆秤:左边是“这道菜合不合客人口味”,右边是“这道菜跟桌上已上的菜撞不撞车”,λ 决定客人更看重哪一头。
  1. 候选剩余集合$R \setminus S$ 表示从候选池 $R$ 中,去掉已经被选进列表的集合 $S$,剩下的才是待选项。
    di∈R∖Sd_i \in R \setminus S
  2. 选取最优$\arg\max$ 表示在剩余候选中,挑出使括号内得分最高的那个物品 $d_i$。
    arg⁡max⁡di∈R∖S\arg\max_{d_i \in R \setminus S}
  3. 相关项$\lambda \cdot \text{Sim}_1(d_i, q)$ 是物品与用户需求 $q$ 的相似度,乘上权重 $\lambda$,越大说明越对口。
    λ⋅Sim1(di,q)\lambda \cdot \text{Sim}_1(d_i, q)
  4. 冗余惩罚$\max_{d_j \in S} \text{Sim}_2(d_i, d_j)$ 取该物品与已选集合中相似度的最大值——“最撞车的一次”。
    max⁡dj∈SSim2(di,dj)\max_{d_j \in S} \text{Sim}_2(d_i, d_j)
  5. 权衡系数$\lambda$ 控制相关项与惩罚项的比例,$\lambda=1$ 时退化为纯相关性排序,$\lambda$ 越小越强调多样。
    λ∈[0,1]\lambda \in [0, 1]

影响因素

老周的菜单改革推行了一个月,效果却不理想。他仔细一查,发现问题出在后厨的备菜清单上:新来的小工每天只按照头一天销量最高的十道菜备货,客人想吃的创新菜根本没食材。源头被卡住了,前面怎么改菜单都没用。

推荐系统存在同样的“源头收窄”。首当其冲的是召回阶段的“热门偏差”:召回通常以点击率、销量等指标为信号,头部热门物品被反复捞起,长尾物品根本进不了候选池。接着是排序阶段的“CTR 偏见”:精排模型以点击概率为目标,同类爆款的得分天然相近,模型本身就对“相似”没有惩罚。再加上用户点击数据本身存在马太效应——越被推荐的越有人点,越有人点的越被推荐——整个系统像一台不断自我收窄的漏斗。

可以用信息熵来衡量候选集合的多样性萎缩程度。熵越高代表类别越均衡,越低代表越集中:

老周意识到,要改变“越推越窄”的恶性循环,不能只在菜单上做文章,得从备菜源头抓起。对推荐系统而言,这意味着要逐一检查召回、排序、数据三个环节:召回是否给长尾留了入口?排序是否惩罚了冗余?用户画像是否只用了一个片面的标签?源头的熵补回来,多样性才能活起来。

H(C)=−∑c∈Cp(c)log⁡p(c)H(C) = - \sum_{c \in C} p(c) \log p(c)
这道公式像老周统计“今天的备菜里肉、菜、鱼、汤各占多少比例”:如果九成都是肉,熵就很低,宴席注定油腻单调。
  1. 类别概率$p(c)$ 表示候选集中属于类别 $c$ 的物品所占比例。
    p(c)p(c)
  2. 对数项$\log p(c)$ 对概率取对数,概率越小负得越多,最终对熵的贡献越大。
    log⁡p(c)\log p(c)
  3. 累加取负对所有类别求和再取负号,结果落在一个正数区间,越低说明越集中单一。
    −∑c∈Cp(c)log⁡p(c)- \sum_{c \in C} p(c) \log p(c)

优化策略

找到病根后,老周动了一场大手术。他在菜单上开辟了三个区:经典必点区(利用已知偏好)、每周新菜区(探索未知口味)、季节限量区(制造惊喜稀缺感)。每桌还定下规矩:荤素搭配、不可重复主料。这套组合拳,对应推荐系统里的几大优化策略。

第一是类目配额。像每桌必须荤素搭配一样,给每个类目设一个推荐上限:再好吃的菜品,一类最多占两个推荐位,保证列表覆盖多个类目。第二是长尾挖掘:通过降低热门物品的曝光比例、给新品和冷门好物加权,把推荐池的尾巴做厚——对应老周每周推新菜。第三是探索机制:用一个随机概率让系统偶尔跳出“最相关”的舒适区,扔几个冒险选项给用户,看看反应。

长尾挖掘的效果用覆盖率来度量——系统最终能推荐出去多少种不同的物品,公式是:

老周的“三区菜单”让店里的翻台率和回头客都涨了。推荐系统也是如此:类目配额保证基础多样,长尾挖掘拓宽整体覆盖,探索机制给用户选择权,动态权重则根据用户状态随时微调——新客多一点探索,老客多一点贴心。多样性的优化从来不是单点改动,而是一套组合策略。

COV=∣⋃u∈UD(u)∣∣D∣\text{COV} = \dfrac{\left| \bigcup_{u \in U} D(u) \right|}{|D|}
覆盖率像老周统计“全月菜单里真正上过桌的菜,占整个菜品库的几分之几”。只卖爆款,覆盖率就低;勇于把新菜端上桌,覆盖率才涨得起来。
  1. 推荐集合$D(u)$ 是给用户 $u$ 生成的推荐列表中包含的物品集合。
    D(u)D(u)
  2. 并集运算$\bigcup_{u \in U} D(u)$ 把所有用户推荐过的物品取并集,去重后统计总共有多少不同的物品被推了出去。
    ⋃u∈UD(u)\bigcup_{u \in U} D(u)
  3. 候选仓库$|D|$ 表示平台上全部候选物品的总数。
    ∣D∣|D|
  4. 比例含义分子分母相除得到的比值越接近 1,说明系统触达面越广,长尾利用越充分。
    ∣⋃u∈UD(u)∣∣D∣\dfrac{\left| \bigcup_{u \in U} D(u) \right|}{|D|}

评估体系

菜单改革三个月后,老周想确认:这一套到底值不值得坚持下去?他学聪明了,不再只听一两位熟客的夸奖,而是盯住三组数字:每桌平均点菜数、一个月内回头客比例、以及新菜被尝试的频率。不听单一声量,看系统指标,这是评估的第一原则。

推荐系统评估多样性,同样要分层把关。离线阶段先看指标组:ILAD 有没有提升?覆盖率涨了多少?长尾物品在曝光中的占比是否增加?这些指标快、便宜,但只是“模拟考”。真正的检验在线上的 AB 实验:一部分用户走老策略(对照组),一部分走多样性新策略(实验组),对比双方的实际行为指标——平均时长、留存、点击的类目广度,而不仅仅是 CTR 这一个数字。

AB 实验常用“提升率”来报告相对变化:

老周的三组数字替他说服了合伙人,评估体系的本质是建立信任。对推荐团队来说,离线指标帮你快速迭代,在线实验帮你稳健决策,而业务指标和体验度量帮你回答最后那个问题:多样性策略,到底有没有让用户更开心地留下来。

Lift=Metricexp−MetricctrMetricctr×100%\text{Lift} = \dfrac{\text{Metric}_{\text{exp}} - \text{Metric}_{\text{ctr}}}{\text{Metric}_{\text{ctr}}} \times 100\%
提升率像老周对比改革前后的“回头客占比”:涨了几个百分点,比任何自我感觉都可靠。
  1. 实验组指标$\text{Metric}_{\text{exp}}$ 是实验中应用多样性策略那组用户的观察值。
    Metricexp\text{Metric}_{\text{exp}}
  2. 对照组指标$\text{Metric}_{\text{ctr}}$ 是沿用旧策略那组用户的观察值。
    Metricctr\text{Metric}_{\text{ctr}}
  3. 相对变化两者相减再除以对照组,得到相对旧策略的提升幅度。
    Metricexp−MetricctrMetricctr\dfrac{\text{Metric}_{\text{exp}} - \text{Metric}_{\text{ctr}}}{\text{Metric}_{\text{ctr}}}
  4. 百分比表达乘以 100% 便于业务方阅读——“时长涨了 3%”,比“涨了 0.03”直观得多。
    ×100%\times 100\%

工程案例

老周把“点菜哲学”写成了一本后厨手册,从备菜到上桌每个环节都有章可循,店里的运转不再依赖某个厨师的临场发挥。企业级推荐系统同样如此:多样性的理念要落实为一个个可以稳定运行的工程模块。

以电商“猜你喜欢”为例。经典链路是“召回 → 粗排 → 精排 → 重排”,多样性主要发生在重排阶段。精排输出 100 个高分商品后,重排模块用 MMR 或者 DPP 做二次筛选:同一款式的衣服最多保留一两件,再插入搭配的裤子、配饰等不同类目。同时配合类目配额,保证一屏内服饰、数码、家居都有露脸机会。内容社区则是另一种形态:新用户缺乏历史行为,系统会给“探索池”分配固定流量,让 10% 的推荐位尝试用户没有任何记录的新领域内容,积累兴趣标签后再逐步调整多样性权重。

类目配额可以建模成一个带约束的优化问题:在“每类不超过上限”的前提下最大化总相关分:

工程落地的调参经验也很重要:λ 从 0.6 起步,观察 ILAD 和 CTR 的变化曲线,再按用户群体细分——新用户 λ 调小、回头客 λ 调大。一本清晰的后厨手册,加上持续的数据反馈,让“让用户吃得好也吃不腻”从口号变成了线上稳定运行的系统。

max⁡∑i∈Rreli⋅xis.t.∑i∈cxi≤capc, ∑i∈Rxi=k\max \sum_{i \in R} \text{rel}_i \cdot x_i \quad \text{s.t.} \quad \sum_{i \in c} x_i \le \text{cap}_c ,\ \sum_{i \in R} x_i = k
这像老周的后厨手册规定“一桌菜里同一主料的菜最多两道”——既要满桌好看,又不能任性地全上招牌肉。
  1. 决策变量$x_i$ 取 1 表示物品 $i$ 被选进最终列表,取 0 表示不选。
    xi∈{0,1}x_i \in \{0, 1\}
  2. 目标函数$\sum \text{rel}_i \cdot x_i$ 是所有被选物品的相关性得分之和,优化目标是让它最大。
    ∑i∈Rreli⋅xi\sum_{i \in R} \text{rel}_i \cdot x_i
  3. 类目上限约束$\sum_{i \in c} x_i \le \text{cap}_c$ 表示类别 $c$ 内被选中的物品数不能超过配额 $\text{cap}_c$。
    ∑i∈cxi≤capc\sum_{i \in c} x_i \le \text{cap}_c
  4. 总量约束$\sum_{i \in R} x_i = k$ 保证最终恰好选出 $k$ 个物品组成推荐列表。
    ∑i∈Rxi=k\sum_{i \in R} x_i = k

挑战展望

老周的馆子越开越火,可他心里仍有两件烦心事:一是新来的客人没有点菜记录,不知道口味偏好,该不该让他们尝创新菜?二是食材价格波动,每道新菜都有成本,试错多了要亏钱。这两件事,对应推荐多样性的两个永恒难题:冷启动和探索预算。

冷启动的本质是“信息不足时如何做决策”。用户是新的、物品是新的,系统没有历史信号,只能靠概率混合:一部分按先验知识推荐(比如热门新品),一部分随机探索(纯靠运气的惊喜)。这被称为探索与利用的权衡,可以用一个带 ε 的混合打分公式表示:

另一个方向是动态兴趣。用户的胃口是会变的,上个月爱吃辣的,这周可能迷上清淡的,多样性策略需要感知这种变化,动态调整 α 与 ε。多目标优化则是把多样性、准确性、时效性和商业指标放进同一个框架里联合求解,而不是拍脑袋调参。老周还在写他的新菜谱,推荐系统的探索也远未结束——在这条“相关与多样”的钢丝上保持平衡,永远是一门值得精进的学问。

Score(i)=(1−ε)⋅P0(i∣u)+ε⋅Peval(i)\text{Score}(i) = (1 - \varepsilon) \cdot P_0(i \mid u) + \varepsilon \cdot P_{\text{eval}}(i)
这像老周给新客人的上菜策略:七成按大众口味安排经典菜,三成赌一把上道创意菜。ε 就是那三成的“冒险额度”。
  1. 先验相关分$P_0(i \mid u)$ 是根据已有画像给出的物品相关概率,冷启动时它主要依赖性别、年龄、地理位置等粗粒度特征。
    P0(i∣u)P_0(i \mid u)
  2. 探索项$P_{\text{eval}}(i)$ 是探索信号,比如物品新颖度或随机实验分配的权重,负责“跳出舒适区”。
    Peval(i)P_{\text{eval}}(i)
  3. 混合权重$\varepsilon$ 是探索概率,取值在 0 到 1 之间,越大越爱冒险。
    ε∈[0,1]\varepsilon \in [0, 1]
  4. 加权合成两部分加权相加,兼顾了“稳妥的推荐”和“惊喜的尝试”。
    Score(i)=(1−ε)P0+εPeval\text{Score}(i) = (1 - \varepsilon) P_0 + \varepsilon P_{\text{eval}}

AI 应用场景

电商“猜你喜欢”的多样性重排

阶段:重排与策略优化

解决的问题:用户浏览过两件同款白色卫衣后,推荐流继续疯狂推同款卫衣,导致用户觉得“系统不懂我”、转化下降。传统方式只按 CTR 排序,完全没有考虑“重复感”,而 AI 重排可以通过 MMR 在精排结果上再次筛选,抑制与已选物品高度相似的候选,同时保留高相关物品。

具体案例:某电商平台在重排模块引入 MMR,λ 设为 0.65,并将“同款”相似度阈值调到 0.85。上线后,推荐列表的类目覆盖率提升 18%,用户人均浏览商品数增加 12%,而 CTR 只是微降 1%——用户看得更多,买得更欢。

短视频平台新用户的探索池

阶段:召回与探索机制

解决的问题:新注册用户没有观看历史,传统的协同过滤完全失效,系统只能推热门内容,导致新用户看到的全是“别人爱看”的,觉得平台没意思。AI 用 ε 探索策略混合打分,给冷启动用户留出固定比例的探索位推荐跨领域内容。

具体案例:某短视频 App 将新用户推荐流的 15% 分配给探索池,用 ε=0.15 的混合打分公式探索各类目内容。两周后,新用户次日留存提升 9%,且回访用户关注的话题数平均多了 2.3 个,兴趣画像建立速度明显加快。

资讯 App 的多样性 AB 实验评估

阶段:评估与在线实验

解决的问题:产品团队担心多样性策略会拉低点击率,迟迟不敢上线。传统评估只盯 CTR,忽略了多样性带来的长期价值。AI 的解法是设计一套分层 AB 实验:对照组用纯 CTR 排序,实验组用加强多样性的重排,同时观测点击率、阅读时长、人均类目数、长尾阅读占比等多个指标。

具体案例:某资讯 App 的 AB 实验持续 14 天,结果显示实验组 CTR 下降 2%,但人均阅读时长提升 6%,长尾类目的阅读占比从 11% 升到 19%,整体留存改善明显。团队据此判断多样性利大于弊,并全量上线。

Python 演示

python38 行
"""MMR 重排演示:在候选物品上应用最大边际相关,观察权重 alpha 对多样性的影响。"""  def mmr_rerank(candidates, rel_scores, alpha=0.7):    """candidates: 含 id 与 category 的字典列表       rel_scores: {id: 相关性得分}       alpha: 相关性权重,越大越偏相关,越小越偏多样    返回重排后的物品 id 列表。"""    selected = []    pool = list(candidates)     def similarity(a, b):        return 0.9 if a['category'] == b['category'] else 0.1     while pool:        best_id = None        best_score = -float('inf')        for item in pool:            rel = rel_scores[item['id']]            max_sim = max([similarity(item, s) for s in selected], default=0)            score = alpha * rel - (1 - alpha) * max_sim            if score > best_score:                best_score = score                best_id = item['id']        picked = next(item for item in pool if item['id'] == best_id)        selected.append(picked)        pool.remove(picked)    return [item['id'] for item in selected]  if __name__ == '__main__':    items = [{'id': i, 'category': i % 4} for i in range(12)]    rel = {i: 1.0 - i * 0.05 for i in range(12)}    for alpha in (0.3, 0.7, 1.0):        order = mmr_rerank(items, rel, alpha)        cats = [items[i]['category'] for i in order]        dup = sum(1 for i in range(len(cats) - 1) if cats[i] == cats[i + 1])        print('alpha=%.1f order=%s adjacent_dup=%d' % (alpha, order, dup))
目的:演示 MMR 重排中 alpha 参数的作用——alpha 越大越偏向相关性,列表内同类相邻越多;alpha 越小,系统越主动穿插不同类目,多样性越好。
  1. score = alpha * rel - (1 - alpha) * max_simMMR 的核心公式:相关分减去与已选集合的最大相似度,即“越相关越好、越重复越扣分”。
  2. max_sim = max([similarity(item, s) for s in selected], default=0)计算当前物品与已选集合里最相似的那个值,代表“撞车程度”。
  3. similarity(a, b)同类物品相似度设为 0.9,异类设为 0.1,这是工程里极简版的相似度函数。
  4. pool.remove(picked)选中的物品从候选池中移除,保证每个物品只被推荐一次。
  5. dup = sum(1 for i in range(len(cats) - 1) if cats[i] == cats[i + 1])统计相邻同类次数,用来快速对比不同 alpha 下的多样性表现。

常见误区

误区我看到推荐列表里全是同一类内容,就在重排里加一个随机函数,把结果粗暴打乱,觉得这样就有多样性了。反正用户看到不同的东西总比盯着看一样的好。

正解无约束的随机打散是“把红烧肉换成乱炖”,表面上花哨,实际上把相关性地基也给拆了。真正的多样性是“在相关性基础上的多样化”——MMR、DPP、类目配额都是带约束的优化,目标是让列表既保留高相关核心,又用不同类目去填充其余位置。打散是破坏,重排是重构,两者本质不同。

为何常见:初学者容易把“多样性”直观理解为“看起来不一样”,忽略了推荐系统最底层的目标是满足用户需求,多样性只是这个目标在长期维度上的补充。

误区我在离线评测里看到覆盖率从 20% 涨到 35%,ILAD 也明显提升,就觉得自己做的多样性策略非常成功,可以放心上线了。

正解覆盖率上升可能只是“把用户根本不看的冷门内容硬塞进列表”造成的假象。离线指标只能证明“系统变得多样”,无法证明“用户感受到了多样且因此更开心”。必须配合在线 AB 实验观察时长、留存、长尾点击占比等指标,才能判断策略是真正提升了体验,还是为了多样性牺牲了基本盘。

为何常见:离线指标容易获得、反馈快,而在线实验周期长、成本高,人们天然倾向于用“看起来专业”的离线数字说服自己。

误区我在重排里加了 MMR,也设置了类目配额,但线上效果还是不好。于是我以为算法有问题,其实可能是召回阶段捞上来的候选本身就全是同一类的东西。

正解多样性是一个链路问题。如果召回池里 90% 都是同一类目,再优秀的重排也无米下锅。要从源头解决:召回阶段就为长尾和不同类目留出入口,排序阶段加入对冗余的惩罚,最后重排阶段做精细筛选。老周的例子很贴切——后厨没备菜,菜单再花哨也是空谈。

为何常见:因为重排是“离用户最近”的环节,新手最容易在这个位置看到明显效果,从而忽略了上游系统性的偏差积累。

误区我给所有用户用同一个 MMR 参数 α=0.7,认为这样既照顾相关性又保留多样性,是一个放之四海而皆准的设置。

正解不同用户对多样性的容忍度差异极大:饭量小的客人只求一道满意的菜,喜欢尝鲜的客人巴不得每道都是新菜。同样,新用户需要更多探索来建立画像,重度老用户则需要更精准的重复推荐。业界做法是分人群设置 α:新客 0.4、活跃老客 0.7、流失预警用户 0.9,甚至用模型动态预测每位用户最优的 α。

为何常见:调参时“一个参数打天下”最省事,也最容易在局部找到看似合理的值,导致忽视了用户群体的结构性差异。

面试题

Q1. 推荐系统引入“多样性”的核心目的是?

单选题 · easy

  • A.让推荐列表内容更丰富
  • B.防止内容逐步越推越窄← 正确答案
  • C.降低服务器计算的负载
  • D.缩短模型训练的总时长

答案:B。多样性主要解决“信息茧房”问题——系统只推最相关的内容,用户看到的东西会越来越同质化,最终失去新鲜感。选项 A 是多样性带来的表面效果而非核心目的;C、D 是工程性能问题,与多样性无关。就像老周不能顿顿上红烧肉,系统也不能屏屏推同款。

Q2. ILAD 主要衡量哪方面多样性?

单选题 · easy

  • A.候选池整体的分布均匀度
  • B.全部用户推荐的总覆盖度
  • C.单个列表内物品间的差异← 正确答案
  • D.用户对推荐物品的点击率

答案:C。ILAD(列表内平均距离)是把单个推荐列表中的物品两两配对,计算它们的平均不相似度,属于“列表内多样性”指标。A 描述的是候选池整体分布的均衡性,B 是覆盖率,D 是点击率,三者都不是 ILAD 的定义。一桌菜里任意两道菜的平均差异,就是 ILAD 的直觉。

Q3. MMR 算法中的 λ 参数主要作用是?

单选题 · mid

  • A.调节学习速率和正则强度
  • B.权衡相关性与冗余惩罚← 正确答案
  • C.控制神经网络的层数规模
  • D.决定贝叶斯先验的强度

答案:B。MMR 选择物品的公式是“λ × 相关 − (1−λ) × 最大冗余”,λ 直接控制相关性项与冗余惩罚项的相对权重。λ=1 时只看相关,λ=0 时只看多样。A 是训练超参,C 是网络结构,D 是贝叶斯方法,均与 MMR 无关。

Q4. 覆盖率公式中分母 |D| 表示的是?

单选题 · mid

  • A.全部候选物品的总数量← 正确答案
  • B.单个用户的平均列表长度
  • C.模型可训练参数的总量
  • D.一周内用户的点击总次数

答案:A。覆盖率 COV = |∪D(u)| / |D|,分子是所有用户推荐列表的并集大小,分母是整个候选物品库的总量。它衡量系统整体能推荐出多少种不同的物品。B、C、D 分别与列表长度、模型参数、点击次数有关,都不是分母的含义。

Q5. 下列哪些做法会加剧推荐多样性降低?

多选题 · mid

  • A.只按点击率做榜单排序← 正确答案
  • B.召回阶段只取热门物品← 正确答案
  • C.对相似物品不做任何抑制← 正确答案
  • D.在重排中加入类目配额

答案:ABC。A 只按点击率排序会让高热度同类内容霸榜;B 召回只看热门会直接截断长尾;C 不抑制相似物品会让列表内部越来越同质。D 的类目配额恰恰是提升多样性的手段,不属于加剧因素。备菜只按最畅销的菜来,整本菜单必然会越来越窄。

Q6. 探索(exploration)机制的核心目的是?

单选题 · easy

  • A.让用户体验更多新内容← 正确答案
  • B.提高接口的响应速度
  • C.降低存储的占用开销
  • D.简化标签的维护流程

答案:A。探索是在“最优推荐”之外故意给用户看一些没有历史信号的内容,从而积累反馈、拓宽兴趣边界,也是冷启动的重要手段。B、C、D 是系统性能与工程效率问题,与探索无关。老周每周给熟客上一道创新菜,就是最容易理解的探索机制。

Q7. 下列对 DPP(行列式点过程)的描述正确的是?

单选题 · hard

  • A.每次都只选最高分物品
  • B.一次选子集并抑制相似项← 正确答案
  • C.用矩阵分解预测用户评分
  • D.无法处理大规模候选集

答案:B。DPP 的核心是整体挑选一个“既相关又彼此不同”的子集,通过行列式值同时考虑物品质量和两两之间的差异性,是多样性的全局最优方案。A 描述的是纯贪心排序,C 是协同过滤家族的方法,D 是错误的——DPP 结合贪心近似可处理大规模候选。

Q8. 评估多样性策略时,合理的做法包括?

多选题 · hard

  • A.只看离线覆盖率的提升
  • B.结合在线时长与留存指标← 正确答案
  • C.分人群单独分析实验结果← 正确答案
  • D.同步观察点击的类目分布← 正确答案

答案:BCD。多样性评估必须“离线 + 在线 + 业务”三管齐下。B 关注长期体验指标,C 避免一刀切掩盖不同人群的差异,D 直接观察推荐触达的类目广度。A 只凭离线覆盖率做判断,容易落入“推了用户不看的冷门内容”的假象陷阱。

Q9. 类目配额约束中 cap_c 的含义是?

单选题 · hard

  • A.单个类目被推荐的数量上限← 正确答案
  • B.模型在验证集上的准确率
  • C.分类器的输出概率阈值
  • D.用户画像标签的权重值

答案:A。类目配额是“每桌荤素搭配”的数学化:对每个类目 c 设定一个 cap,类目内被选入最终推荐列表的物品数不能超过这个上限,从而强制列表覆盖多个类目。B、C、D 分别属于模型评估、分类决策和用户画像的概念,并不涉及类目配额。

Q10. 关于多样性与相关性的权衡,下列说法正确的是?

多选题 · extreme

  • A.可用约束式优化平衡两者← 正确答案
  • B.提升多样可能牺牲相关分数← 正确答案
  • C.两者矛盾可通过调参消除
  • D.不同用户的最优权重不同← 正确答案

答案:ABD。A 正确,类目配额、MMR 都是约束式优化的例子。B 正确,多样性本质是对“纯相关排序”的偏离,必然在某些位置牺牲相关性。C 错误,两者是结构性矛盾,调参只能调整取舍位置,无法让“又全相关又全多样”同时成立。D 正确,不同用户对多样的容忍度不同,个性化 α 是业界共识。