学校食堂新来了一位师傅,他很快发现一个道理:如果只盯着“大家最爱吃什么”来做菜,每天端上五道红烧肉,第一周大家吃得很开心,第二周就开始剩菜,第三周大家改点外卖了。菜好吃,不等于天天吃不腻。推荐系统也是一样——传统算法拼命追求“推荐得准”,结果把用户喜欢的内容同类型地不断堆回去,短期点击率漂亮,长期用户却悄悄流失。于是,“多样性”成了推荐系统里一把重要的尺子。这把尺子要量两件事:第一,一个推荐列表内部,物品之间是否足够有差异,这叫 Intra-list 多样性;第二,不同列表之间(不同用户之间、或同一个用户不同时间段之间)是否互相重复,这叫 Inter-list 多样性。就像评价一个食堂师傅,既要看他一个餐盘里荤素搭配得如何,也要看他给不同顾客端的盘子是不是千篇一律。本文就用“食堂配菜”这个比喻,把这把尺子的原理、算法和工程实践一次讲透。
对 AI 从业者来说,多样性度量是推荐系统从“能推荐”走向“会推荐”的关键标尺。掌握 Intra-list / Inter-list 两种度量,你就能在设计排序策略、诊断信息茧房、做冷启动探索时有的放矢——这是推荐算法工程师面试和日常优化中绕不开的核心能力。
目录
可视化演示
展示Intra-list列表内多样性、Inter-list列表间多样性、MMR最大边际相关性和DPP行列式点过程,含六边网格背景和发光动画。
本节配有交互动效(进入视口后自动加载,约 3KB)。
多样性缘起:为什么推荐不能只看准确率
学校食堂的师傅最初以为,把最受欢迎的红烧肉做多一点总没错。于是他每天的五道菜全换成红烧肉——第一周光盘,第二周剩菜,第三周学生们开始点外卖。菜好吃,不等于天天吃不腻。 推荐系统也一样:早年大家只比赛点击率(CTR)、评分预测误差(RMSE)这类“好不好吃”的指标,算法为了贴合用户历史喜好,把同类型内容疯狂往回推。你以为用户爱看悬疑剧,就十条推八条悬疑剧。短期指标漂亮,长期用户却悄悄流失。这就是信息茧房:推荐列表的营养面越来越窄。
为了让“不腻”有标尺可量,业界把多样性列为推荐列表的关键体验指标。一个最直观的度量,是看列表里主导类目占多大比例:
师傅后来明白,评价一餐不能只看“是否有人吃光”,还要看“盘子里的菜是不是太单一”。$1-\max$ 就像给餐盘拍一张照、数数颜色——颜色越少,越单调。
- 列表 $L$ 与长度 $N$$L$ 是推荐系统给用户返回的一次列表,$N$ 是列表里放了多少个物品,比如手机屏幕一屏 10 个。
- 类目集合 $\mathcal{C}$ 与目标类目 $c$把物品按内容分类(电影、小说、纪录片……),$\text{count}_c(L)$ 统计类目 $c$ 在列表里出现了几次。
- 最大占比$\displaystyle \max_{c \in \mathcal{C}}$ 找出占比最高的那个类目,比如 5 道菜里 4 道是红烧肉,占 0.8。
- 取补得到多样性用 $1$ 减去主导占比,占比高则多样性低,反之则高。
准确率权衡:在“合胃口”与“有新意”之间找平衡
师傅开始正式配菜。如果他每顿都做顾客最爱吃的糖醋排骨,准确率 100%,可连吃三天没人受得了;如果他为了花样百出,每天做十道从没见过的暗黑料理,顾客又嫌不好吃。现实中的配菜,是在“合胃口”和“有新意”之间找平衡。这正是推荐系统里著名的探索与利用(Exploration vs Exploitation)问题:利用是把已知高相关的物品排前面,把 CTR 做高;探索是把用户没点过但可能喜欢的物品混进来,把多样性做上去。两者在目标函数里常常是一对矛盾项。
常见的做法是把相关度和多样性加权组合成整体效用,再在列表长度约束下求最大化:
食堂经营要同时看“好吃”和“不腻”。推荐系统里的 λ 就是师傅手里那勺“新菜比例”——舀多了可能翻车,舀少了又腻。
- $\text{Rel}(L)$ 相关度总分把列表里每个物品与用户的匹配程度加起来,相当于“菜合口味的总分”。
- $\text{Div}(L)$ 多样性总分用后续介绍的 ILD 或类目覆盖度等指标计算列表的差异程度。
- $\lambda$ 平衡系数λ 大则偏好探索,λ 小则偏好利用;这是业务上可以直接调的旋钮。
- 约束 $|L|=N$列表长度固定,不能为了多样性而无限制地加菜。
单列度量:如何给“一个餐盘”打分
光说“不腻”还不够,得能量化。单看一个餐盘,如何用数字说明它丰富?答案是:把盘子里每两道菜都比一比,看看它们差距有多大。Intra-list 多样性(列表内多样性)衡量的正是这个:同一个推荐列表中物品彼此之间的差异。业界最经典的单列指标是 ILD(Intra-list Distance,列表内平均距离):
实践中还会用更简单的类目覆盖度做 Intra-list 近似的替代:列表覆盖的类目数除以列表长度。极限情形很直观——全部同类目,ILD 为 0;全部各不相同,ILD 达到最大。餐盘里如果把“红烧肉 vs 拍黄瓜”“红烧肉 vs 冬瓜汤”的差距全部求平均,平均值高,就说明这盘菜搭配丰富。这就是 ILD 的朴素直觉。
- 两个求和符号外层 $i$ 从 1 到 $N$,内层 $j$ 从 $i+1$ 到 $N$,保证每对物品只算一次——就像每两道菜比较一次,不重复、不遗漏。
- 距离函数 $d$$d(\text{item}_i, \text{item}_j)$ 给两个物品打分,越不相似数值越大;它可以用内容向量的余弦距离,也可以用类目直接判断。
- 累加所有两两距离把所有组合的差异加在一起,相当于把盘子里所有“两道菜对比”的差距累计起来。
- 除以组合数 $N(N-1)/2$系数 $2/[N(N-1)]$ 正好等于 $1 / C_N^2$,让结果变成“平均每对差距”,不受列表长短影响。
跨列度量:两个盘子之间,或昨天和今天之间
师傅刚保证了单盘丰富,另一个问题又来了:两个顾客端着完全一样的餐盘,或者同一个顾客昨天和今天吃的是同一套菜。就算每盘内部很丰富,重复上菜依然会腻。Inter-list 多样性(跨列表多样性)关注的就是不同列表之间的差异,它主要用在两个场景:一是多用户之间,不同用户看到的推荐结果应当有区分度,不能千篇一律;二是同一用户的连续会话,今天的列表不要和昨天的几乎一样。
最直接的指标是重叠率(Overlap):
再进一步,考虑时间维度的 NGSD(Next-list / Next-session Diversity,下一列表多样性):
师傅可以随时自问:昨天端上的 4 道菜,今天还剩几道?剩得越少,越说明师傅懂得“换花样”。Inter-list 度量就是给这份“翻新率”打分。
- $L_u(t)$ 与 $L_u(t-1)$同一个用户 $u$ 在最近两次推荐得到的列表,比如昨天一屏和今天一屏。
- 交集 $|L_u(t) \cap L_u(t-1)|$两屏里重复出现的物品个数。重复 3 个,就说明有一半是剩菜。
- 除以当前列表长度 $|L_u(t)|$把绝对重复数转成比例,排除列表长度不同的影响。
- 用 $1$ 减重复比例越高,得分越低;NGSD 越大,列表间差异越大、多样性越好。
优化策略:MMR 贪心、DPP 与类目打散
现在师傅知道了目标,怎么把目标落进现实?他要在几十道候选菜里选出 4 道,既要合口味,又要彼此不重复。最直觉的方法是一道一道挑:每次挑新菜时,不仅看它好不好吃,还要看它和盘里已选的菜像不像。这就是 MMR(Maximum Marginal Relevance,最大边际相关)贪心重排的核心思想——从候选集合 $R$ 中逐步选出物品加入已选集 $S$:
比 MMR 更全局的方法是 DPP(Determinantal Point Process,行列式点过程):它一次性选出一个“整体多样性最优”的子集,从概率上避免贪心带来的局部次优。工程界最常用的还有类目打散——先把候选按相关度排好,再按类目轮换插空,简单粗暴但效果稳定。师傅每挑一道菜都回头看看盘里:新菜和哪道最像?太像就扣分。这样 4 道菜挑完,盘里既有好吃的,又有差异。
- 候选减去已选 $R \setminus S$只从还没被选中的物品里挑,保证盘子里不会出现重复。
- 相关度 $\text{rel}(s_i)$$s_i$ 与用户需求的匹配分,相当于菜的“口味分”。
- 最大相似度惩罚把 $s_i$ 和已选集合中每个物品比相似度,取最大的那个作为惩罚——新菜与任何一道老菜越像,扣分越多。
- $\lambda$ 权重决定“口味分”与“重复惩罚”谁更重,是师傅手中的配菜旋钮。
冷启动应对:用多样性当“探针”
新食堂开业,师傅对每位顾客的口味一无所知:不晓得谁爱吃辣、谁爱清淡。如果只按大众口味做菜,所有人都吃一样的“招牌菜”,反而永远探不到顾客的个性需求。新店阶段的策略是:每桌都先上几道不同风味的小样,让顾客尝了再说。这就是推荐系统的冷启动问题——新用户或新物品缺少历史反馈时,没有可靠的相关度信号可用。如果照搬热门榜,列表会异常同质化(全是爆款),加剧马太效应。冷启动阶段恰恰要把多样性当作“探针”:用类目先验、均匀采样等方式主动覆盖更多内容类目,尽早点亮用户兴趣。
一种经典做法,是用随反馈衰减的探索权重来混合热门策略与均匀策略:
新店靠“试吃小样”摸清顾客口味,反馈越多,师傅越敢加大招牌菜比例。冷启动的多样性,就是系统在不确定性最高时用于购买信息的“菜单样品”。
- $P_{\text{pop}}(i)$ 热门概率物品 $i$ 被推荐的基础热度,相当于食堂的固定招牌菜。
- $P_{\text{uniform}}(i)$ 均匀概率让所有类目有相近机会被推荐,是“广撒网”的探针。
- $\eta(u)$ 探索权重由反馈量决定。新用户 $\text{fb}(u)=0$ 时 $\eta=1$,几乎全靠探索;老用户 $\eta \to 0$,回归个性化。
- $\beta$ 平滑常数控制“从探索转向利用”的速度,反馈积累越快,越早进入稳定配菜阶段。
评估实践:离线指标、在线实验与业务联动
食堂经营一个月,光看师傅自己说“我配菜很均衡”不算数。老板要看:回头客多了没有?剩菜多了没有?新顾客愿不愿意再来?——这才是评估。推荐系统的多样性评估同样要分三层。离线评估是在历史数据上直接计算 ILD、重叠率、覆盖率等指标,快速验证策略方向;在线 AB 实验则要切流量对比,观察多样组和对照组在 CTR、时长、留存上的差异;最后的业务联动最关键:多样性不能单看,要和相关度指标一起考察,否则会出现“多样性升了、点击率崩了”的翻车。
工程上常用加权综合健康分来对齐指标:
师傅的配菜评估不能只看“今天光盘率”,还要看“明天还来不来”以及“顾客有没有抱怨菜式重复”。多样性最终要为留存和长期体验服务,这正是推荐系统持续优化的意义所在。
- $\text{CTR}$ 相关度侧写点击率反映“推荐内容是否合胃口”,相当于顾客是否愿意下筷子。
- $\text{Div}_{\text{norm}}$ 归一化多样性把 ILD、Overlap 等不同尺度的多样性值映射到 $[0,1]$,便于相加。
- $\lambda$ 权重由业务决定多样性在综合评分中的份量,例如内容社区更重视新鲜感时 λ 调大。
- 同步观察多指标单个数字健康不代表真健康,还要盯时长、留存、负反馈率。
AI 应用场景
长视频平台首页信息流
阶段:重排序(Ranking)阶段
解决的问题:传统 CTR 排序容易把同类型剧集堆在同一屏,用户刷到第 4 条就开始划走。通过 Intra-list 多样性约束(如类目打散 + ILD 监控)让一屏内剧情、综艺、纪录片交替出现,可以显著降低审美疲劳。
具体案例:某长视频 App 在首页信息流上线“类目打散 + ILD 上限约束”后,同类内容连续曝光率下降 42%,单次会话观看时长提升 8%,人均次日留存提升 3 个百分点——这就是“少推一道红烧肉,多上一碟拍黄瓜”的收益。
电商跨用户“猜你喜欢”
阶段:召回 / 后处理阶段
解决的问题:新用户没有行为记录时,系统容易把热销爆款推给所有人,导致“千人一面”——这本质是跨列表多样性(Inter-list)差的问题。通过重叠率监控,平台可以发现并干预“两个用户推荐列表重合度过高”的情况。
具体案例:某电商平台针对新用户引入类目探索机制:前 3 次推荐中强制覆盖 6 个以上叶子类目,并用 Overlap 指标监控新老用户列表的差异度。实验组新用户首单转化率比对照组提升 15%,且 7 日复购率更高。
音乐播放器的连续播放
阶段:流式排序 / 会话级排序
解决的问题:音乐 App 的连续播放如果总推同一歌手或同一曲风,用户很快疲惫。这正是 NGSD(会话级 Inter-list 多样性)的应用场景:上一首和下一首之间要有足够差异。
具体案例:某音乐 App 在“每日推荐”中引入 NGSD 约束,让连续两首歌的艺人相似度和曲风相似度都不能超过阈值。上线后,用户平均播放时长提升 11%,切歌率下降 20%,“随手播下去都不会腻”成了评论区高频好评。
Python 演示
import numpy as np def _normalize(vec): norm = np.linalg.norm(vec) return vec / norm if norm > 0 else vec def intra_list_diversity(item_vecs): """计算 Intra-list 平均两两距离(ILD)""" n = len(item_vecs) if n < 2: return 0.0 total = 0.0 for i in range(n): for j in range(i + 1, n): cos = float(np.dot(_normalize(item_vecs[i]), _normalize(item_vecs[j]))) total += 1.0 - cos return 2.0 * total / (n * (n - 1)) def inter_list_overlap(list_a, list_b): """计算列表间重叠率:交集大小 / 并集大小""" sa, sb = set(list_a), set(list_b) common = len(sa & sb) union = len(sa | sb) return common / union if union else 0.0 def ngsd(prev_list, cur_list): """计算 NGSD:1 - 当前列表与上一列表的重复比例""" n = len(cur_list) if n == 0: return 0.0 return 1.0 - len(set(prev_list) & set(cur_list)) / n def demo(): item_vecs = { '钢铁侠': np.array([1.0, 0.1, 0.0]), '美队': np.array([0.9, 0.2, 0.0]), '流浪地球': np.array([0.1, 1.0, 0.0]), '舌尖': np.array([0.0, 0.8, 0.2]), '小猪佩奇': np.array([0.0, 0.1, 1.0]), } list_a = ['钢铁侠', '美队', '流浪地球', '舌尖', '小猪佩奇'] list_b = list_a[:] # 与 A 完全相同 → Inter 多样性差 list_c = ['流浪地球', '钢铁侠', '小猪佩奇', '美队', '舌尖'] # 换顺序,集合没变 print('A 列表 Intra-list ILD:', round(intra_list_diversity([item_vecs[i] for i in list_a]), 4)) print('A vs B Overlap:', round(inter_list_overlap(list_a, list_b), 4)) print('A vs C Overlap:', round(inter_list_overlap(list_a, list_c), 4)) print('连续两时刻 NGSD:', round(ngsd(list_a, list_b), 4)) if __name__ == '__main__': demo()
def intra_list_diversity(item_vecs)定义 ILD 计算函数,对应正文第 3 节的公式total += 1.0 - cos用余弦距离逐对累加两两差异return 2.0 * total / (n * (n - 1))除以组合数,得到平均两两距离def inter_list_overlap(list_a, list_b)交集除以并集,衡量两个列表的重叠程度def ngsd(prev_list, cur_list)用 1 减重复比例,反映连续两次推荐的新鲜度list_b = list_a[:]构造一个与 A 完全相同的列表,用来揭露“Intra 好但 Inter 差”list_c = ['流浪地球', '钢铁侠', '小猪佩奇', '美队', '舌尖']只换顺序不换集合,重叠率依然是 1.0,说明“打乱顺序 ≠ 多样性”
常见误区
误区有的人觉得,既然要多样性,那我直接把推荐列表 shuffle 一下、换个顺序,不就多样了吗?反正看起来“乱”了。
正解随机打乱只是改变了排列位置,物品集合本身一个没变。如果列表里全是同类型内容,shuffle 后还是同类型。多样性度量衡量的核心是“内容之间的差异”,不是“顺序的凌乱”。拿食堂打比方:把五盘红烧肉在桌上换个位置,顾客依旧面对五盘红烧肉。
为何常见:直观上容易把“乱”等同于“丰富”,忽略了多样性度量的对象是内容集合的差异,而不是视觉上的顺序变化。
误区“我把每个列表内部都做了充足的类目打散,每个列表都五颜六色的,那列表之间的多样性肯定也没问题吧?”
正解完全不是。本文可视化演示就是最极端的反例:两个列表内部都四色齐全(Intra 优秀),但逐位对比完全一致(Inter 极差)。Intra-list 管的是“一个盘子里菜与菜的差异”,Inter-list 管的是“两个盘子之间或两顿之间的差异”,两者是不同维度的指标,必须分别计算、分别监控。
为何常见:因为日常优化大多只盯着单屏效果,容易忽视“不同用户看到的内容是否千篇一律”“今天和昨天是否重复”这些跨列表问题。
误区“多样性指标升了肯定对用户体验好,那把 λ 调到最大,让系统彻底放飞自我吧!”
正解多样性过度会严重伤害相关性——用户会觉得“推荐的都是什么乱七八糟的东西”。真实业务中,多样性提升的同时必须守住 CTR、时长、留存等底线。就像食堂师傅如果为了花哨每天做十道黑暗料理,顾客第一顿觉得新奇,第二顿就跑了。多样性是约束条件,不是唯一目标,需要与相关度联合调优。
为何常见:把指标本身当成了最终目标,而忘了指标的初衷是服务于用户长期体验。
误区“冷启动时用户没有行为反馈,算法反正也猜不准,先把热门内容推上去刷量,等数据多了再考虑多样性。”
正解冷启动恰恰是最需要多样性策略的阶段。没有反馈时,热门推荐会让所有新用户看到同一批爆款,形成新的“千人一面”;而多样性的探索性推荐(如类目均匀、探索加权)能主动覆盖更多内容类目,帮助系统快速收集用户兴趣信号。冷启动的多样性不是奢侈品,而是购买信息的必要投资。
为何常见:把冷启动当成了“无指标可优化”的空白期,忽略了此时系统最需要靠多样性打破信息茧房。
面试题
Q1. 下列哪项描述最符合 Intra-list 多样性?
- A.不同用户的推荐列表差异
- B.单个列表内物品的差异← 正确答案
- C.推荐结果与点击反馈的差异
- D.同一物品在列表中的重复率
答案:B。Intra-list 是“列表内部”,衡量一个推荐列表里物品彼此之间的差异。选项 A 说的是 Inter-list,C 说的是相关性评估,D 说的是重复率。就像评价一个餐盘,看的是盘内菜与菜之间搭不搭,而不是两个盘子之间像不像。
Q2. ILD(Intra-list Distance)计算时使用的是物品之间的什么量?
- A.物品两两之间的相似度
- B.物品两两之间的距离← 正确答案
- C.物品在列表中出现的频率
- D.用户浏览行为的活跃频度
答案:B。ILD 是“平均两两距离”,分母是组合数,分子是距离总和。注意它用的是距离而非相似度——距离越大,差异越大,多样性越好。如果误用相似度,方向就反了。
Q3. 影响 Intra-list 多样性计算结果的因素有哪些?
- A.列表长度 N 的具体大小← 正确答案
- B.物品间距离函数的选择← 正确答案
- C.参与推荐的总人数规模
- D.列表内物品类目的分布← 正确答案
答案:ABD。列表长度 N 通过组合数影响归一化,距离函数 d 直接决定两两差异值,类目分布决定了物品的差异结构;而参与推荐的总人数跟单个列表内部的多样性无关。就像一盘菜的多样性取决于盘中有几道菜、菜与菜差多远,而不是今天店里来了多少人。
Q4. 两个推荐列表的重叠率是 50%,下列判断正确的是哪项?
- A.对,重合率已足够低
- B.错,重叠过高缺新意← 正确答案
- C.无法仅凭重合率判断
- D.取决于列表间距离值
答案:B。重叠率 50% 意味着两个列表一半内容相同,对用户而言“这一半是重复上菜”,Inter-list 多样性明显偏差。重叠率作为跨列表多样性指标时,数值越高越差,不需要再看其他距离值——就像两个餐盘一半的菜一样,已经足够说明问题。
Q5. NGSD 计算中,分子是“当前列表与上一列表的交集大小”,分母是什么?
- A.两个列表并集的大小
- B.当前列表的长度 N← 正确答案
- C.全库物品的总个数
- D.目标用户的总数量
答案:B。NGSD 关注的是当前列表被上一列表“污染”了多少,因此分母用当前列表长度 $|L_u(t)|$,把重复数转成比例后再用 1 减。如果分母换成并集,指标含义就变成了 Jaccard 相似度,不再适合跨时刻序列的衡量。
Q6. MMR 算法在每一轮选择物品时,会考虑哪些因素?
- A.与已选集合的最大相似度← 正确答案
- B.物品自身的相关度打分← 正确答案
- C.物品上架时间的早晚
- D.用户历史点击偏好的信号← 正确答案
答案:ABD。MMR 的公式是 $\lambda \cdot \text{rel}(s_i) - (1-\lambda) \max \text{sim}$,其中 rel 通常来自用户历史点击偏好建模,sim 是某候选与已选集合的最大相似度。上架时间不在 MMR 标准公式中。就像师傅挑菜时只看两件事:好不好吃、和盘里已选的菜像不像,而不看这道菜是什么时候进的货。
Q7. 为什么冷启动阶段特别需要重视推荐多样性?
- A.多样性可提升计算的响应速度
- B.反馈稀少需要探索更多类目← 正确答案
- C.多样性可以完全替代准确率
- D.冷启动不存在多样性的问题
答案:B。冷启动时没有用户反馈,系统无法准确判断用户口味,此时用多样性策略(类目均匀、探索加权)主动覆盖更多内容,能像“试吃小样”一样收集兴趣信号。多样性不是替代准确率,而是帮系统更快逼近准确率。
Q8. 在线评估一个“多样性提升”实验时,除多样性指标外还应监控下列哪些业务指标?
- A.点击率(CTR)的变化幅度← 正确答案
- B.用户平均停留时长的变化← 正确答案
- C.离线 ILD 指标的计算过程
- D.内容完播率的波动趋势← 正确答案
答案:ABD。在线实验必须同时监控相关度侧写(CTR)和用户价值侧写(时长、完播率),防止多样性上升但体验崩盘。离线 ILD 计算是验证策略方向的工具,不是在线实验的业务监控指标。就像食堂上新菜单后,要盯顾客夹菜次数、用餐时间和剩菜量,而不是去重算菜谱配比公式。
Q9. 下列哪种方法是重排序阶段常用的多样性优化算法?
- A.MMR 最大边际相关法← 正确答案
- B.SGD 随机梯度下降法
- C.PageRank 网页排序法
- D.K-means 聚类算法
答案:A。MMR 是专门用于相关性与多样性平衡的贪心重排算法;SGD 是优化器,PageRank 是图排序,K-means 是聚类。MMR 的核心思路是“每挑一道新菜,都要拿它与已选菜的最大相似度作为惩罚项”。
Q10. 一个推荐列表长度是 5,5 个物品全部属于“悬疑”类,它的 Intra-list 多样性表现如何?
- A.很不错,类目很集中
- B.很差,内容高度同质← 正确答案
- C.与类目分布没有任何关系
- D.取决于物品的排列顺序
答案:B。5 个同类物品的两两距离必然很小,ILD 趋近于 0,类目覆盖度也只有 1/5,Intra-list 多样性极差。类目集中和多样性好是两回事——五道菜全是红烧肉,哪怕摆得再整齐,也是一盘腻菜。