想象你是美食杂志的数据分析师。杂志社有几百位美食评论家,他们品鉴过城市里不计其数的餐厅,但显然没人能尝遍所有店。编辑想知道:如果让某位只吃过二十家店的评论家去一家他从未去过的新餐厅,他会打几分?直接数「共同吃过的餐厅」太粗浅——评论家之间的交集少得可怜。这时你灵机一动:虽然每个人的口味千差万别,但本质都可以拆成几个「口味维度」——辣度偏好、甜口喜爱、分量要求、环境讲究、性价比敏感。每家人在这几个维度上有各自的偏好分数(用户向量),每家餐厅在这几个维度上也有自己的表现分数(物品向量),两者一相乘,就是个性的化预测。这个思路就是隐语义模型(Latent Factor Model,LFM)。 但新问题冒出来了:评论家们只留下「去过哪些店」的记录(正样本),却没有「明确说讨厌哪些店」的信息。那些没去过的店成百上千,我们该挑哪些当「他不喜欢」的样板(负样本)来训练?随机挑?专挑热门店?还是专挑那些看起来很像他会喜欢的店?这就是负采样(Negative Sampling)要解决的难题。本文将通过这个故事,带你逐步理解 LFM 的原理、负采样的三种策略、比例把控与训练实践。
掌握 LFM 与负采样,是进入工业级推荐系统的重要台阶。无论是电商、短视频还是信息流产品,隐语义模型都是召回阶段最常用的算法之一,而负采样的质量直接决定模型效果。学会它,你就理解了推荐算法工程师日常工作中最核心的一块拼图。
可视化演示
演示矩阵分解R≈PQ^T的因子学习、三种负采样策略对比及隐因子空间中用户-物品匹配关系。
本节配有交互动效(进入视口后自动加载,约 3KB)。
矩阵分解 稀疏矩阵R分解为P·Q^T 内积预测r_hat=p_u·q_i min Σ(r_ui - p_u·q_i)^2 + λ(|p_u|^2+|q_i|^2) 通过SGD学习用户和物品的隐因子向量
协同过滤瓶颈
美食杂志的编辑们最开始的推荐办法是「找风格相近的餐厅」。怎么判断两家餐厅风格相近?看看它们是不是常被同一群评论家光顾。如果评论家 A 喜欢川菜馆 X,而 X 和 Y 经常出现在同一拨人的打卡记录里,那 Y 大概也合 A 的口味。这个思路正是基于物品的协同过滤(ItemCF)——用「共同被喜欢」来度量物品相似度,再由相似物品的偏好外推到用户身上。
但现实很快给了编辑们一闷棍。城市里有上千家餐厅,每位评论家平均只吃过 30 家,两家餐厅共同出现的次数常常是 0。数据稀疏得像是被晒裂的旱地,到处是窟窿。很多餐厅明明风格类似,却因为没有任何「共现记录」而被判定为「毫无关系」。ItemCF 一族的方法都依赖物品间的共现信息——把用户对物品的交互看成集合,物品 i 和 j 的相似度常写成余弦形式的集合公式:
与其纠结「谁和谁一起被吃过」,不如换一种问法:这家餐厅在「麻辣、甜口、分量、环境、性价比」这几条口味轴线上各得几分?那位评论家又更看重哪些轴线?把两者对齐相乘,就能得到预测分——这正是 LFM 的起点。
- 交集计数分子 $|N(i) \cap N(j)|$ 统计同时与物品 i、j 交互过的用户数,是「共现」的直接证据,类似两家餐厅被同一群评论家都光顾过的次数。
- 分母归一$\sqrt{|N(i)| \cdot |N(j)|}$ 将交集除以两个物品各自流行度的几何平均,避免热门餐厅因为「见过的人多」就在相似度上虚高。
- 稀疏断层当交集为 0 时相似度直接为 0。真实推荐系统中用户-物品交互矩阵的稀疏度普遍超过 99%,大量长尾物品没有任何共现,协同过滤就此失效。
LFM核心原理
假设编辑们决定用 5 条口味轴线来刻画所有餐厅:麻辣接受度、甜口喜爱、分量讲究、环境格调、性价比敏感。每家餐厅在这些轴线上都有自己的表现分(比如这家店麻辣度 9 分、甜口 3 分),每位评论家也有自己的偏好强度(比如小王无辣不欢,麻辣偏好 9 分、甜口 2 分)。当两者「对上眼」,预测评分就是各轴线分相乘再求和。
这套「口味轴线」在算法里叫隐因子(Latent Factor)。说它「隐」,是因为我们不需要人工定义轴线的具体含义——LFM 直接从行为数据中反推轴线。就像我们不必逐一追问评论家「你有多爱吃辣」,只要看他的打分记录,就能自动还原出他在每个隐因子上的位置。形式化地说,LFM 把用户-物品交互矩阵分解成两个低维矩阵的乘积:R ≈ P Qᵀ。P 的每一行是用户 u 的 K 维隐向量 p_u,Q 的每一行是物品 i 的 K 维隐向量 q_i,预测分就是两者的点积:
就像编辑不需要真的设计「什么是麻辣接受度」,算法自动从几千条评论记录里还原出这条轴线上每个人的位置。K 取几十到几百,矩阵被压进一个紧凑的隐空间,这正是 LFM 应对稀疏数据的底气。
- 用户隐向量$\mathbf{p}_u = (p_{u1}, p_{u2}, \dots, p_{uK})$ 表示用户 u 在 K 个隐因子上的偏好强度,相当于评论家的口味画像。
- 物品隐向量$\mathbf{q}_i = (q_{i1}, q_{i2}, \dots, q_{iK})$ 表示物品 i 在 K 个隐因子上的属性表现,相当于餐厅在各口味轴线上的得分。
- 逐维相乘$p_{uk} q_{ik}$ 把用户在维度 k 的偏好与物品在维度 k 的表现对齐相乘,某一条轴线上「偏好 × 表现」越高,贡献越大。
- 累加求和$\sum_{k=1}^{K}$ 把所有维度的乘积加总得到最终预测分。原始交互矩阵需要存 U×I 个位置,LFM 只需存 U×K + I×K 个参数——高维稀疏交互被压缩成低维稠密表示。
负采样策略
现在新难题出现了。评论家们留下的都是「去过哪些店」的正样本,可 LFM 训练需要同时知道「哪些是负样本」。没去过的店有上千家,但「没去」不等于「不喜欢」——可能是没听说过、离家太远,或者只是还没来得及去。如果只拿正样本训练,模型会发现最省力的解是「对所有物品都打高分」,就像学生只背正确答案,考场上永远选「对」。所以必须挑一些「没去过的店」当负样本,逼模型学会区分。
怎么挑?三种主流策略各有利弊。随机采样从没去过的店里均匀抽取,实现最简单,但可能抽到「其实评论家也喜欢、只是还没去」的店,引入噪音,适合冷启动阶段快速跑通基线。热度采样优先抽那些「全城很多人都去过、唯独他没去」的餐厅——如果一家店所有人都打卡了他却从没去过,那大概率是真不喜欢而不是不知道。Word2Vec 的负采样思路正是如此:按热度加权,再用 0.75 次方做软压缩:
第三种难例挖掘(Hard Negative Mining)更聪明:训练中途用当前模型给所有没去过的店打分,把「模型以为他会喜欢、但他没去」的店挑出来当负样本。这就像考试时专挑错题集里的题反复练——模型越容易混淆的样本,学习价值越大。选择哪种策略,要看业务里「没交互」为什么发生:信息流场景「曝光未点击」是天然的高置信负样本;曝光不足的冷启动场景,则要谨慎混合多种策略。
- 物品热度$f(i)$ 表示物品 i 的交互次数(餐厅被光顾的次数),热度越高的物品曝光越充分,「有曝光却没交互」的置信度越高。
- 软压缩指数$f(i)^{0.75}$ 对热度做次方压缩。取 0.75 是为了让热门物品的概率不至于过高,冷门物品也保有被采到的机会。
- 归一化分母$\sum_{j \in I} f(j)^{0.75}$ 把所有候选物品的加权值求和,保证每个物品的采样概率在 0 到 1 之间且总和为 1,构成合法的概率分布。
正负样本比例
训练 LFM 就像做一道菜:正样本是主菜,负样本是调味。盐太少菜没味,调料太多菜齁得慌。正负样本的比例,直接决定这桌菜能不能端上桌。隐式反馈场景下,正样本通常远少于候选负样本——如果比例太小(如 1:50),模型看到的海量负样本会把正样本信号稀释,训练迟迟不收敛;如果比例太大(如 10:1),负样本不足,模型对「不喜欢」的约束太弱,容易给所有物品都打高分。
业界经验是正负比 1:1 到 1:10 是常用区间,短视频场景常用 1:4 到 1:8。除了直接控制采样数量,还可以在损失函数里给负样本加一个权重 α,对负样本的误差做软缩放:
值得强调的是,比例和 α 是一对「双旋钮」:调大负样本数量的同时调小 α,可以稳定训练;反之减少负样本数量时可以把 α 适当调大。主菜和调料的比例,需要厨师(算法工程师)根据模型在验证集上的表现动态调整,而不是抄一个固定配方就走。
- 正样本集合$D^{+}$ 是观测到交互的(用户,物品)对,即评论家真正去过的餐厅,主菜部分。
- 预测误差$e_{ui} = r_{ui} - \hat{r}_{ui}$,真实交互值(1 或 0)与模型预测分的差,误差大说明模型在该样本上判断失准。
- 负样本权重$\alpha$ 通常取 0.1 到 1.0,α 越小负样本对总损失的贡献越弱,训练越偏重正样本信号;α 越大模型越 aggressively 学习「不喜欢」的边界。
采样实践指南
好的厨师不会照本宣科,而是根据食材状态动态调整火候。负采样也一样,工业界落地时有一组经验性「手感」——热度加权的 0.75 指数来自身经百战的调参智慧。指数取 1.0 时热门物品垄断采样,模型几乎只学「热门不爱」而忽略长尾;取 0 时退化为均匀随机采样,冷门物品的噪音被放大。实际业务里可在 0.5 到 0.85 之间做小范围网格搜索。
训练过程中负样本的配置也应当是动态的。训练早期,模型还很「无知」,大量热度采样能快速建立基础判别力;训练后期,模型已经能分清大部分易分样本,此时应减少负样本数量或逐步衰减负样本权重,让模型从「大量学习边界」过渡到「精调」。工业界主流的混合策略是热度采样为主、难例挖掘为辅,例如 80% 负样本来自热度采样、20% 来自难例挖掘:
工程上还有两个常用技巧:热度采样的概率分布变化慢,可以预先算好缓存起来;难例挖掘的模型分数变化快,需要每隔 N 个 batch 重算一次。另外推荐用「曝光未点击」作为负样本来源,比全局未交互干净得多——这相当于只从「评论家确实看到过却没进去」的店里选,噪音小一大截。
- 热度基座$\beta \cdot \frac{f(i)^{0.75}}{\sum_{j} f(j)^{0.75}}$ 用热度采样保证基础覆盖,参数 β 控制「普遍性」的权重。
- 难例增量$(1 - \beta) \cdot P_{hard}(i)$ 用难例挖掘补充边界信息,把模型当前最易混淆的样本混进训练。
- 典型配比β 通常取 0.7 到 0.9,即 70% 到 90% 的负样本来自热度采样,其余来自难例挖掘。热度采样保证收敛稳定,难例挖掘提升判别锐度。
模型优化训练
现在参数有了、损失有了,该怎么调?用随机梯度下降(SGD)——每次拿一个「评论家-餐厅」对,算出预测误差,然后轻轻推动用户向量和物品向量向误差减小的方向走一小步。步子的大小叫学习率,推的时候还要稍微往回拽一点(正则化),防止参数乱飞。LFM 的损失函数是平方误差加 L2 正则,SGD 的更新规则如下:
SGD 按样本逐条更新,天然适合流式数据。训练时每个 epoch 遍历一遍用户及其采样出的正负样本,交替刷新 P 和 Q 两个矩阵,直到验证集上的评估指标(如 AUC、Hit@K)不再提升即提前终止。就像评论家不断去新餐厅试菜、微调自己的口味认知——最终,每个人和每家店都在隐空间里找到了自己的坐标,推荐也就水到渠成。
- 预测误差$e_{ui} = r_{ui} - \hat{r}_{ui}$,真实交互值与预测分的差,驱动的方向来源。
- 梯度方向$e_{ui} q_i$ 和 $e_{ui} p_u$ 分别给出用户向量、物品向量应移动的方向——误差乘以对方向量,相当于把「对方的特征」按误差大小搬到自己身上。
- 学习率$\eta$ 控制移动步长。太大导致震荡无法收敛,太小收敛缓慢,常用 0.001 到 0.05 之间。
- 正则化回拽$-\lambda p_u$ 和 $-\lambda q_i$ 将参数向 0 微缩,防止模型在训练集上过度拟合,λ 常用 0.001 到 0.1。
AI 应用场景
短视频推荐召回
阶段:召回阶段(模型训练 → 向量召回)
解决的问题:短视频场景只有「播放/未播放」的隐式信号,没有显式评分。LFM 把用户和视频映射到同一隐因子空间,用内积计算相关性做向量召回。负样本从「曝光但未被点击/播放时长过短」的日志中采样,代替全局随机采样,大幅降低「没看到 ≠ 不喜欢」的噪音。
具体案例:某资讯类 App 在召回阶段用 LFM + 热度采样负样本(正负比 1:5)替代 ItemCF 后,Hit@100 提升 11%,长尾视频曝光量显著上升。难例挖掘被用于每周一次的全量重算,进一步优化了用户兴趣边界。
电商「猜你喜欢」混合采样
阶段:召回/粗排阶段的离线训练
解决的问题:电商场景正样本是「点击/加购/购买」,负样本若全用热度采样会让模型对「高曝光低点击」的商品过度惩罚;若全用难例挖掘则训练不稳定。用 80% 热度 + 20% 难例的混合策略,兼顾收敛速度与判别精度。
具体案例:某电商平台的「猜你喜欢」频道,把负样本池改为「曝光未点击 + 部分加购未购买」,并配比 α=0.3 的负样本权重,下单转化率提升约 6%,同时训练 epoch 数降低了 1/3。
招聘平台职位推荐
阶段:召回模型离线训练与线上 A/B 验证
解决的问题:求职者对职位的反馈高度稀疏,投递行为极少。LFM 将求职者与职位映射到技能需求、薪资期望、行业偏好等隐因子空间;负样本从「展示了职位但未点击投递」中采样,并用难例挖掘强化「看起来匹配但实际不投」的边界。
具体案例:某招聘平台用 LFM + 曝光未点击负样本替换规则匹配后,投递转化率提升 9%。负采样比例从 1:1 到 1:8 做了网格搜索,最终选定 1:4 配合 α=0.5。
Python 演示
import numpy as np def make_data(users=200, items=100, k=5, seed=42): """构造隐式反馈矩阵与物品热度:真实隐因子内积生成评分,取高分为交互""" rng = np.random.default_rng(seed) P = rng.normal(size=(users, k)) Q = rng.normal(size=(items, k)) score = P @ Q.T inter = (score > np.percentile(score, 90)).astype(float) item_pop = inter.sum(axis=0) return inter, item_pop class LFMTrainer: """隐语义模型:矩阵分解 + 负采样 SGD 训练""" def __init__(self, k=8, lr=0.02, reg=0.01, epochs=3, neg_alpha=1.0): self.k = k self.lr = lr self.reg = reg self.epochs = epochs self.neg_alpha = neg_alpha self.user_vec = None self.item_vec = None def fit(self, train, item_pop, negs=4, strategy="random", seed=0): users, items = train.shape rng = np.random.default_rng(seed) self.user_vec = rng.normal(scale=0.1, size=(users, self.k)) self.item_vec = rng.normal(scale=0.1, size=(items, self.k)) for _ in range(self.epochs): for u in range(users): pos_idx = np.where(train[u] == 1)[0] if pos_idx.size == 0: continue neg_pool = np.where(train[u] == 0)[0] if neg_pool.size == 0: continue if strategy == "random": prob = np.ones(neg_pool.size) elif strategy == "popularity": prob = item_pop[neg_pool] ** 0.75 else: prob = np.exp(self.user_vec[u] @ self.item_vec[neg_pool].T) prob = np.maximum(prob, 1e-9) prob = prob / prob.sum() neg_idx = rng.choice(neg_pool.size, size=min(negs, neg_pool.size), replace=False, p=prob) for i in pos_idx: self._update(u, i, 1.0, 1.0) for n in neg_idx: self._update(u, neg_pool[n], 0.0, self.neg_alpha) return self def _update(self, u, i, target, weight): err = target - self.user_vec[u] @ self.item_vec[i] self.user_vec[u] += self.lr * (weight * err * self.item_vec[i] - self.reg * self.user_vec[u]) self.item_vec[i] += self.lr * (weight * err * self.user_vec[u] - self.reg * self.item_vec[i]) def hit_rate(self, test, top_k=10): hits = 0 total = 0 for u in range(test.shape[0]): pos = np.where(test[u] == 1)[0] if pos.size == 0: continue total += 1 pred = self.user_vec[u] @ self.item_vec.T top = np.argsort(pred)[::-1][:top_k] if np.intersect1d(top, pos).size > 0: hits += 1 return hits / total def run(): inter, item_pop = make_data() rng = np.random.default_rng(7) test_mask = np.zeros_like(inter) pos_ids = np.argwhere(inter == 1) chosen = rng.choice(pos_ids.shape[0], size=int(pos_ids.shape[0] * 0.2), replace=False) for idx in chosen: test_mask[tuple(pos_ids[idx])] = 1 train = inter - test_mask for strategy in ["random", "popularity", "hard"]: model = LFMTrainer() model.fit(train, item_pop, strategy=strategy) print(strategy, "hit@10 =", round(model.hit_rate(test_mask) * 100, 2), "%") if __name__ == "__main__": run()
inter = (score > np.percentile(score, 90)).astype(float)把连续打分按 90 分位截断为 0/1 隐式反馈,模拟「去了/没去」prob = item_pop[neg_pool] ** 0.75热度采样的核心:热度 0.75 次方软压缩,热门但用户未交互的物品更易被选中prob = np.exp(self.user_vec[u] @ self.item_vec[neg_pool].T)难例挖掘:用当前模型给所有未交互物品打分取指数,避免负数rng.choice(neg_pool.size, size=min(negs, neg_pool.size), replace=False, p=prob)按概率分布无放回采样负样本self._update(u, i, 1.0, 1.0)正样本以权重 1 做误差回传self._update(u, neg_pool[n], 0.0, self.neg_alpha)负样本以 α 加权,目标值为 0err = target - self.user_vec[u] @ self.item_vec[i]计算当前样本的预测误差self.user_vec[u] += self.lr * (...)SGD 更新用户向量,正则项防止过拟合test_mask[tuple(pos_ids[idx])] = 1随机 mask 掉 20% 正样本做测试集,模拟真实评估
常见误区
误区用户没买过、没点过的东西都可以直接当负样本,负样本越多模型学得越充分。
正解未交互 ≠ 不喜欢。可能是没曝光、没注意、或者还没下定决心。把海量未交互数据全部当负样本,不仅让模型学到「没曝光 = 不喜欢」的系统性偏差,还会带来巨大的训练开销。负采样的本质就是从巨大的候选池里挑出「真正有信息量」的样本,而不是囫囵吞枣。
为何常见:直觉上「没有正反馈就是负反馈」,忽略了隐式反馈中「缺失」是多义信号——没去那家餐厅,可能只是因为它没出现在评论家眼前。
误区负样本多多益善,把正负比拉到 1:100,模型见过的反例多,边界应该更清晰。
正解比例过大会让负样本淹没正样本,模型严重偏向「预测为负」,召回率反而下降;同时训练时间变长、梯度被大量易分负样本占据,收敛变慢。常用区间是 1:1 到 1:10,并配合负样本权重 α 做软控制。做菜时盐放太多,菜反而咸得没法入口。
为何常见:把「反例越多越鲁棒」的分类任务直觉迁移到推荐场景,没意识到隐式反馈的正样本本就已经很稀疏、且负样本质量参差。
误区反正是负样本,随机抽一批就行,popularity 和难例挖掘的收益不明显,还增加实现成本。
正解随机采样会抽到大量「和用户毫无关系」的易分样本,这些样本的梯度接近零,学习效率极低。热度采样和难例挖掘能显著加快收敛、提升最终效果——尤其在曝光充足的场景,差别可能达到几个点的 Hit@K。随机采样只适合冷启动阶段的基线。
为何常见:初期实现成本低,线上 A/B 差异不够显著时,容易被「反正差别不大」的错觉误导。
误区模型最困惑的样本最有价值,那负样本全部用难例,模型应该进步最快。
正解难例比例过高会让训练不稳定甚至「矫枉过正」——模型被反复用最难样本逼到墙角,容易震荡;而且难例里常混入「伪负例」(用户其实喜欢,只是没曝光),放大了噪音。一般控制难例在负样本总量的 10%~30%,与热度采样配合使用。错题集要刷,但不能只刷错题。
为何常见:把「难例」与「信息量」画等号,忽略了过度惩罚的副作用和伪负例的存在。
面试题
Q1. LFM 与 ItemCF 的本质区别是什么?
- A.LFM 直接比较物品的共现关系
- B.用低维隐向量表达用户与物品← 正确答案
- C.LFM 不需要用户的交互数据
- D.用规则匹配用户与物品属性
答案:B。LFM 用 K 维隐因子向量分别刻画用户和物品,预测分由点积算出,不依赖显式共现关系。A 是 ItemCF 的做法;C 错,LFM 恰恰需要交互数据反推隐向量;D 说的是规则/画像方法。把「共现比较」换成「隐向量点积」,正是协同过滤进化的关键一步。
Q2. 隐式反馈场景中,下列哪项最适合作为正样本?
- A.用户浏览过但未点击的商品
- B.用户点击并停留较久的商品← 正确答案
- C.从未曝光给用户的商品
- D.系统随机生成的商品样本
答案:B。正样本应是「用户真实表达偏好」的行为。点击且停留较久说明用户感兴趣;仅浏览未点击信号太弱,未曝光和随机生成根本不是真实行为,不能作为正样本。就像美食评论:只有真正坐下吃完并给出好评的店,才配叫「喜欢」。
Q3. 关于负采样策略,正确的说法有哪些?
- A.随机采样实现简单但有噪音← 正确答案
- B.热度采样偏向热门物品← 正确答案
- C.难例挖掘可以提升判别边界← 正确答案
- D.三种策略的效果完全相同
答案:ABC。随机采样把「没去过」一律当不喜欢,可能选到用户其实喜欢的店,所以有噪音(A 对);热度采样优先挑热门但用户没交互的物品(B 对);难例挖掘专挑模型当前最易混淆的负样本,能显著改善边界(C 对);D 显然错误,三种策略在不同数据分布下效果差异明显。
Q4. 正负样本比例通常取什么范围较稳妥?
- A.1:0.1 到 1:0.5
- B.1:1 到 1:10← 正确答案
- C.1:50 到 1:100
- D.1:1000 以上
答案:B。负样本太少(A)模型学不到「不喜欢」;太多(C、D)正样本信号被稀释、训练不稳定,还带来额外计算开销。业界经验是 1:1 到 1:10,再配合负样本权重 α 微调。就像做菜时盐的用量在稳定区间内,太多太少都毁掉整道菜。
Q5. LFM 中用户 u 对物品 i 的预测分如何计算?
- A.用户向量与物品向量做点积← 正确答案
- B.用户向量与物品向量取最大值
- C.用户与物品的共现次数
- D.物品热度的加权平均
答案:A。LFM 假设预测分是用户隐向量 p_u 与物品隐向量 q_i 的点积,即逐维相乘再求和。B、C、D 都不符合矩阵分解的定义。点积让「用户偏好」和「物品属性」在同一隐因子维度上对齐,就像口味偏好分与餐厅口味分相乘累加得到匹配度。
Q6. 难例挖掘可能带来的副作用有哪些?
- A.伪负例噪音被放大← 正确答案
- B.训练稳定性下降← 正确答案
- C.长尾物品被过度压制← 正确答案
- D.模型不再需要负样本
答案:ABC。难例挖掘选「模型以为用户喜欢但没交互」的样本,其中可能混入「用户其实喜欢只是没曝光」的伪负例,A 对;高难样本占比过高会让梯度震荡、训练不稳,B 对;热门难例被反复惩罚会挤占长尾物品的学习空间,C 对;D 荒谬,任何有监督训练都需要负样本。
Q7. 为什么不能把全部未交互数据都当作负样本?
- A.未交互不等于用户不喜欢← 正确答案
- B.正样本的数量会因此变少
- C.模型训练速度会明显变快
- D.所有物品都会得到推荐
答案:A。隐式反馈中「没交互」可能源于没曝光、没留意或没来得及,不等于负向偏好。全部拿来当负样本不仅让模型学偏,还产生海量训练对。这正是负采样存在的意义——从巨大候选池里挑出真正有信息量的负样本,而非照单全收。
Q8. LFM 的 SGD 更新过程中涉及哪些要素?
- A.学习率控制步长← 正确答案
- B.预测误差驱动方向← 正确答案
- C.正则项防止过拟合← 正确答案
- D.物品发布时间决定顺序
答案:ABC。SGD 更新公式里,误差 e_ui 提供梯度方向,学习率 η 控制步长,正则项 λ 把参数往回拽,所以 A、B、C 都对。物品发布时间属于上下文特征,虽然可作为特征使用,但不是 SGD 更新公式的组成要素。
Q9. Word2Vec 负采样中的热度指数 0.75 主要作用是什么?
- A.提高热门物品的采样概率
- B.软压缩热度以平衡采样分布← 正确答案
- C.让所有物品采样概率完全相等
- D.完全消除热门物品的采样影响
答案:B。0.75 次方是对热度做「软压缩」:热门物品的概率被压得没那么高,冷门物品也保有采样机会,在采样分布与均匀分布之间取得平衡。A 只说了表面——提高热门不是目的,平衡才是;C、D 与指数调节的初衷相悖。0.75 是经验值,实际可在 0.5~0.85 调优。
Q10. 混合采样中「热度为主、难例为辅」的典型配比是?
- A.约 80% 热度采样加 20% 难例← 正确答案
- B.约 20% 热度采样加 80% 难例
- C.约 50% 热度采样加 50% 难例
- D.约 100% 难例且无热度采样
答案:A。工业界常用热度采样保证基础收敛、难例挖掘提升判别边界,配比多取 7:3 到 9:1,因此 80/20 是典型值。B 中难例占比过高会引入过多伪负例与震荡;C 对等配比难以兼顾稳定与锐度;D 完全放弃热度采样,过拟合风险高。