双塔模型学习

双塔模型概述


双塔模型是什么?

双塔模型是推荐系统中的一种经典结构,它的核心思想是用户和物品的特征分开处理。就像两个人各拿一个望远镜观察不同方向:

  • 用户塔:专注分析用户的兴趣(如年龄、历史行为)
  • 物品塔:专注提取物品的特征(如标题、价格)
    两个塔最终输出低维向量,通过向量相似度计算匹配度

为什么需要双塔模型?

  1. 解耦处理:用户和物品特征维度/类型差异大,分开建模更灵活
  2. 高效检索:向量化后可用近似最近邻搜索(ANN),解决百万级物品实时匹配
  3. 可扩展性:用户塔和物品塔能独立更新,适合用户兴趣快速变化的场景

基本原理三步走

  1. 特征分治:用户特征扔进用户塔,物品特征扔进物品塔
  2. 向量化映射:两个塔输出维度相同的向量(如128维)
  3. 相似度计算:用户向量和物品向量做内积/余弦相似度,得分高则推荐

举个栗子:
当你在淘宝搜索「运动鞋」,你的浏览历史(用户塔)会输出[0.3, -0.5, 2.1,...],某个耐克鞋(物品塔)输出[0.2, -0.4, 2.0,...],两者相似度极高→系统推荐这双鞋。


关键优势

  • :预先计算物品向量,线上只需算1次用户向量
  • :用户塔和物品塔可共享模型参数
  • :解决新物品冷启动(仅需物品塔处理新品特征)

一句话总结:双塔就像相亲介绍所,把用户需求和对象条件拆开分析,最后撮合最匹配的两人


六、双塔模型与交叉熵损失理论详解

6.1 双塔模型数学本质

6.1.1 模型基础形式

设用户特征空间为 U ⊆ R d u \mathcal{U} \subseteq \mathbb{R}^{d_u} URdu,物品特征空间为 V ⊆ R d v \mathcal{V} \subseteq \mathbb{R}^{d_v} VRdv,双塔模型建立两个映射函数:
f θ : U → R k ( 用户塔 ) g ϕ : V → R k ( 物品塔 ) \begin{aligned} f_{\theta}: \mathcal{U} \to \mathbb{R}^k \quad &(\text{用户塔}) \\ g_{\phi}: \mathcal{V} \to \mathbb{R}^k \quad &(\text{物品塔}) \end{aligned} fθ:URkgϕ:VRk(用户塔)(物品塔)
相似度计算定义为内积形式:
s ( u , v ) = ⟨ f θ ( u ) , g ϕ ( v ) ⟩ s(u,v) = \langle f_{\theta}(u), g_{\phi}(v) \rangle s(u,v)=fθ(u),gϕ(v)⟩

6.1.2 概率解释

通过softmax转化后验概率:
p ( v ∣ u ) = exp ⁡ ( s ( u , v ) / τ ) ∑ v ′ ∈ V exp ⁡ ( s ( u , v ′ ) / τ ) p(v|u) = \frac{\exp(s(u,v)/\tau)}{\sum_{v'\in \mathcal{V}}\exp(s(u,v')/\tau)} p(vu)=vVexp(s(u,v)/τ)exp(s(u,v)/τ)
其中 τ \tau τ 为温度系数,控制概率分布陡峭程度

理论意义:此建模方式等价于隐含假设用户-物品交互服从多项分布,温度系数调节对困难样本的关注度


6.2 交叉熵损失的理论推导

6.2.1 基础形式

给定正样本对 ( u , v + ) (u,v^+) (u,v+) 和负样本 { v i − } i = 1 N \{v_i^-\}_{i=1}^N {vi}i=1N,损失函数为:
L = − log ⁡ exp ⁡ ( s ( u , v + ) / τ ) exp ⁡ ( s ( u , v + ) / τ ) + ∑ i = 1 N exp ⁡ ( s ( u , v i − ) / τ ) \mathcal{L} = -\log \frac{\exp(s(u,v^+)/\tau)}{\exp(s(u,v^+)/\tau) + \sum_{i=1}^N \exp(s(u,v_i^-)/\tau)} L=logexp(s(u,v+)/τ)+i=1Nexp(s(u,vi)/τ)exp(s(u,v+)/τ)

6.2.2 梯度分析

