🏠 总目录📚 本教程 13 · 冷启动与E&E
📑 本页目录(点开跳转)

13 · 冷启动与探索利用

20 分钟 | ⭐ 核心


🎯 一句话

冷启动 = 「没数据怎么推」;探索利用 = 「要不要冒险试试新东西」。 两者是同一枚硬币的两面:你不探索,就永远没数据。

时间 →累计收益回本点纯利用带探索前期更差(在花钱买信息)探索一开始一定是亏的 —— 它换来的是后面的信息⭐ 所以「探索该投多少」取决于你还要跑多久:短期活动别探索,长期系统必须探索
带探索的曲线一开始一定在纯利用下面 —— 那段差距就是你在花钱买信息。⭐ 所以「探索该投多少」取决于你还要跑多久:短期活动别探索,长期系统必须探索。

❄️ 三种冷启动

① 用户冷启动 —— 新用户来了,我啥都不知道
  • 难度:★★★☆☆ 解法相对成熟
② 物品冷启动 —— 新内容发布了,没人看过
  • 难度:★★★★★ 最难,也最关键 ⭐
  • 每天有海量新内容,处理不好整个内容生态就崩了
③ 系统冷启动 —— 新产品上线,两边都是空的
  • 难度:★★★★☆ 靠冷启动期的运营和外部数据

① 用户冷启动:五步阶梯

按「拿到的信息量」递进,工业界通常几种叠加使用:

用户刚打开 App —— 系统对他一无所知1Step 1 · 兜底:热门 + 高质量 + 多样推各类目爆款,覆盖尽可能多的兴趣 —— 多样本身就是在「探测」↑ 有了设备 / 注册信息2Step 2 · 人口统计 / 设备画像地域、机型(iPhone 15 Pro vs 千元机 → 消费力)、注册渠道↑ 主动询问用户3Step 3 · 引导页选兴趣 ⭐ 简单粗暴但极其有效「选 3 个感兴趣的话题」;代价是增加注册流失,要 A/B 权衡↑ 有了 3–5 次行为4Step 4 · 快速试探(Bandit)前 20 刷有意识铺开类目,用 Thompson Sampling 定位兴趣↑ 行为够多了5Step 5 · 正常个性化流程行为够多了,交给召回 → 精排的常规链路至此冷启动结束,进入常规个性化链路
用户冷启动是一条按「手里有多少信息」递进的阶梯:每上一级都靠新拿到的一类信息解锁,工业界通常几级同时叠加使用,而不是只挑一级。

🔧 实战关键:新用户前 20 次刷的体验,直接决定次日留存。 很多公司有专门的新用户推荐链路,模型、策略、指标都和老用户不同。


② 物品冷启动:最难的那个 ⭐

为什么难 —— 死亡螺旋

     新物品没有交互数据
              ↓
        模型给它低分
              ↓
         得不到曝光
              ↓
     永远没有交互数据  ←──┘  💀 无限循环

这个循环必须靠「外力」打破——这就是冷启动策略存在的原因。

解法一:内容特征(最根本)⭐

思路:新物品虽然没有行为,但有内容

  新视频
    ├─ 标题文本  → 文本 Embedding (BERT / 多语言模型)
    ├─ 封面图    → 图像 Embedding (CLIP / ViT)
    ├─ 视频内容  → 视频 Embedding
    ├─ 音频      → 音频 Embedding
    └─ 元数据    → 类目、标签、作者、时长

          ↓ 全部拼起来
    内容向量  →  在向量空间里找相似的老物品
          ↓
    继承它们的用户群 / 统计特征作为先验

双塔模型的一个巨大好处:物品塔的输入可以完全不含 item_id,只用内容特征。 这样任何新物品一发布就有向量,可以立刻参与召回。

📌 这叫 ID-free / Content-based Tower,是解决物品冷启动最优雅的方案。 折中做法:item_emb = ID_embedding + content_embedding,新物品 ID 部分为 0,靠内容部分工作。

解法二:强制曝光配额(Explore Pool)

def allocate_slots(candidates, n_slots=10, explore_ratio=0.1):
    """每 10 个位置留 1 个给冷启动物品"""
    n_explore = max(1, int(n_slots * explore_ratio))
    cold = [c for c in candidates if c.impressions < 1000]
    warm = [c for c in candidates if c.impressions >= 1000]

    result = warm[:n_slots - n_explore]
    result += sorted(cold, key=lambda c: c.content_score)[:n_explore]
    return result

分级流量池(工业界常用设计)

   新物品发布
        ↓
   【池 1】给 500 次曝光  →  CTR 达标?──否──→ 淘汰
        ↓ 是
   【池 2】给 5000 次曝光 →  CTR 达标?──否──→ 淘汰
        ↓ 是
   【池 3】给 5万次曝光   →  完播率达标?──否─→ 淘汰
        ↓ 是
   进入正常推荐池(爆款诞生)

⚠️ 注意统计陷阱:500 次曝光的 CTR 波动巨大,不能直接用来判定。 ✅ 用置信区间下界贝叶斯平滑后的估计(见第 7 节),否则会误杀好内容。

