正负样本比例不平衡
之前的一个ctr预测任务,数据集正负样本比例达到惊人的1:64,导致acc很高但是auc低,因为模型倾向于将样本判负,负样本多,都预测为负值自然acc高。
belike:
[W1]Epoch1:loss=0.7100acc=0.4700auc=0.5534gauc=0.5104[W1]Epoch2:loss=0.6931acc=0.5149auc=0.6044gauc=0.5183[W1]Epoch3:loss=0.6818acc=0.6062auc=0.6424gauc=0.5336[W1]Epoch4:loss=0.6734acc=0.6955auc=0.6647gauc=0.5457[W1]Epoch5:loss=0.6659acc=0.7706auc=0.6781gauc=0.5525[W1]Epoch6:loss=0.6540acc=0.8560auc=0.6905gauc=0.5627[W1]Epoch7:loss=0.6375acc=0.9189auc=0.6984gauc=0.5677[W1]Epoch8:loss=0.6195acc=0.9509auc=0.7025gauc=0.5727优化思路:
一、调整正负样本比例
也就是对负样本进行采样:按时间or用户随机采样;采样困难负样本;其他根据实际任务的采样策略等。
但是做这种任务时,总是“不舍得”为数不多的数据,总想着将所有数据都用上。
二、调整正负样本对梯度的贡献比例
分析:CTR任务的损失函数一般是BCE,换种不等价但是直观的理解方式就是ACC准确率。如果一个batch内有63个负样本1个正样本,只需要将样本全部预测为负,ACC就会很高。所以,样本不均衡造成的问题是梯度被负样本淹没,梯度将向着“将样本预测为负”的方向优化。
解决思路:既然是正样本对梯度的贡献太小,那么提高正样本的贡献权重。
1. balance ce loss,即加权BCE
标准 BCE(二元交叉熵)的公式:
LBCE(y,p)=−[y⋅log(p)+(1−y)⋅log(1−p)]\mathcal{L}_{\text{BCE}}(y, p) = - \big[ y \cdot \log(p) + (1 - y) \cdot \log(1 - p) \big]LBCE(y,p)=−[y⋅log(p)+(1−y)⋅log(1−p)]
对于一个批次(batch)的 ( N ) 个样本,平均损失为:
LBCE=−1N∑i=1N[yi⋅log(pi)+(1−yi)⋅log(1−pi)]\mathcal{L}_{\text{BCE}} = -\frac{1}{N} \sum_{i=1}^{N} \big[ y_i \cdot \log(p_i) + (1 - y_i) \cdot \log(1 - p_i) \big]LBCE=−N1i=1∑N[yi⋅log(pi)+(1−yi)⋅log(1−pi)]
对于正负样本比例1:64的1 batch数据,将正样本的loss乘权重64,模型优化时每看到一个正样本,它的梯度贡献等价于看到 64个负样本——刚好抵消数据中的比例失衡。
即:LBCE(y,p)=−[α⋅log(p)+(1−y)⋅log(1−p)]\mathcal{L}_{\text{BCE}}(y, p) = - \big[\alpha \cdot \log(p) + (1 - y) \cdot \log(1 - p) \big]LBCE(y,p)=−[α⋅log(p)+(1−y)⋅log(1−p)],其中α=正样本/负样本\alpha = 正样本/负样本α=正样本/负样本
注意:此公式是一种简单情况下的简化,更通用的是log§乘α,log(1 - p) 乘1-α,
(1−α)/α = 正样本/负样本 ,m为正样本数,n为负样本数。
2. Focal loss,即动态调整困难样本的权重
通过修改标准的交叉熵损失函数,降低对能够很好分类样本的权重(down-weights the loss assigned to well-classified examples),解决类别不均衡问题.
# p_t: 正确类别的预测概率 p_t = p * y_true + (1 - p) * (1 - y_true) # [B, 1] # alpha_t: 类别权重 alpha_t = alpha * y_true + (1 - alpha) * (1 - y_true) # [B, 1] # Focal Loss ce = F.binary_cross_entropy_with_logits(logits, y_true, reduction='none') fl = alpha_t * (1 - p_t) ** gamma * ce