对用户塔参数 θ \theta θ 求梯度:
∇ θ L = 1 τ [ E p ( v ∣ u ) [ ∇ θ f θ ( u ) g ϕ ( v ) ] ⏟ 正样本牵引 − ∇ θ f θ ( u ) g ϕ ( v + ) ⏟ 负样本推动 ] \nabla_\theta \mathcal{L} = \frac{1}{\tau}\left[ \underbrace{\mathbb{E}_{p(v|u)}[\nabla_\theta f_\theta(u)g_\phi(v)]}_{\text{正样本牵引}} - \underbrace{\nabla_\theta f_\theta(u)g_\phi(v^+)}_{\text{负样本推动}} \right] θL=τ1 正样本牵引 Ep(vu)[θfθ(u)gϕ(v)]负样本推动 θfθ(u)gϕ(v+)

梯度方向说明:

  • 正样本牵引:提升正样本的相似度
  • 负样本推动:降低所有负样本的相似度期望
6.2.3 损失函数的几何解释

图示说明:

    嵌入空间可视化

   ▲
   │         ○ 正样本
   │       ↗
u │     ➔ θ更新的方向 
   │       ↘
   │         × 负样本
   └─────────────────▶

6.3 对比学习理论框架

6.3.1 InfoNCE目标函数

双塔模型的交叉熵损失等价于InfoNCE目标函数的变体:
L InfoNCE = − E [ log ⁡ exp ⁡ ( s ( u , v + ) ) exp ⁡ ( s ( u , v + ) ) + ∑ exp ⁡ ( s ( u , v − ) ) ] \mathcal{L}_{\text{InfoNCE}} = -\mathbb{E} \left[ \log \frac{\exp(s(u,v^+))}{\exp(s(u,v^+)) + \sum \exp(s(u,v^-))} \right] LInfoNCE=E[logexp(s(u,v+))+exp(s(u,v))exp(s(u,v+))]

其本质是最大化正样本对的互信息下界:
I ( u ; v ) ≥ log ⁡ N − L InfoNCE I(u;v) \geq \log N - \mathcal{L}_{\text{InfoNCE}} I(u;v)logNLInfoNCE

6.3.2 温度系数的理论作用

温度系数 τ \tau τ 对梯度的调节作用:
∂ L ∂ s i = 1 τ ( p i − y i ) \frac{\partial \mathcal{L}}{\partial s_i} = \frac{1}{\tau} \left( p_i - y_i \right) siL=τ1(piyi)
其中:

  • p i = exp ⁡ ( s i / τ ) ∑ exp ⁡ ( s j / τ ) p_i = \frac{\exp(s_i/\tau)}{\sum \exp(s_j/\tau)} pi=exp(sj/τ)exp(si/τ)
  • y i y_i yi 是真实标签分布

τ \tau τ 减小时:

  • 梯度幅值增大 → 强化对显著差异样本的学习
  • 概率分布陡峭 → 模型置信度提高

6.4 双塔模型的泛化误差界

基于Rademacher复杂度理论,对于包含 m m m个样本的训练集,泛化误差满足:
R ( h ) ≤ O ~ ( B k m ) \mathcal{R}(h) \leq \tilde{O}\left( \frac{B\sqrt{k}}{\sqrt{m}} \right) R(h)O~(m Bk )
其中:

  • B B B 是嵌入向量的幅值上界
  • k k k 是嵌入空间维度
  • O ~ \tilde{O} O~ 表示忽略对数项的渐进符号

