BYOL对比学习入门指南:从理论到PyTorch实战

1次阅读
没有评论

共计 2889 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

背景介绍

自监督学习是近年来机器学习领域的重要方向,它通过从无标注数据中自动生成监督信号来训练模型。对比学习作为自监督学习的核心范式,其核心思想是拉近相似样本(正样本对)的表示距离,同时推开不相似样本(负样本对)的表示距离。

BYOL 对比学习入门指南:从理论到 PyTorch 实战

传统对比学习方法(如 SimCLR)依赖于大量负样本构建对比任务,但负样本的采集和存储会带来计算开销和内存压力。BYOL(Bootstrap Your Own Latent)的创新之处在于完全摒弃负样本,仅通过在线网络和目标网络的交互实现特征学习。

BYOL 创新点

BYOL 与 SimCLR 等传统方法的区别主要体现在三个方面:

  1. 无需负样本 :通过目标网络提供的稳定表征作为学习目标,避免负样本带来的计算负担
  2. 非对称结构 :在线网络包含预测头,目标网络通过 EMA(指数移动平均)更新
  3. 目标一致性 :目标网络参数缓慢更新,为在线网络提供一致的学习目标

其核心公式可表示为:
$$\mathcal{L}{\theta,\xi} = |q\theta(z_\theta) – z’\xi|_2^2$$
其中 $q
\theta$ 是在线网络的预测头,$z_\theta$ 和 $z’_\xi$ 分别是在线网络和目标网络的输出。

核心组件

1. 双分支网络结构

  • 在线网络 :包含编码器 $f_\theta$ 和预测头 $q_\theta$,通过梯度下降更新
  • 目标网络 :结构同在线网络(不含预测头),参数 $\xi$ 通过 EMA 更新:
    $$\xi \leftarrow \tau\xi + (1-\tau)\theta$$
    典型 $\tau$ 值取 0.99-0.999

2. 数据增强策略

BYOL 对同一输入应用两种随机增强:

  • 全局视图:包含颜色失真、高斯模糊等强增强
  • 局部视图:随机裁剪等空间变换

3. 对称损失计算

对 batch 内每个样本计算两个方向的预测误差:
$$\mathcal{L} = \frac{1}{2N}\sum_{i=1}^N (|q(z_i)-z’_i|^2 + |q(z’_i)-z_i|^2)$$

PyTorch 实现

import torch
import torch.nn as nn
import torch.nn.functional as F

class MLPHead(nn.Module):
    """BYOL 的预测头"""
    def __init__(self, dim_in, hidden_size=4096, dim_out=256):
        super().__init__()
        self.net = nn.Sequential(nn.Linear(dim_in, hidden_size),
            nn.BatchNorm1d(hidden_size),
            nn.ReLU(inplace=True),
            nn.Linear(hidden_size, dim_out)
        )

    def forward(self, x):
        return self.net(x)

class BYOL(nn.Module):
    def __init__(self, backbone, hidden_size=4096, pred_dim=256, tau=0.996):
        super().__init__()
        self.tau = tau
        self.online_encoder = backbone
        self.target_encoder = backbone

        # 初始化目标网络与在线网络参数一致
        for param_o, param_t in zip(self.online_encoder.parameters(), 
                                   self.target_encoder.parameters()):
            param_t.data.copy_(param_o.data)
            param_t.requires_grad = False  # 目标网络不更新梯度

        # 预测头
        self.online_predictor = MLPHead(dim_in=backbone.output_dim, 
                                      hidden_size=hidden_size,
                                      dim_out=pred_dim)

    @torch.no_grad()
    def update_target(self):
        """EMA 更新目标网络"""
        for param_o, param_t in zip(self.online_encoder.parameters(),
                                   self.target_encoder.parameters()):
            param_t.data = self.tau * param_t.data + (1 - self.tau) * param_o.data

    def forward(self, view1, view2):
        """
        输入: 
            view1, view2 - 同一图像的两个增强视图
        返回:
            loss - 对称损失值
        """
        # 在线网络前向
        z1_o = self.online_encoder(view1)
        z2_o = self.online_encoder(view2)
        p1_o = self.online_predictor(z1_o)
        p2_o = self.online_predictor(z2_o)

        # 目标网络前向 (不计算梯度)
        with torch.no_grad():
            z2_t = self.target_encoder(view2)
            z1_t = self.target_encoder(view1)

        # 对称损失
        loss = 0.5 * (F.mse_loss(p1_o, z2_t.detach()) + 
                     F.mse_loss(p2_o, z1_t.detach()))

        # 更新目标网络
        self.update_target()
        return loss

训练技巧

  1. 学习率设置
  2. 基础学习率建议 3e-4,配合线性 warmup(前 10 个 epoch)
  3. 使用 AdamW 优化器,weight decay 设为 1e-6

  4. Batch Size 选择

  5. 单卡 GPU 建议 256-512,多卡可适当增大
  6. 过小 batch size 可能导致学习不稳定

  7. 训练时长

  8. 小数据集(如 CIFAR)约 100-200epoch
  9. ImageNet 等大数据集需要 300-500epoch

  10. 数据增强组合

  11. 必须包含随机裁剪 + 颜色扰动
  12. 可添加高斯模糊增强鲁棒性

避坑指南

模型坍塌(Collapse)

现象 :所有样本输出相同表示(损失趋近于 0 但无意义)

解决方案 :
– 确保使用 batch normalization(BN)
– 预测头使用固定维度的输出(如 256)
– 适当增大 batch size(至少 256)

训练不稳定

现象 :损失值剧烈波动

解决方法 :
– 降低基础学习率(尝试 1e- 4 到 3e-4)
– 增加 EMA 系数 $\tau$(接近 1 的值如 0.996)
– 检查数据增强是否过于激进

延伸思考

BYOL 在实际业务中的应用潜力:

  1. 医学影像分析
  2. 解决标注数据稀缺问题
  3. 通过无监督预训练提升下游任务性能

  4. 推荐系统

  5. 学习用户行为序列的通用表示
  6. 缓解冷启动问题

  7. 工业质检

  8. 利用正常样本学习特征空间
  9. 异常检测时通过距离阈值判断

  10. 多模态学习

  11. 扩展为跨模态对比框架
  12. 对齐视觉与文本特征空间

结语

BYOL 通过巧妙的网络设计和 EMA 机制,实现了无需负样本的高效对比学习。虽然训练过程需要更多 epoch 才能收敛,但节省了显存开销,更适合实际业务部署。建议初学者先从小型数据集(如 CIFAR-10)开始实验,逐步调整超参数,体会算法的工作原理。

正文完
 0
评论(没有评论)