解法三:作者/店铺继承

新物品先继承作者的历史表现作为先验。 「这个作者过去 10 个视频平均完播率 60%」→ 新视频的初始预估也高一些。

解法四:跨域迁移

在其他场景已有数据的物品(如搜索里被搜过),迁移到推荐场景。


🎰 探索与利用(Explore & Exploit)

用老虎机讲清楚

   你面前有 5 台老虎机,不知道哪台中奖率高。
   有 1000 次机会,怎么赢最多钱?

   策略 A:全部投同一台(纯利用 Exploit)
      → 万一选错了,白白亏 1000 次

   策略 B:每台平均投 200 次(纯探索 Explore)
      → 知道了哪台好,但已经没机会了

   策略 C:先试探,逐渐把钱压到表现好的那台 ✅
      → 这就是 E&E 要解决的问题

映射到推荐: - 利用(Exploit):推模型认为你最喜欢的 → 短期收益高 - 探索(Explore):推不确定的内容 → 短期可能亏,但换来信息


三个经典算法(从简单到实用)

① ε-greedy —— 最简单

import random

def epsilon_greedy(candidates, model_scores, epsilon=0.1):
    if random.random() < epsilon:
        return random.choice(candidates)        # 10% 随机探索
    return candidates[int(np.argmax(model_scores))]   # 90% 选最优

✅ 一行就能实现 ❌ 探索是盲目的,不区分「已经很确定很差」和「还不确定」

② UCB —— 给不确定性加奖励

$$\text{UCB}_i = \underbrace{\bar{x}_i}_{\text{当前估计的收益}} + \underbrace{c\sqrt{\frac{2\ln N}{n_i}}}_{\text{不确定性奖励}}$$

💡 人话「这个东西看起来一般,但我只试过 3 次,说不定其实很好——给它加点分让它再露个脸。」

def ucb_score(mean_reward, n_pulls, total_pulls, c=2.0):
    if n_pulls == 0:
        return float('inf')                     # 没试过的必须先试
    return mean_reward + c * np.sqrt(2 * np.log(total_pulls) / n_pulls)

③ Thompson Sampling —— 工业界最爱 ⭐

思想:给每个物品维护一个「CTR 的概率分布」,每次从分布里采样,按采样值排序。

  物品A:曝光 10000 次,点击 500 次
         → 分布很窄,几乎确定 CTR ≈ 5%
              ╱▔▔╲
         ────╱────╲──────

  物品B:曝光 10 次,点击 1 次
         → 分布很宽,CTR 可能 1% 也可能 30%
            ╱▔▔▔▔▔▔▔▔╲
         ──╱──────────╲──

  每次从各自分布里抽一个数 → B 有机会抽到高值 → 得到曝光机会
  B 曝光多了,分布自然收窄 → 探索自动减少 ✅
import numpy as np

class ThompsonSampling:
    """Beta-Bernoulli Thompson Sampling —— 30 行的工业级 E&E"""
    def __init__(self, n_items, prior_a=1.0, prior_b=1.0):
        # Beta 分布的两个参数:alpha ≈ 点击数, beta ≈ 未点击数
        self.a = np.full(n_items, prior_a)
        self.b = np.full(n_items, prior_b)

    def select(self, candidates, k=10):
        """从每个候选的 Beta 分布采样,取采样值最高的 k 个"""
        samples = np.random.beta(self.a[candidates], self.b[candidates])
        top = np.argsort(-samples)[:k]
        return [candidates[i] for i in top]

    def update(self, item, clicked):
        if clicked: self.a[item] += 1
        else:       self.b[item] += 1

    def set_prior_from_content(self, item, predicted_ctr, strength=20):
        """⭐ 用内容模型的预估当先验,冷启动更快"""
        self.a[item] = predicted_ctr * strength
        self.b[item] = (1 - predicted_ctr) * strength

为什么 Thompson Sampling 在工业界最受欢迎: - 探索量自适应(不确定就多探索,确定了自动少探索) - 天然支持并行/批量推荐(每个位置独立采样) - 实现简单,效果通常优于 UCB 和 ε-greedy - 容易接入先验(用内容模型的预估初始化)


🚀 更进一步:Contextual Bandit

上面的 bandit 对所有用户一视同仁。Contextual Bandit 考虑用户特征:

「这个视频对科技爱好者的 CTR 是多少?」而不是「这个视频的 CTR 是多少?」

代表算法:LinUCBNeural Bandit。 本质是:用一个模型预测收益 + 用模型的不确定性做探索


🕸️ 反馈循环:探索的深层价值

① 模型推荐 AA 拿走了绝大部分曝光② 用户点了 A因为只有 A 有机会被看到③ 训练数据全是 AB/C/D 连曝光记录都没有④ 模型更确信 A 好下一轮更用力地推 A回音室越推越窄的闭环🔓 探索 = 打破循环强制分给 B/C/D一点曝光机会,才知道它们好不好💀 不探索的结局:模型越来越确信只有 A 好,B、C、D 从此人间蒸发
关键是这个「环」:曝光决定了训练数据,训练数据又决定下一轮曝光。不主动撕开一个口子,系统就只会不断证明自己是对的。

