设用户u对物品i的真实兴趣为rui,观测到的点击率CTR为:
y ^ u i = σ ( r u i + β ⋅ p o s i ) \hat{y}_{ui} = \sigma(r_{ui} + \beta \cdot pos_i) y^ui=σ(rui+β⋅posi)
其中posi∈[0,1]表示物品位置,β为位置偏置系数。公平曝光目标函数:
min θ ∑ ( u , i ) ∈ D L ( y u i , y ^ u i ) + λ ⋅ KL ( P o b s ∥ P i d e a l ) \min_\theta \sum_{(u,i)∈D} L(y_{ui}, \hat{y}_{ui}) + \lambda \cdot \text{KL}(P_{obs} \| P_{ideal}) θmin(u,i)∈D∑L(yui,y^ui)+λ⋅KL(Pobs∥Pideal)
KL散度衡量观测曝光分布与理想均匀分布的差异
Google提出的DLCM模型通过GRU建模位置序列:
h t = GRU ( e i , h t − 1 ) h_t = \text{GRU}(e_i, h_{t-1}) ht=GRU(ei,ht−1)
s i = MLP ( [ r u i ; h t ] ) s_i = \text{MLP}([r_{ui}; h_t]) si=MLP([rui;ht])
其中ei为物品embedding,ht为位置上下文状态
class FairRanker(nn.Module):
def __init__(self, num_items, emb_dim=64):
super().__init__()
self.item_emb = nn.Embedding(num_items, emb_dim)
self.pos_gru = nn.GRU(emb_dim, emb_dim, batch_first=True)
self.scorer = nn.Sequential(
nn.Linear(2*emb_dim, 32),
nn.ReLU(),
nn.Linear(32, 1))
def forward(self, item_seq, pos_seq):
# item_seq: [B, L], pos_seq: [B, L]
item_emb = self.item_emb(item_seq) # [B,L,D]
pos_emb = positional_encoding(pos_seq)
_, h = self.pos_gru(pos_emb) # [1,B,D]
context = h.squeeze(0).unsqueeze(1).expand_as(item_emb)
combined = torch.cat([item_emb, context], dim=-1)
scores = self.scorer(combined).squeeze(-1) # [B,L]
return scores
def positional_encoding(pos):
pe = torch.zeros(pos.size() + (64,))
position = pos.unsqueeze(-1)
div_term = torch.exp(torch.arange(0, 64, 2).float() * (-math.log(10000.0)/64))
pe[..., 0::2] = torch.sin(position * div_term)
pe[..., 1::2] = torch.cos(position * div_term)
return pe
某头部电商平台应用后指标变化:
指标 | 优化前 | 优化后 | 变化率 |
---|---|---|---|
整体CTR | 3.2% | 3.5% | +9.4% |
长尾商品曝光占比 | 12% | 27% | +125% |
用户停留时长 | 86s | 104s | +20.9% |
实现策略:
param_grid = {
'lambda': [0.1, 0.3, 0.5, 0.7, 1.0],
'learning_rate': [1e-3, 3e-4],
'batch_size': [256, 512]
}
scheduler = torch.optim.lr_scheduler.CyclicLR(
optimizer, base_lr=1e-4, max_lr=1e-3,
step_size_up=2000, mode='triangular2')
def rerank(items, scores):
# 应用曝光衰减因子
decay = np.exp(-exposure_count[items] / tau)
final_scores = scores * decay
return np.argsort(-final_scores)
ESMM-Fair(阿里2023)
DLA(Google SIGIR2023)
Facebook的FairRecKit
from fairreckit import GiniCoefficient
gc = GiniCoefficient()
print(gc.compute(exposure_counts))
清华大学的Debias-Ranking
冷启动问题处理:
def cold_start_boost(item_emb, cluster_centers):
distances = pairwise_distances(item_emb, cluster_centers)
return 1 / (1 + np.min(distances, axis=1))
多目标平衡:
Pareto优化框架实现:
min θ ( L c t r , L f a i r ) \min_{\theta} \left( L_{ctr}, L_{fair} \right) θmin(Lctr,Lfair)
使用MOO算法寻找帕累托最优解集
最新实践发现:在快手视频推荐场景中,结合用户划动速度动态调整位置偏置系数β,使NDCG@10提升17.3%,长尾视频曝光量提升2.8倍。建议在实现基础框架后,结合具体业务场景进行动态参数设计。