搜广推面经九十八
阿里国际・搜索广告算法
一、如何避免特征之间的多重共线性,避免了又会有什么缺点
1.1. 计算相关系数矩阵(如皮尔逊相关系数)
- 使用
np.corrcoef或pandas.corr()找出高度相关(如 > 0.9)的特征对 - 删除其中一个冗余特征或合并(如取平均)
1.2. 方差膨胀因子(VIF: Variance Inflation Factor)
VIF > 5或VIF > 10通常认为存在共线性,可使用statsmodels工具包计算:
from statsmodels.stats.outliers_influence import variance_inflation_factor
vif = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
1.3. 主成分分析(PCA)或线性降维
通过线性变换将数据投影到方差最大的方向,得到一组不相关的主成分
1.4. L1 正则化(Lasso)
自动进行特征选择,将一些权重为零
1.5. 可能存在的缺点
- 信息损失:删除/合并特征可能丢掉对预测有帮助的微弱信号
- 模型可解释性下降:如 PCA 后主成分难以直接解释
- 泛化能力不一定提高:在部分深度模型中,共线性未必严重影响性能
二、XGBoost 是如何处理缺失值的?
XGBoost 在建模时具有内建的 缺失值处理机制,它不需要用户显式填补缺失值(如用均值、中位数等填充),而是通过以下方式自动处理:
2.1. 原理
在构建每棵树时,对于每一个分裂节点,XGBoost 会自动学习一个默认方向(default direction) 来处理缺失值。
👉 即:
- 对于一个特征的某个分裂点(如 x ≤ t),
- 如果某个样本该特征为缺失(NaN),模型会判断:
- 让缺失样本走左子树更好,还是右子树更好?
- 这个“更好”是通过提升后的 损失函数增益(Gain)最大化 来判断的。最终每个特征的每个节点,都会记录一个 缺失值应该走向哪一边 的默认路径。
2.2. 特点
- 无需预处理:原始数据中保留 NaN 即可。
- 每个节点独立学习缺失分支:不同树、不同特征、不同位置的缺失值走向可能不同。
- 自动化、优化后的处理:提升精度同时降低人工处理成本。
三、说一下NCELoss和Sample softmaxloss的区别,Sample softmaxloss的消偏是怎么做的?
3.1. 背景:为何需要采样?
在 大词表/大类别推荐场景 中,全量 softmax 计算代价高昂(需计算所有类别得分并归一化),因此引入 负采样损失(Negative Sampling)。
3.2. NCELoss(Noise Contrastive Estimation Loss)
3.2.1. 原理:
NCE 把多分类任务转换为二分类任务:
目标:区分真实样本(positive)和从噪声分布中采样的负样本(noise)
- 假设词表大小为 VVV,采样 kkk 个负样本 y1,...,yky_1,...,y_ky1,...,yk 来近似 softmax
- 模型学习一个 判别器:
P(D=1∣x,y)=Pdata(y∣x)Pdata(y∣x)+k⋅Pn(y) P(D = 1 | x, y) = \frac{P_{\text{data}}(y|x)}{P_{\text{data}}(y|x) + k \cdot P_n(y)} P(D=1∣x,y)=Pdata(y∣x)+k⋅Pn(y)Pdata(y∣x)
其中:- Pn(y)P_n(y)Pn(y):负样本的采样分布(通常为 unigram 或 log-unigram)
- 使用 logistic regression 对 D∈{0,1}D \in \{0, 1\}D∈{0,1} 做分类
3.2.2. 缺点:
- 目标函数是逼近 data distribution,而非逼近 softmax 概率
- 训练和推理目标不一致(train for classification, infer for softmax)
3.3. NCELoss 伪代码(Noise Contrastive Estimation)
for (x, y_true) in dataset:
# 1. 正样本打分
s_pos = dot(embedding(x), embedding(y_true))
# 2. 采样 k 个负样本 y_neg_i ~ P_n(y)
y_neg_samples = sample_k_negatives(k)
# 3. 计算负样本打分
s_negs = [dot(embedding(x), embedding(y_neg)) for y_neg in y_neg_samples]
# 4. 合并打分
logits = [s_pos] + s_negs
labels = [1] + [0] * k # 正样本为1,其余为0
# 5. 二分类损失(二元交叉熵)
loss = binary_cross_entropy(logits, labels)
3.4. Sampled Softmax Loss(带偏差校正的采样 softmax)
3.4.1. 原理:
Sampled Softmax Loss 是 softmax 的近似形式,通过采样负类减少计算,但仍近似原始 softmax:
Softmax(y∣x)=exp(sy)∑y′∈Vexp(sy′)≈exp(sy)exp(sy)+∑y′∈Nexp(sy′) \text{Softmax}(y|x) = \frac{\exp(s_y)}{\sum_{y' \in \mathcal{V}} \exp(s_{y'})} \quad \approx \quad \frac{\exp(s_y)}{\exp(s_y) + \sum_{y' \in \mathcal{N}} \exp(s_{y'})} Softmax(y∣x)=∑y′∈Vexp(sy′)exp(sy)≈exp(sy)+∑y′∈Nexp(sy′)exp(sy)
- N\mathcal{N}N:采样的一小部分负类
- sy=logit(x,y)s_y = \text{logit}(x, y)sy=logit(x,y)
3.5. 为什么要校正?
采样的负样本分布 q(y)q(y)q(y) 往往与真实 softmax 分布差异很大,导致偏差。
对 logits 加上 采样分布的概率校正项,即对每个负样本:
s~y=sy−logq(y) \tilde{s}_y = s_y - \log q(y) s~y=sy−logq(y)
其中 q(y)q(y)q(y) 是采样概率。
最终 softmax:
softmax(y∣x)=exp(sy−logq(y))∑y′∈pos∪negexp(sy′−logq(y′)) \text{softmax}(y|x) = \frac{\exp(s_y - \log q(y))}{\sum_{y' \in \text{pos} \cup \text{neg}} \exp(s_{y'} - \log q(y'))} softmax(y∣x)=∑y′∈pos∪negexp(sy′−logq(y′))exp(sy−logq(y))
这个校正项使得采样 softmax 在理论上更加逼近全量 softmax。
3.6. Sampled Softmax Loss 伪代码
逼近原始 softmax,校正采样偏差
for (x, y_true) in dataset:
# 1. 正样本打分
s_pos = dot(embedding(x), embedding(y_true))
# 2. 采样 k 个负样本 y_neg_i ~ q(y)
y_neg_samples = sample_k_negatives(k)
# 3. 所有样本合并(正 + 负)
all_y = [y_true] + y_neg_samples
# 4. 计算 logits
logits = []
for y in all_y:
score = dot(embedding(x), embedding(y))
bias_correction = -log(q(y)) # 消偏修正
logits.append(score + bias_correction)
# 5. 构造标签
labels = [0] # 正样本在第0位
# 6. 交叉熵损失(对 softmax 分布)
loss = softmax_cross_entropy(logits, labels)
3.6.1. q(y) 的计算和作用
在 Sampled Softmax Loss 中的 q(y) 是负样本采样分布(noise distribution),用来表示采样负样本的概率。它是消偏(bias correction)时用到的关键量。
-
定义:q(y) 是从类别空间中采样负样本 y 的概率。
-
一般取法:
- 基于 unigram 频率:用训练集中类别 y 出现的频率作为 q(y),即:
q(y)=count(y)/totalcount q(y) = count(y) / total_count q(y)=count(y)/totalcount - 平滑频率:为了避免频率过小或过大,一般做幂平滑(power smoothing):
q(y)=(count(y))α/sumi(count(i))α q(y) = (count(y))^α / sum_i (count(i))^α q(y)=(count(y))α/sumi(count(i))α
其中 α ∈ (0,1),例如 0.75,是常见的平滑指数。
- 基于 unigram 频率:用训练集中类别 y 出现的频率作为 q(y),即:
-
作用:
- 负采样时依据 q(y) 采样负样本,越频繁的类别被采样概率越高。
- 在 Sampled Softmax Loss 中,logits 需要减去
log q(y)做偏差校正,避免采样偏差影响模型学习。
3.7. 总结对比
| 项目 | NCELoss | Sampled Softmax Loss |
|---|---|---|
| 本质 | 分类任务(正 vs 负) | Softmax 近似 |
| 是否校正偏差 | ❌ 否(拟合二分类目标) | ✅ 是(log 采样概率校正) |
| 推理一致性 | ❌ 不一致 | ✅ 一致(训练/推理) |
| 采样分布要求 | 灵活 | 需明确估计 q(y)q(y)q(y) |
- NCELoss 多用于 word2vec、representation learning 等 embedding 学习场景
- Sampled Softmax 多用于大规模分类任务、推荐系统中的点击预测或召回任务中
四、如何利用计算机求π,不限时间复杂度,可以循环一亿次
4.1. 莱布尼茨级数(Leibniz series)
π=4∗(1−1/3+1/5−1/7+1/9−...)π = 4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 - ... )π=4∗(1−1/3+1/5−1/7+1/9−...)
pi = 0.0
sign = 1
for k in range(100_000_000):
pi += sign / (2 * k + 1)
sign = -sign
pi *= 4
4.2. 蒙特卡罗方法(Monte Carlo)
利用几何概率:在边长为1的正方形中随机采点,点落在内切圆内的概率是 π/4。
import random
inside = 0
total = 100_000_000
for _ in range(total):
x = random.random()
y = random.random()
if x * x + y * y <= 1:
inside += 1
pi = 4 * inside / total
print(f"Estimated π: {pi}")
更多推荐


所有评论(0)