工程指导意义

  • 提升模型表现需增加训练数据量( m ↑ m↑ m
  • 合理控制嵌入维度( k k k不是越大越好)
  • 添加正则化约束嵌入幅值( B ↓ B↓ B

6.5 负采样策略理论分析

6.5.1 经典采样方案对比
采样策略数学形式理论特点
均匀随机采样 p ( v − ) ∝ 1 p(v^-) \propto 1 p(v)1计算简单,但未考虑流行度偏差
流行度加权采样 p ( v − ) ∝ N v + α p(v^-) \propto \sqrt{N_v+α} p(v)Nv+α 缓解头部物品支配问题,参数α调节平滑强度
对抗性采样 p ( v − ) ∝ exp ⁡ ( s ( u , v − ) / β ) p(v^-) \propto \exp(s(u,v^-)/β) p(v)exp(s(u,v)/β)β控制采样难易度,有助于挖掘困难负例
蒙特卡洛马尔可夫链基于MCMC的动态采样适应数据分布变化,但计算代价高
6.5.2 采样偏差修正公式

采用逆概率加权(IPS)的无偏估计:
L unbiased = E [ δ ( v + ) p ( v + ) log ⁡ exp ⁡ ( s + ) ∑ exp ⁡ ( s − ) ] \mathcal{L}_{\text{unbiased}} = \mathbb{E}\left[\frac{\delta(v^+)}{p(v^+)} \log \frac{\exp(s^+)}{\sum \exp(s^-)} \right] Lunbiased=E[p(v+)δ(v+)logexp(s)exp(s+)]
其中:

  • δ ( v ) \delta(v) δ(v) 是真实相关性标签
  • p ( v ) p(v) p(v) 是观测到的曝光概率

七、理论框架的工程实践启示

7.1 双塔结构设计原则

7.1.1 塔结构对称性

用户塔容量 : 物品塔容量 = 1 : ( 1.5 ∼ 2 ) \text{用户塔容量} : \text{物品塔容量} = 1 : (1.5 \sim 2) 用户塔容量:物品塔容量=1:(1.52)
理论依据:物品特征通常包含更多视觉/文本细节信息,需要更强的表示能力

7.1.2 梯度反传分析
梯度流示意图

用户塔梯度:
∇ θ L = ( p ( v ∣ u ) − y ) ⋅ g ϕ ( v ) \nabla_\theta \mathcal{L} = (p(v|u)-y) \cdot g_\phi(v) θL=(p(vu)y)gϕ(v)
说明用户特征更新与物品嵌入密切相关


7.2 损失函数改进方向

7.2.1 多任务联合训练

L total = λ 1 L click + λ 2 L like + λ 3 L share \mathcal{L}_{\text{total}} = \lambda_1 \mathcal{L}_{\text{click}} + \lambda_2 \mathcal{L}_{\text{like}} + \lambda_3 \mathcal{L}_{\text{share}} Ltotal=λ1Lclick+λ2Llike+λ3Lshare
理论支撑:解耦不同用户意图的表达学习,符合多目标优化理论

7.2.2 解纠缠正则化项

增加正则项:
L reg = ∑ i ≠ j ∣ f θ ( u i ) ⊤ g ϕ ( v j ) ∣ 2 \mathcal{L}_{\text{reg}} = \sum_{i≠j} | f_\theta(u_i)^\top g_\phi(v_j) |^2 Lreg=i=jfθ(ui)gϕ(vj)2
数学解释:强制非相关用户-物品对的相似度趋近于0


上述理论体系揭示了推荐算法设计背后的深刻数学原理,工程师应在实践中注意:

  1. 温度系数需要配合学习率同步调整
  2. 对比学习中负样本数量与质量的平衡
  3. 嵌入维度的选择需权衡模型容量与推理延时

有趣现象

双塔模型和CLIP(Contrastive Language-Image Pretraining)的设计思路确实是高度一致的。它们的核心都是将不同模态(或多领域)的数据映射到统一语义空间,通过对比学习实现对齐。以下从3个角度解释它们的共性及特性差异:


一、底层思路完全一致

1. 架构相似性
对比维度推荐双塔模型CLIP
模态1的处理用户特征塔(全连接网络)文本编码器(Transformer)
模态2的处理物品特征塔(全连接网络)图像编码器(Vision Transformer)
对齐方式内积/余弦相似度向量点积对比
2. 训练目标一致

二者均基于对比学习(Contrastive Learning)

  • 正样本对:用户点击的(用户,物品) ↔ CLIP的(图片,正确描述)
  • 负样本对:用户未点击的组合 ↔ CLIP的(图片,随机文本)

损失函数本质上都是:
L = − log ⁡ exp ⁡ ( s 正 ) exp ⁡ ( s 正 ) + ∑ exp ⁡ ( s 负 ) \mathcal{L} = -\log \frac{\exp(s_{\text{正}})}{\exp(s_{\text{正}}) + \sum \exp(s_{\text{负}})} L=logexp(s)+exp(s)exp(s)

3. 关键技术共享
  • 负样本挖掘策略
  • 温度系数(Temperature)控制
  • 特征归一化(L2 Normalization)

二、关键差异点解析

1. 输入模态的复杂性
  • 推荐双塔

    • 输入通常是结构化特征(用户ID、年龄、点击记录;物品ID、类别等)
    • 处理方式:Embedding层 + 浅层MLP
  • CLIP

    • 输入是多模态非结构化数据(自然语言文本 + 高维像素)
    • 处理方式:需要深层语义理解(Transformer处理语言、ViT处理图像)
2. 监督信号来源
推荐双塔模型CLIP
正样本隐式反馈(点击/购买)显式配对(图片-文本对)
监督密度高(用户行为丰富)低(需弱配对监督)
3. 部署场景差异
推荐双塔模型CLIP
推理方式用户塔实时计算,物品塔预计算双端实时计算(动态比对)
计算瓶颈物品检索速度图像/文本编码器延时

三、互相借鉴的技术点

在实际应用中,两种框架的技术可以交叉融合:

1. 推荐系统引入CLIP技术
  • 混合模态处理:用CLIP编码商品图文信息 → 增强物品塔特征
    class ItemTowerWithCLIP:
        def __init__(self):
            self.clip = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
            self.mlp = nn.Linear(512, 256)  # 将CLIP输出适配到推荐空间
    
        def forward(self, images, texts):
            clip_feat = self.clip(images, texts)  # 融合图文特征
            return self.mlp(clip_feat)
    
  • 跨域冷启动:利用CLIP关联文本描述→解决新物品无行为数据问题
2. CLIP借鉴推荐系统技巧
  • 负采样策略:采用推荐中的对抗采样(AWS)提升困难样本区分度
  • 在线服务优化:使用推荐系统的高效ANN检索实现CLIP大规模部署

一句话总结:

双塔模型和CLIP本质上是同一套对比学习框架在不同领域的具象化——推荐双塔是从行为数据中学习用户-物品的关联,CLIP是从图文配对中学习跨模态语义映射。二者的核心区别仅在于处理的数据类型和应用场景。

以下是关于双塔模型和CrossEntropyLoss的深度技术解读,包含理论推演、工业级实现细节和实际应用场景分析:


双塔模型与交叉熵损失深度解析

一、双塔模型架构详解

1.1 基础架构图示

class TwoTower(nn.Module):
    def __init__(self, user_dim=128, item_dim=256):
        super().__init__()
        # User Tower (用户特征处理)
        self.user_net = nn.Sequential(
            nn.Linear(256, 512),  # 用户原始特征维度256
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(512, user_dim)
        )
      
        # Item Tower (物品特征处理)
        self.item_net = nn.Sequential(
            nn.Linear(512, 1024), # 物品原始特征维度512
            nn.ReLU(),
            nn.LayerNorm(1024),
            nn.Linear(1024, item_dim)
        )

    def forward(self, user_feat, item_feat):
        user_emb = F.normalize(self.user_net(user_feat), p=2, dim=-1)
        item_emb = F.normalize(self.item_net(item_feat), p=2, dim=-1)
        return user_emb, item_emb

1.2 核心设计原则

  1. 解耦特性:用户与物品特征完全独立处理
  2. 异步更新:允许用户/物品塔单独更新(增量学习)
  3. 归一化约束:L2归一化保证内积等于余弦相似度
  4. 层次抽象
用户原始特征 → MLP → 高阶表征 → 语义浓缩 → 低维嵌入(128维)
物品原始特征 → 更深的MLP → 细粒度特征捕获 → 低维嵌入(256维)

1.3 工业级优化策略

优化技术实现方式收益说明
共享底层网络用户/物品共享前2层参数减少参数量,防止过拟合
混合精度训练使用AMP(Automatic Mixed Precision)节省显存,提升训练速度40%+
动态温度系数引入可学习的temperature参数自适应调整相似度分布
异步嵌入更新用户塔更新频率大于物品塔适配用户兴趣的快速变化
# 带温度系数的双塔实现
class TemperatureScaledTwoTower(TwoTower):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.temperature = nn.Parameter(torch.ones([]) * 0.07)  # 初始温度0.07

    def forward(self, user_feat, item_feats):
        user_emb, item_embs = super().forward(user_feat, item_feats)
        logits = user_emb @ item_embs.T / self.temperature.exp()
        return logits

二、交叉熵损失(CrossEntropyLoss)在推荐中的应用

2.1 数学形式与物理意义

交叉熵损失定义

L = − ∑ i = 1 B log ⁡ exp ⁡ ( s i + ) exp ⁡ ( s i + ) + ∑ j = 1 N exp ⁡ ( s j − ) \mathcal{L} = -\sum_{i=1}^B \log \frac{\exp(s_i^+)}{\exp(s_i^+) + \sum_{j=1}^N \exp(s_j^-)} L=i=1Blogexp(si+)+j=1Nexp(sj)exp(si+)

  • s i + s_i^+ si+:正样本的相似度分数
  • s j − s_j^- sj:负样本的相似度分数
  • B B B:Batch Size
  • N N N:负样本数量
近似等价形式(示例计算)
def manual_cross_entropy(s_pos, s_negs):
    # s_pos: [batch_size] 
    # s_negs: [batch_size, num_negs]
    numerator = s_pos
    denominator = torch.logsumexp(
        torch.cat([s_pos.unsqueeze(1), s_negs], dim=1), 
        dim=1
    )
    return -torch.mean(numerator - denominator)

2.2 推荐系统中的三种负采样模式

模式1:In-batch随机负采样(最常用)
class InBatchNegativeSampler:
    def generate(self, user_embs, item_embs):
        # user_embs: [B, D]
        # item_embs: [B, D]
        scores = user_embs @ item_embs.T  # [B, B]
        labels = torch.eye(scores.size(0), device=scores.device)
        loss = F.cross_entropy(scores, labels)
        return loss

特点

  • 自动采样同一batch中其他样本作为负例
  • 效率极高但可能存在false negative问题
模式2:显式负采样
class ExplicitNegativeSampler:
    def __init__(self, item_pool):
        self.items = item_pool  # 预加载所有物品特征
  
    def sample(self, user_emb, pos_item, num_negs=100):
        # 返回负样本:随机采样或困难负例挖掘
        neg_ids = np.random.choice(len(self.items), num_negs)
        neg_emb = self.items[neg_ids]
        scores = user_emb @ neg_emb.T
        return scores
模式3:流式负采样(工业级方案)
# 结合Kafka实现的流式采样
class StreamingNegativeSampler:
    def __init__(self, kafka_conf):
        self.consumer = KafkaConsumer(
            'neg_samples', 
            **kafka_conf,
            value_deserializer=lambda x: pickle.loads(x)
        )
  
    def generate(self):
        while True:
            msg = self.consumer.poll(1.0)
            for tp, messages in msg.items():
                for msg in messages:
                    yield msg.value  # 返回流式到来的负样本

2.3 损失函数选择策略

操作场景推荐损失函数适用说明
全库召回任务CrossEntropyLoss隐式负采样,天然适配多分类问题
高度稀疏数据Margin Loss (如Triplet Loss)强调正负样本间距,适合冷启动场景
多目标学习MultiTask CrossEntropy不同任务通过不同温度系数加权
去偏纠正式训练IPS-Weighted CE通过逆倾向分数加权解决曝光偏差

三、工业级训练流程示例

3.1 数据准备Pipeline

class RecDataset(Dataset):
    def __init__(self, data_path, neg_ratio=5):
        self.data = pd.read_parquet(data_path)
        self.item_features = load_all_item_features()  # 预加载至内存
        self.neg_ratio = neg_ratio
      
    def __getitem__(self, idx):
        row = self.data.iloc[idx]
        user_feat = process_user(row['user_info'])
        pos_item_feat = self.item_features[row['item_id']]
      
        # 显式负采样(规避in-batch假负例)
        neg_ids = sample_negatives(row['user_hist'], self.neg_ratio)
        neg_feats = [self.item_features[i] for i in neg_ids]
      
        return {
            'user': user_feat,
            'pos_item': pos_item_feat,
            'neg_items': torch.stack(neg_feats)
        }

def sample_negatives(hist_items, num):
    # 基于流行度降权采样的高级实现
    all_items = list(ITEM_POOL.keys())
    probs = 1.0 / (ITEM_POPULARITY[all_items] + 1e-6)
    return np.random.choice(all_items, num, p=probs/probs.sum(), replace=False)

3.2 高效训练实现

def train_epoch(model, dataloader, optimizer):
    model.train()
    total_loss = 0.0
  
    for batch in dataloader:
        user_feats = batch['user'].to(device)      # [B, user_dim]
        pos_items = batch['pos_item'].to(device)   # [B, item_dim]
        neg_items = batch['neg_items'].to(device)  # [B, N, item_dim]
      
        # 正样本嵌入计算
        user_emb, pos_emb = model(user_feats, pos_items)
        pos_score = (user_emb * pos_emb).sum(dim=-1, keepdim=True)  # [B, 1]
      
        # 负样本嵌入计算
        neg_embs = model.item_net(neg_items.view(-1, item_feat_dim))  # [B*N, E]
        neg_embs = neg_embs.view(user_emb.size(0), -1, item_emb_dim)  # [B, N, E]
      
        # 相似度计算
        neg_scores = torch.matmul(user_emb.unsqueeze(1), neg_embs.permute(0,2,1))  # [B, 1, N]
        neg_scores = neg_scores.squeeze(1)  # [B, N]
      
        # 构建最终logits矩阵
        logits = torch.cat([pos_score, neg_scores], dim=1)  # [B, N+1]
        labels = torch.zeros(logits.size(0), dtype=torch.long).to(device)
      
        # 计算交叉熵损失
        loss = F.cross_entropy(logits, labels)
      
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
      
        total_loss += loss.item()
  
    return total_loss / len(dataloader)

3.3 关键训练技巧

  1. 不对称学习率
optimizer = torch.optim.AdamW([
    {'params': model.user_net.parameters(), 'lr': 1e-3},
    {'params': model.item_net.parameters(), 'lr': 5e-4}
])
  1. 动态隐藏层维度(搜索最优值)
def find_optimal_dim(model_class, dims=[64, 128, 256]):
    results = {}
    for d in dims:
        model = model_class(user_dim=d, item_dim=d)
        score = evaluate(model)
        results[d] = score
    return dict(sorted(results.items(), key=lambda x: -x[1]))
  1. 无监督对比学习预热(Cold Start场景)
class PretrainWrapper:
    def contrastive_loss(self, emb1, emb2):
        # 使用NT-Xent损失做预训练
        logits = emb1 @ emb2.T
        labels = torch.arange(logits.size(0)).to(device)
        return F.cross_entropy(logits, labels)

四、在线服务关键技术点

4.1 嵌入索引优化

# FAISS索引构建器
class FaissIndex:
    def build(self, item_embeddings):
        dim = item_embeddings.shape[1]
        quantizer = faiss.IndexFlatIP(dim)
        self.index = faiss.IndexIVFFlat(quantizer, dim, 100)
        self.index.train(item_embeddings)
        self.index.add(item_embeddings)
  
    def search(self, query_emb, top_k=100):
        D, I = self.index.search(query_emb.reshape(1,-1), top_k)
        return I[0]

4.2 服务端部署架构

                  +------------------+
                  |   API服务        |
                  | (Flask/FastAPI) |
                  +-------+----------+
                          |
          +---------------+----------------+
          | 用户特征实时检索 (Redis)         |
          +----------------+---------------+
                          |
          +----------------+---------------+
          | 双塔模型推理服务 (TorchServe)    |
          +----------------+---------------+
                          |
          +----------------+---------------+
          | 实时特征拼接层                  |
          +----------------+---------------+
                          |
          +----------------v---------------+
          | FAISS向量检索集群 (横向扩展)     |
          +----------------+---------------+
                          |
          +----------------v---------------+
          | 多策略融合 & 过滤逻辑           |
          +----------------+---------------+
                          |
                  +--------v--------+
                  |  推荐结果返回     |
                  +-----------------+

五、评估与调优指南

5.1 离线评估指标

指标实现代码工业意义
Recall@Kdef recall(preds, labels, k): return sum(1 for p,l in zip(preds, labels) if l in p[:k]) / len(preds)真实覆盖用户的喜好能力
MRR@Ksum(1/(preds[i][:k].index(labels[i])+1) if labels[i] in preds[i][:k] else 0 for i in range(len)) / len衡量排名质量
Feature Coveragelen({item for batch in preds for item in batch}) / total_items推荐系统对新物品的覆盖能力
Latency@95th使用APM工具监控服务响应时间在线服务质量保障

5.2 超参数搜索参考

参数推荐范围影响分析调整策略
嵌入维度64-512↑维度→表征能力↑但线上压力↑通过A/B测试选择最优值
负样本比例5-20↑比例→泛化能力↑但训练难度↑观察验证集损失曲线变化
学习率1e-5 ~ 1e-3用户塔通常比物品塔大1-2倍两阶段调整策略
最小曝光阈值10-100次曝光防止长尾物品的噪声干扰统计物品点击率分布分位数

补充说明:实际部署时需考虑模型蒸馏、多模态特征融合等进阶技术,建议结合UMAP可视化工具分析嵌入空间分布质量。

<think>嗯,用户想了解双塔模型中负采样的方法和实现。首先,我需要回忆一下双塔模型的基本结构。双塔模型通常用于推荐系统或者信息检索,一个塔处理用户特征,另一个处理物品特征,然后计算两者的相似度。负采样在这里的作用应该是为了训练时生成负样本,让模型能够区分正样本和负样本。 用户提到的参考内容里,有提到Cross-Batch Negative Sampling(CBNS)方法,这个方法利用之前batch的embedding来增加负样本数量,从而减少对当前batch大小的依赖。需要解释清楚这个方法的原理,比如如何缓存历史embedding,如何结合当前和历史的负样本。同时,还要注意内存效率的问题,因为直接缓存所有历史数据可能不现实,可能需要滑动窗口或其他策略。 另一个参考是百度提出的动态自蒸馏方法,结合了交互模型和双塔模型。这可能涉及到知识蒸馏,即用更复杂的模型(比如交叉编码器)来指导双塔模型的训练,提升其性能。这里需要说明蒸馏的过程,比如如何用交互模型生成软标签,或者如何设计损失函数让双塔模型学习到更好的表示。 用户可能还关心具体的实现步骤,比如代码层面的负采样如何操作。可能需要给出伪代码或代码片段,比如在PyTorch中如何缓存embedding,如何进行相似度计算和损失函数计算。此外,需要比较不同负采样方法的优缺点,比如in-batch和CBNS的区别,以及它们对训练效果和资源消耗的影响。 还要注意用户提到的机器学习深度学习的上下文,所以在解释方法时要结合这些领域的知识,比如梯度下降、反向传播等。另外,用户可能对实际应用场景感兴趣,比如推荐系统或信息检索中的具体案例,可以简要提及。 最后,生成的相关问题需要覆盖理论、优化、应用和比较等方面,帮助用户进一步探索。例如,如何解决负采样中的偏差问题,或者如何结合其他技术提升双塔模型效果。</think>### 双塔模型中的负采样方法及实现 #### 1. 核心原理 双塔模型通过分离用户侧和物品侧的编码器生成独立向量表示$u_i$和$v_j$,通过相似度计算(如内积、余弦相似度)进行匹配。负采样的目标是**在训练过程中高效构造对比学习所需的负样本**,帮助模型区分正样本(用户真实交互的item)与负样本(未交互的item)[^1]。 #### 2. 典型方法实现 **(1) In-Batch负采样** ```python # 以PyTorch实现为例 user_emb = user_tower(batch_users) # shape: (B,d) item_emb = item_tower(batch_items) # shape: (B,d) logits = user_emb @ item_emb.t() # (B,B)相似度矩阵 labels = torch.arange(B) # 对角线为正样本 loss = F.cross_entropy(logits, labels) ``` 特点: - 每个batch内所有非对角线item自动成为负样本 - 受batchsize限制,负样本数量= batchsize-1 **(2) Cross-Batch负采样(CBNS)[^1]** ```python # 维护历史item embedding队列 item_queue = deque(maxlen=K) for batch in dataloader: # 当前batch计算 user_emb, item_emb = model(batch) # 从历史队列中采样负样本 neg_embs = sample(item_queue, num_neg=100) # 合并当前与历史负样本 all_neg = torch.cat([item_emb, neg_embs], dim=0) # 更新队列 item_queue.extend(item_emb.detach().cpu()) ``` 特点: - 通过滑动窗口缓存历史embedding突破batchsize限制 - 实验显示可减少30%训练时间保持相同效果 **(3) 动态自蒸馏[^2]** 通过交互模型(Cross-Encoder)生成软标签指导双塔模型训练: $$ \mathcal{L}_{distill} = \text{KL}(s_{dual}(u,i) \parallel s_{cross}(u,i)) $$ 实现步骤: 1. 使用交互模型计算query-doc的精细相关性分数 2. 将分数作为监督信号训练双塔模型 3. 结合传统对比损失: $$ \mathcal{L} = \alpha\mathcal{L}_{contrast} + (1-\alpha)\mathcal{L}_{distill} $$ #### 3. 关键优化方向 | 方法类型 | 优点 | 缺点 | |---------------|--------------------------|--------------------------| | In-Batch | 实现简单,无额外计算 | 负样本数量受限 | | CBNS | 突破batch限制,效率高 | 需管理历史embedding内存 | | 知识蒸馏 | 提升模型表达能力 | 依赖教师模型,计算成本高 | ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Terrence Shen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值