所以探索的价值不只是「找到新爆款」,更是: 1. 收集无偏训练数据(用于正确评估模型,见第 12 节) 2. 防止模型退化到局部最优 3. 维持内容生态健康(新作者有出头机会) 4. 打破用户的信息茧房

🔧 工业界的标配:留 1–5% 的流量做完全随机曝光。 这部分流量的短期指标一定是负的,但它产生的无偏数据集是整个系统的「校准基准」。 说服老板保留这部分流量,是算法负责人的重要工作。


🎚️ 探索强度怎么定

场景 探索比例 理由
新用户前 20 刷 高(20–30%) 快速定位兴趣
成熟用户 低(5–10%) 已经很了解,探索成本高
内容更新极快(新闻/短视频) 物品生命周期短,必须持续探索
内容稳定(电影/图书) 老物品的估计已经很准
高风险决策(贷款/医疗) 极低或不探索 探索的代价是真实伤害 ⚠️

🔗 这一章连到哪里

去哪为什么
强化学习 07ε-greedy / UCB / Thompson Sampling 的原理与后悔界:UCB 那个 √(2lnN/n) 是怎么推出来的
强化学习 01多臂老虎机是 RL 的最小形态;「纯利用一定次优」这件事在这里被讲清楚
数学原理 02Thompson 的 Beta(a,b) 就是先验伪计数——用内容模型预估当先验,正是贝叶斯的 MAP 视角

✅ 检查点

  1. 三种冷启动分别是什么?哪个最难?
  2. 物品冷启动的「死亡螺旋」是什么?怎么打破?
  3. 双塔模型怎么帮助物品冷启动?(ID-free 塔是什么意思)
  4. ε-greedy、UCB、Thompson Sampling 的核心区别?
  5. Thompson Sampling 为什么在工业界最受欢迎?
  6. 为什么要留 1-5% 流量做随机曝光?(说出两个理由)
👀 答案 1. 用户冷启动、物品冷启动、系统冷启动。物品冷启动最难,因为新内容持续大量产生,且处理不好会伤害整个内容生态。 2. 没数据→模型低分→没曝光→还是没数据。必须靠外力打破:内容特征、强制曝光配额、分级流量池。 3. 物品塔的输入可以只用内容特征不含 item_id,这样新物品一发布就有向量,能立刻参与召回。 4. ε-greedy 固定概率盲目随机;UCB 给「试得少」的物品加确定性奖励;Thompson Sampling 给每个物品维护收益的概率分布,每次采样后排序,探索量自适应。 5. 探索量自适应(不确定就多探索,确定后自动减少)、天然支持批量推荐、实现简单、效果通常最好、容易接入内容模型作为先验。 6. ① 收集无偏训练/评估数据,用来正确评估模型(对抗曝光偏差);② 打破反馈循环,防止模型退化到局部最优、维持内容生态和用户兴趣的广度。

🛑 可以停在这里

走神救援

冷启动三种:用户(五步阶梯:兜底→画像→选兴趣→bandit→正常)、物品(最难,死亡螺旋,靠内容特征 + ID-free 双塔 + 分级流量池)、系统。E&E 三算法:ε-greedy(盲目)、UCB(给不确定性加奖励)、Thompson Sampling(采样,探索自适应,工业最爱)。留 1-5% 随机流量收集无偏数据 + 打破反馈循环。死亡螺旋的闭环长这样:新物品没数据 → 模型不敢推 → 拿不到曝光 → 永远没数据。ID-free 双塔是最优雅的破法:物品塔只吃内容特征、不含 item_id,新物品一发布就有向量;折中写法是 item_emb = ID_emb + content_emb,新品 ID 部分为 0,先靠内容工作。⭐ 分级流量池(500 → 5000 → 5 万曝光,逐级看 CTR/完播率晋级或淘汰)是工业界的标配。⚠️ 但这里有个统计陷阱:500 次曝光算出的 CTR 波动极大,绝不能直接拿来判生死,要用置信区间下界或贝叶斯平滑后的估计,否则会误杀好内容。⭐ Thompson 的杀手锏是 先验可以从内容模型灌进去a=预估CTR×strength, b=(1-预估CTR)×strength),冷启动和 E&E 在这里合成了一件事。⭐ 再往前一步是 Contextual Bandit(LinUCB / Neural Bandit):问的不再是「这个视频 CTR 多少」,而是「这个视频对科技爱好者的 CTR 多少」。⚠️ 探索强度要分场景:新用户前 20 刷可以 20–30%,成熟用户 5–10%,而贷款、医疗这类高风险决策几乎不该探索——那里探索的代价是真实伤害。

下一节 👉 14-生成式推荐-2026前沿.md

🔨 想把这一节变成肌肉记忆? 挑战项目B·信息流模拟器 会让你亲眼看到反馈循环怎么毁掉一个推荐系统,再用本节的 Thompson Sampling 把它救回来。

打卡记录保存在你的浏览器里,首页能看到总进度