对比学习的正负对 以及参数设置

对比学习中, 通常在 实例级别进行正负对划分, 而不在类别层面上进行正负对划分

通常情况下使用相同样本的不同数据增强变换作为正对, 不同样本的数据增强变换作为负对

一般情况下不使用类别的不同来划分正对,负对;
即不使用不同类别的数据增强作为负对,

这样做的原因是许多对比学习应用中,是在没有类别信息的情况下, 来区分不同的实例。

特别是自监督应用中,数据样本的类别标签是未知的。这种情况需要一种无需依赖特定类别信息即可有效运行的方法。通过将单独样本的不同转换版本视为负对,模型学会区分不同的实例,无论其类别如何,这在明确类别标签不可用的情况下特别有用。

1.对比学习中,超参数应该如何设置,

在对比学习中,超参数(包括损失函数中的温度参数)的设置对于模型性能至关重要。以下是关于如何在处理特定数量的类别(例如 7 个类别的示例)时设置这些超参数的一般指南:

1.1 Temperature Parameter1、温度参数

对比学习中的温度参数,通常表示为 τ \tau τ ,控制损失函数中距离或相似性度量的尺度。该参数在软化嵌入点积导出的概率方面起着关键作用。设置此参数的方法如下:

  • Start with Standard Values: 通常,在许多实现中使用 0.05 到 0.5 之间的温度参数值。例如,在 SimCLR 框架中,0.1 或 0.2 的温度值通常是一个很好的起点。

  • Adjust Based on Dataset and Task Complexity: 根据数据集和任务复杂性进行调整:对于具有 7 个类别的数据集,您可能会从此范围的较高端开始(例如 0.2 或 0.3),因为类别数量较少可能意味着需要的粒度分离较小。然而,这在很大程度上取决于类间和类内方差。

  • Experiment and Validate:

  • 实验和验证:最佳设置通常需要经验验证。您应该尝试不同的值,并根据模型在验证集上的性能来验证它们。寻找平衡点,使模型既不会学习琐碎的解决方案(崩溃问题),也不会无法很好地区分类别。

1.2. Margin in Triplet Loss or Contrastive Loss

. Triplet Loss 或 Contrastive Loss 的裕度

If you are using a margin-based variant like triplet loss or pair-wise contrastive loss:如果您使用margin-based variant l,例如三元组损失或成对对比损失:

  • Set Initial Margin:
  • 设置初始边距:从边距开始,该边距既不能太小而导致嵌入重叠,也不能太大而导致学习受到太大限制。常见的起始值约为 1.0。
  • Adjust Based on Performance: 根据性能进行调整:如果类别分离良好并且嵌入在初始实验期间似乎聚类得很好,则您可能不需要过多调整边距。如果存在重叠或混乱,请考虑稍微调整边距。

1.3. 批量大小和抽样策略

  • Batch Size:
    批量大小:较大的批量大小通常会为每个正对提供更多的负样本,这在对比学习设置中可能是有益的。但是,这可能会受到计算资源的限制。

  • Sampling Strategy:
    抽样策略:确保您的批次包含来自 7 个类别的样品的均衡组合。
    如果您的模型在随机采样方面表现不佳,这可能涉及诸如硬负挖掘之类的策略。

1.4. 学习率和其他优化器设置

  • Learning Rate:学习率:从类似任务或框架推荐的学习率开始,并根据学习曲线进行调整。您可能需要一个学习率调度程序来随着训练的进行而降低学习率。

  • Optimizer: 优化器:通常使用 Adam 或带有动量的 SGD。具体的超参数可能取决于数据集的特定特征。

1.5.正则化技术

  • Data Augmentation: 数据增强:在对比学习中特别有用,可以增加表示的多样性。
  • Dropout, Weight Decay: 这些可以帮助防止过度拟合,特别是在类别数量相对较少的情况下。

综上所述,有效设置这些超参数的关键在于从基于文献或类似任务的推荐值开始,然后根据系统实验和验证结果迭代调整它们。

2 类内差距与类间差距

如果类内差距较大,类间差距较小,温度参数应该如何设置?


当处理类内变异性较大且类间可分离性较小的数据时,在对比学习设置中调整温度参数需要仔细考虑。

对比损失函数中的温度参数主要控制模型对特征空间中样本之间差异的敏感性。以下是在这些特定条件下设置此参数的方法:

2.1 Understanding the Role of Temperature了解温度的作用

较低的温度 :较低的温度值(例如,接近 0.05)使得对比损失中使用的 softmax 函数更加锐利,强调正负对之间更大的裕度。当您想要强调类之间的微小差异时(当类间差距很小时这可能是必要的),这很有用。

  • Higher Temperature: 较高的温度:较高的温度值(例如 0.5 左右)会软化 softmax 函数,使模型对样本之间的差异不太敏感。当模型需要处理同一类中的较大变化而不过度拟合不代表不同类的微小差异时,这非常有用。

2.2 设置温度的策略

  1. Start with a Lower Temperature:从较低的温度开始:鉴于您对具有较小类间差距的数据集的描述,从较低的温度开始可能有助于模型更好地区分间隔紧密的类。此设置有助于确保模型更加关注区分不同类的表示,即使它们的差异很细微。

  2. Experiment with Gradual Increases: 逐步增加实验:如果您发现模型在将类别分开方面过于激进(这可能是由于验证性能不佳所表明的,例如高假阴性率或类别之间的混淆),请考虑逐渐增加温度。这种调整可以帮助适应较大的类内变异,使模型更能容忍同一类内的较大变化。

  3. Monitor and Adjust Based on Validation Metrics: 根据验证指标进行监控和调整:仔细监控验证集上的性能指标。需要关注的关键指标包括:

    • Precision and Recall: 精确率和召回率:这些指标将帮助您了解模型是否有效地区分类别,而不牺牲每个类别中真实阳性的识别。

    • Confusion Matrix: 混淆矩阵:分析混淆矩阵以查看特定类别是否始终与其他类别混淆,这可能表明需要调整温度或其他模型超参数。

  4. Balance with Other Hyperparameters: 与其他超参数的平衡:请记住,温度参数不能单独工作。它的影响与其他超参数相互依赖,例如学习率、批量大小以及基于保证金的损失中的潜在保证金。根据温度调整这些参数,以找到最佳的整体参数集。

  5. Use Advanced Sampling Techniques: 使用高级采样技术:如果标准采样策略不能提供令人满意的结果,请考虑使用硬负挖掘等技术。硬负挖掘侧重于选择接近决策边界的负对,这在类间变异性较低时特别有用。

综上所述,当类间可分离性较小且类内变异性较大时,从较低温度开始并根据系统实验和详细性能分析进行调整是一种谨慎的方法。此策略有助于微调模型对定义类边界的关键特征的敏感性。

3. 如何使用数据增强

在进行比较学习时,是否应该对批次中同一类别的样本使用相同的数据增强,而对不同类别的样本使用不同的数据增强?
也就是我很好奇,在进行对比学习时,不同样本进行数据增强时,是不是应该利用每个样本的类别来进行对应的数据增强呢?

3.1 根据类别执行数据增强(不常规)

在对比学习中,数据增强方法对于模型学习有用且稳健的表示的效果起着重要作用。您概述的策略(对一批中同一类别的样本使用相同的数据增强,对不同类别的样本使用不同的数据增强)是一种有趣的策略,在某些条件下可能是有益的。以下更详细地介绍了如何实施这种方法并从中受益:

Augmentation Strategies in Contrastive Learning对比学习中的增强策略

  1. Consistent Augmentation Within Categories:类别内的一致增强:

    • Purpose: 目的:通过对批次中同一类别的样本应用相同的增强技术,可以帮助模型学习识别该类别的核心不变特征。这是因为批次内的所有变化仅来自样本的固有差异,而不是来自增强。

    • Example:示例:如果一批中所有猫的图像都进行类似的旋转,并且所有狗的图像都进行类似的裁剪,则模型了解到旋转角度和特定裁剪不会定义类别边界。

  2. Varied Augmentation Across Categories:跨类别的不同增强:

    • Purpose: 目的:对不同类别使用不同的增强策略可以通过强调特定于类别的特征来帮助加强类别区别。它还在数据集中引入了更多的可变性,有可能提高模型的稳健性和跨不同条件的泛化能力。

    • Example: 示例:如果猫总是通过旋转来增强,而狗则通过裁剪来增强,则模型可能会学会将某些变换鲁棒性与特定类别相关联,这在特定于类别的变换很常见的情况下可能会有所帮助。

Considerations for Implementing This Strategy实施该策略的考虑因素

  • Generalization vs. Overfitting: 泛化与过度拟合:虽然使用特定于类别的增强可以帮助模型学习每个类别中更强大的特征,但存在对特定类型的增强过度拟合的风险。确保模型能够在未观察到的变换和条件下进行泛化至关重要。

  • Dataset Diversity: 数据集多样性:此方法的有效性可能取决于数据集的多样性和大小。如果您的数据集有限或不太多样化,则过于专业的增强技术可能会导致模型在训练数据上表现良好,但在新的、看不见的数据上表现不佳。

  • Experimentation: 实验:这种方法应该经过实证检验。进行实验,比较使用跨类别统一增强与差异化增强训练的模型的性能。需要关注的指标包括准确性、精确度、召回率以及推广到验证或测试集的能力。

3.2 替代增强策略

  • Randomized Augmentation: 随机增强:对比学习中的一种常见方法是对每个实例应用随机但可能相同的增强,无论类别如何。该方法确保了各种学习信号和对转换的总体鲁棒性。

  • Symmetric Augmentation: 对称增强:正对中的每个样本(即同一类别的样本)都会经历相同的变换。该策略通过关注类别内变化的相同方面来强化相似性学习方面。

小结: 在对比学习中使用特定于类别的增强的想法对于教授模型特定于类别的不变特征是有利的,
但应该与跨未见条件的泛化需求相平衡。

跨不同场景的定期测试和验证对于确保模型不会变得对于训练数据过于专业化至关重要。

与机器学习的许多方面一样,最佳策略通常取决于数据集的具体特征和应用程序的特定要求。


4. 根据样本来划分 正对和负对

比较学习中常见的做法是否正确?一个批次中的每个样本都会经历两次不同的数据增强,而不需要考虑该批次中每个样本的类别来进行相应的数据增强。这是真的?

在对比学习中,对批次中的每个样本应用两种不同的数据增强确实很常见,而在决定增强时不必考虑每个样本的类别。

这种做法在 SimCLR 这样的自监督学习框架中尤其突出,其主要目标是通过最大化同一数据实例的不同增强视图之间的一致性来学习有用的表示。

4.1 对比学习的 数据增强

  1. Two Augmentations per Sample: 每个样本两次增强:批次中的每个样本都被增强两次,这两个增强版本形成正对。

关键思想是,两个版本都来自相同的基础数据点,但以不同的方式进行转换(例如,不同的裁剪、旋转、颜色抖动)。
然后,模型学习最小化这些正对的嵌入之间的距离,同时最大化负对(即来自不同原始样本的对)嵌入之间的距离。

  1. Random and Diverse Augmentations: 随机和多样化的增强:增强是随机应用的,并涵盖了一组不同的转换。常见的增强包括:

    • Cropping and resizing: 裁剪和调整大小:随机裁剪图像并将其调整回原始尺寸。
    • Color transformations: 颜色变换:修改亮度、对比度、饱和度和色调。
    • Rotation and flipping: 旋转和翻转:将图像旋转任意角度或水平翻转。
    • Blurring and noise: 模糊和噪声:应用高斯模糊或添加随机噪声。
  2. Category Agnosticism: 类别不可知论:通常应用增强而不考虑图像的类别。这种不可知论有助于模型学习不仅对于转换不变而且在不同实例和类别之间不变的特征。

  • 优点:
  • Robust Feature Learning: 鲁棒特征学习:通过学习关联同一样本的两个不同增强视图,该模型对现实场景中可能遇到的变化具有鲁棒性。

  • Generalization: 泛化:此方法鼓励模型关注高级不变特征,这些特征对于区分不同样本很有用,无论其具体类别或增强的性质如何。

  • Simplicity and Flexibility: 简单性和灵活性:应用增强功能而无需针对特定类别进行定制,从而简化了训练过程,并使该方法广泛适用于不同的数据集和任务。

  • 潜在的限制:
  • Category-Specific Features:特定于类别的特征:虽然这种方法对于一般特征学习是有效的,但如果目标是学习特定类别特有的非常具体的特征,特别是如果这些特征可能会因某些增强而减弱或模糊,那么它可能不会那么有效。

  • Hyperparameter Sensitivity: 超参数敏感性:增强的选择和强度可以显着影响性能。太强或不适当的增强可能会导致模型无法学习有用的表示,而太弱的增强可能无法为学习稳健的特征提供足够的挑战。

总之,在不考虑样本类别的情况下对批次中的每个样本应用两种不同的随机增强是对比学习中的标准且有效的实践,特别适合目标是在各种输入中学习广泛有用且稳健的表示的任务。


4.2 为何不用类别来划分正负对

为什么要把不同样本得到的变换作为负对,而不是把不同类别的样本作为负对来增强呢?

在对比学习中,特别是在自监督学习环境中,
主要目标是从未标记的数据中学习可概括且稳健的特征表示。
使用不同样本的转换作为负对,而不是专门针对不同类别的样本,这一概念源于几个关键考虑因素:

未标记的数据使用

在许多对比学习应用中,特别是自监督应用中,数据样本的类别标签是未知的。这种情况需要一种无需依赖特定类别信息即可有效运行的方法。通过将单独样本的不同转换版本视为负对,模型学会区分不同的实例,无论其类别如何,这在明确类别标签不可用的情况下特别有用。

注重实例判别

在这种情况下,对比学习的基本机制是实例辨别——训练模型来识别和区分各个实例,而不是预定义的类别。这是通过以下方式实现的:

  • Positive Pairs: 正对:同一样本的两个不同增强被视为相似(正对),鼓励模型在样本中找到不变的特征,尽管有增强。
  • Negative Pairs:负对:不同样本的增强被视为不同的(负对),鼓励模型区分不同的样本。

通用特征学习

使用不同的样本作为负对的基础有助于模型对数据有更全面的理解。该模型学习的特征不仅对转换不变(从正对中学习),而且在不同实例之间具有区分性。这种广泛的判别能力对于聚类、检索或训练后应用的下游分类任务等任务至关重要。

可扩展性和简单性

使用不同样本的转换作为负对是一种简单的方法,可以很好地随数据量扩展。它避免了必须根据类别选择负对的复杂性和潜在偏差,这在不平衡的数据集或具有大量类别的数据集中可能尤其成问题。

过拟合的鲁棒性

通过关注实例级别的区别而不是类别差异,使用这种方法训练的模型可能会更稳健,不会过度拟合在更一般的上下文中可能不相关的特定类别级别特征。这种方法鼓励学习适用于各种任务和领域的通用特征。

小结

本质上,在对比学习中使用不同样本的转换作为负对(尤其是在自监督框架中)是为了最大化未标记数据的效用,并教导模型辨别区分一个实例的微妙和复杂的模式。来自另一个。该方法还确保学习过程不会受到类别假设或依赖关系的影响,这些假设或依赖关系可能并不总是可用或可靠,从而增强模型跨不同类型的数据和任务进行泛化的能力。


5. 有监督场景中根据类别来划分正对和负对场景

如果将不同类别的样本作为负对,会有什么影响吗?

在对比学习中使用不同类别的样本作为负对确实可以对模型的学习动态及其最终性能产生重大影响。
这种方法在监督或半监督对比学习场景中特别有效或必要,其中类别标签可用且可靠。
以下是合并类别信息来构建负对对学习过程的影响:

增强判别力

通过明确使用不同类别的样本作为负对,直接鼓励模型学习类别之间有区别的特征。这可能导致:

  • Improved Separation:改进的分离:模型可以更好地区分类别,因为它学习最大化来自不同类别的样本嵌入之间的距离。
  • Reduced Ambiguity: 减少歧义:它有助于减少特征空间中的歧义,因为模型经过明确训练以识别和加强类别之间的差异。

减少误报

在某些类别可能具有相似特征的情况下,使用随机负对(不考虑类别)可能无法提供足够的判别训练信号。使用类别感知负采样:
更清晰的边界:该模型可以开发更清晰的类别边界,这对于需要细粒度分类或类之间细微区别的任务至关重要。

对类别的偏见

虽然这种方法可以改善特定类别的判别性学习,但它也可能会引入偏见:

类别偏差:模型可能过度关注根据训练数据的分布和标签定义类别的差异,可能导致模型不能很好地泛化到未标记或不同分布的数据。

训练的复杂性

使用类别信息形成负对会增加训练过程的复杂性:

  • Sampling Strategy: 抽样策略:您需要更复杂的抽样策略来确保公平地代表每个类别,并有效地选择负对以最大化学习。
  • Balanced Data Requirement: 平衡的数据要求:如果数据集不平衡,此策略可能会因过度代表负对中的主导类别而加剧问题,从而扭曲学习到的特征。

过度拟合的可能性

当过度强调类别之间的区别时,存在过度拟合训练期间看到的特定类别的风险:

过度拟合风险:模型可能在区分训练类别方面表现出色,但无法泛化到训练数据中未涵盖的新类别或变体。

改进监督任务的性能

如果最终目标是类别区分至关重要(例如分类)的监督任务,则此方法可以直接将对比学习目标与最终任务目标结合起来,从而有可能提高性能:

任务对齐:直接使用类别区别可以使预训练与依赖这些区别的特定任务更紧密地结合起来。

在对比学习中结合基于类别的区别来形成负对可能是有利的,但会在复杂性、潜在偏差和过度拟合的风险方面进行权衡。这种方法应该谨慎实施,特别是考虑类别的平衡、任务的性质和数据集的特征。当类别区别对于下游任务的性能至关重要时,这是最有益的。


5.2 类别不平衡时

类别极不平衡,任务是分类任务。第二阶段测试集的分布与训练集有差异时。这个时候我该如何利用类别信息进行对比学习呢?


在处理极其不平衡的数据集和分类任务时,特别是当测试集中的分布可能与训练集显着不同时,在对比学习中有效使用类别信息需要采取谨慎的方法来应对这些挑战。
以下是在这些条件下优化您对类别信息的使用的策略:

平衡采样
为了减轻不平衡数据集的影响:

  • Balanced Batches: 平衡批次:使用平衡批次抽样,其中每个批次包含来自每个类别的代表性数量的样本。这可以防止模型偏向更流行的类别。
  • Oversampling/Undersampling: 过采样/欠采样:考虑在训练期间对少数类进行过采样或对多数类进行欠采样。过采样在对比学习中特别有用,因为它提供了更多样的代表性不足的类别的示例供学习。

定制的负配对

Given the imbalance and the task at hand:鉴于不平衡和手头的任务:

  • Intra- and Inter-Class Pairs: 类内和类间对:混合使用类内和类间负对。这意味着不仅在不同类之间形成负对,而且在少数类的同一类内也形成负对,以增强类内方差学习。

  • Hard Negative Mining: 硬负挖掘:结合硬负挖掘,其中根据特征的接近程度选择负对。这鼓励模型学习相似但不同类别样本之间的更细微区别。

损失的自适应加权
调整损失函数以解决类别不平衡的问题:

  • Weighted Loss: 加权损失:通过根据频率对每个类对的贡献进行加权来修改对比损失。这有助于更加重视少数群体。
  • Focal Loss:焦点损失:考虑使用焦点损失变体来更多地关注难以分类的示例,这些示例通常来自代表性不足的类别。

增强策略

增强可以帮助模拟更平衡的数据集:

  • Class-Specific Augmentations: 特定类别的增强:对少数类别应用更积极或更多样化的增强,以人为地增加其在训练过程中的多样性和代表性。

正则化技术

为了避免过度拟合训练集,特别是当训练集不平衡时:

  • Dropout: 在网络中使用 dropout 来防止依赖于可能过于特定于倾斜训练分布的任何特定功能集。

  • Early Stopping早期停止:在训练期间实施早期停止,以防止模型过于适应训练集的噪声和特定偏差。

基于验证集的评估和调整
持续评估模型在验证集上的性能,该验证集的结构可以代表预期的测试集分布:

  • Validation Set Composition: 验证集组成:如果可能,构建一个模仿预期测试集分布的验证集。这可以提供关于模型在实际测试集上的表现的更真实的反馈。

  • Iterative Adjustments:迭代调整:根据验证性能,迭代调整上述策略,特别是采样和损失权重,以完善模型学习。

特征归一化和校准

从训练过渡到测试时:

  • Calibration: 校准:考虑温度缩放或等渗回归等技术来校准输出,提高可靠性,特别是在数据集变化条件下。
  • Normalization: 标准化:确保特征标准化参数(均值、标准差)在训练、验证和测试中保持一致,以减轻分布差异。

通过集成这些策略,您可以更好地利用类别信息,在测试集中预期出现类别不平衡和分布变化的情况下训练更稳健、更公平的模型。这种整体方法既满足了学习判别性特征的直接需求,也满足了模型泛化到新的、看不见的数据场景的更广泛的要求。

5.3 类别平衡时

如果类别是平衡的,是一个分类任务,这时候应该如何利用类别信息进行比较学习呢?

借助平衡的数据集和分类任务,在对比学习中使用类别信息可以有效提高模型区分类别的能力,并增强其对未见过的数据的泛化能力。以下是在这种情况下如何战略性地利用类别信息的方法:

正负样本的结构化配对

由于您的数据集是平衡的,您可以使用类别信息更谨慎地构建正负对:

  • Positive Pairs: 正对:通过对同一样本应用两种不同的增强来创建正对。这种方法有助于模型学习同一类别内的不变特征
  • Negative Pairs: 负对:使用不同类别的样本形成负对。这在平衡数据集中很简单,因为它允许您确保每个类别在负对形成中均等地代表。

增强策略

增强是对比学习中的关键,可确保模型学习稳健的特征:

  • Varied Augmentations 各种增强:使用广泛的增强来确保模型学习泛化不同的转换,而不仅仅是那些简单或常见的转换。这包括几何变换(如旋转和翻转)、颜色调整(如亮度和对比度变化),甚至更复杂的方法,如随机擦除或混合。

  • Category-Specific Augmentations: 特定于类别的增强:虽然一般增强适用于所有类别,但如果相关的话,请考虑根据类别特征应用这些增强的方式略有不同。例如,对颜色变化更敏感的类别(如花朵或鸟类)可能会受益于不同的颜色增强策略。

类别强调的对比损失

有效利用对比损失函数:

  • Temperature Scaling: A温度缩放:调整对比损失的 softmax 函数中的温度参数,以控制模型区分相似对和不相似对的清晰度。较低的温度有助于使模型对类别之间的细微差异敏感,这在平衡数据集中很有用。

  • Margin-Based Losses: 基于边际的损失:考虑使用基于边际的对比损失(如三元组损失),您可以指定负对嵌入之间必须保持的差异边际。

平衡采样

尽管您的数据集是平衡的,但在每个批次中保持这种平衡至关重要:

  • Ensure Representation: 确保代表性:确保训练期间使用的每个批次包含每个类别中大致相等数量的样本。这可以防止模型在特定训练阶段对任何特定类别产生偏见。

利用半监督技术
如果有额外的未标记数据可用,则可以利用半监督对比学习:

  • Pseudo-Labeling: 伪标签:使用模型的预测为未标记的数据生成标签,然后将其合并到训练中以提供额外的多样性和样本量。
  • Consistency Training: 一致性训练:对未标记的数据应用不同的增强,并鼓励在这些增强中进行一致的模型预测。

持续评估
定期评估模型,不仅要评估整体准确性,还要评估其正确分类每个类别的能力:

  • Confusion Matrix: 混淆矩阵:定期分析混淆矩阵,以识别可能始终与其他类别混淆的任何类别。
  • Category-Specific Metrics: 特定于类别的指标:跟踪每个类别的精确度、召回率和 F1 分数,以确保模型全面一致地执行。

在具有分类任务的平衡数据集中,可以优化类别信息的使用,以提高模型的判别能力及其对类别内和类别间变化的鲁棒性。结合深思熟虑的配对、平衡采样和连续评估的结构化训练可以产生一个模型,该模型不仅在训练和验证数据集上表现良好,而且还可以有效地推广到新的、看不见的数据。


5.4 代码实现

给出了pytorch利用类别信息进行比较学习的代码,即重点关注同一批次的不同样本如何根据类别进行不同的变换。已知类别有7类,给出代码。

要创建一个使用类别信息进行对比学习的 PyTorch 示例,其中同一批次的不同样本根据其类别进行不同的转换,我们首先需要为每个类别定义自定义转换。然后,我们将这些转换集成到 DataLoader 中,在加载每个批次时相应地应用它们。

以下是 PyTorch 中的分步实现:

Step 1: Define Custom Transformations第 1 步:定义自定义转换

首先,我们为这 7 个类别中的每一个类别定义具体的转换。 PyTorch 的 torchvision.transforms 模块可用于此目的。

import torchvision.transforms as transforms

# Define transformations for each of the 7 categories
category_transforms = {
    0: transforms.Compose([
        transforms.RandomHorizontalFlip(),
        transforms.ColorJitter(brightness=0.5),
        transforms.RandomRotation(10)
    ]),
    1: transforms.Compose([
        transforms.RandomVerticalFlip(),
        transforms.ColorJitter(contrast=0.5),
        transforms.RandomAffine(degrees=0, translate=(0.1, 0.1))
    ]),
    2: transforms.Compose([
        transforms.RandomCrop(size=224),
        transforms.RandomGrayscale(),
        transforms.GaussianBlur(3)
    ]),
    3: transforms.Compose([
        transforms.RandomResizedCrop(224),
        transforms.RandomPerspective(),
        transforms.RandomRotation(20)
    ]),
    4: transforms.Compose([
        transforms.RandomHorizontalFlip(),
        transforms.RandomVerticalFlip(),
        transforms.RandomRotation(30)
    ]),
    5: transforms.Compose([
        transforms.RandomResizedCrop(224),
        transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),
        transforms.RandomRotation(45)
    ]),
    6: transforms.Compose([
        transforms.RandomCrop(size=224),
        transforms.RandomHorizontalFlip(),
        transforms.RandomRotation(90)
    ])
}

Step 2: Create a Dataset with Category-Specific Augmentation第 2 步:创建具有特定类别增强功能的数据集

We’ll modify a dataset class to use these category-specific transformations. Assuming you have a dataset where each sample consists of an image and its category label.我们将修改数据集类以使用这些特定于类别的转换。假设您有一个数据集,其中每个样本都由图像及其类别标签组成。

from torch.utils.data import Dataset
from PIL import Image

class CustomDataset(Dataset):
    def __init__(self, image_paths, labels, transforms=None):
        self.image_paths = image_paths
        self.labels = labels
        self.transforms = transforms

    def __len__(self):
        return len(self.image_paths)

    def __getitem__(self, idx):
        image = Image.open(self.image_paths[idx])
        label = self.labels[idx]

        # Apply category-specific transformation
        if self.transforms:
            image = self.transforms[label](image)

        return image, label

Step 3: DataLoader第三步:数据加载器

When creating the DataLoader, ensure that the dataset is used with the correct transformations.创建 DataLoader 时,请确保使用正确的转换来使用数据集。

from torch.utils.data import DataLoader

# Example usage
image_paths = ["path_to_image1.jpg", "path_to_image2.jpg", ...]  # paths to images
labels = [0, 1, 2, 3, 4, 5, 6]  # corresponding labels

dataset = CustomDataset(image_paths, labels, transforms=category_transforms)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

Step 4: Training Loop第 4 步:训练循环

In the training loop, images will now be automatically augmented according to their categories.在训练循环中,图像现在将根据其类别自动增强。

for images, labels in dataloader:
    # Perform your training steps here
    pass

这种设置确保每个类别都有特定的增强方式,这可以帮助模型学习每个类别特有的更强大和多样化的特征。当不同类别受益于不同类型的增强以突出其独特特征时,这种方法特别有用。


需要让一个批次中的所有样本进行两次数据增强即可。同一类别的样本属于正对,不同类别的样本属于负对。给出了 Pytroch 实现,以及相应的损失函数实现。

为了实现一个批次中的每个样本经过两次不同的数据增强的场景,其中相同类别的样本形成正对,不同类别的样本形成负对,可以使用像 SimCLR 这样的对比学习方法。
下面,修改 PyTorch 数据集和数据加载器设置,并专门针对此场景实现对比损失函数。

Step 1: Define Transformations第 1 步:定义转换

We’ll start by defining a common transformation that can be applied twice to each sample to generate two augmented versions.我们将首先定义一个通用转换,该转换可以对每个样本应用两次以生成两个增强版本。

import torchvision.transforms as transforms

# Define a transformation that can be applied twice to each sample
base_transform = transforms.Compose([
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5),
    transforms.RandomRotation(20),
    transforms.ToTensor()
])

Step 2: Create a Dataset with Dual Augmentation第 2 步:创建具有双重增强的数据集

Modify the dataset class to return two differently augmented versions of the same image for each data point.修改数据集类,为每个数据点返回同一图像的两个不同增强版本。

from torch.utils.data import Dataset
from PIL import Image

class ContrastiveDataset(Dataset):
    def __init__(self, image_paths, labels):
        self.image_paths = image_paths
        self.labels = labels

    def __len__(self):
        return len(self.image_paths)

    def __getitem__(self, idx):
        image_path = self.image_paths[idx]
        label = self.labels[idx]
        image = Image.open(image_path).convert('RGB')

        # Apply the transformation twice to the same image
        image1 = base_transform(image)
        image2 = base_transform(image)

        return image1, image2, label

Step 3: DataLoader第三步:数据加载器

Now, let’s set up the DataLoader that uses this dataset.现在,让我们设置使用此数据集的 DataLoader。

from torch.utils.data import DataLoader

# Example usage
image_paths = ["path_to_image1.jpg", "path_to_image2.jpg", ...]  # paths to images
labels = [0, 1, 2, 3, 4, 5, 6]  # corresponding labels

dataset = ContrastiveDataset(image_paths, labels)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

Step 4: Implement Contrastive Loss第四步:实施对比损失

For the contrastive loss, we’ll implement a simple version of NT-Xent (normalized temperature-scaled cross-entropy loss) which is commonly used in these settings.对于对比损失,我们将实现这些设置中常用的 NT-Xent(归一化温度缩放交叉熵损失)的简单版本。

import torch

def contrastive_loss(z_i, z_j, temperature):
    """
    Calculate contrastive loss (NT-Xent) between pairs of embeddings (z_i, z_j).
    """
    cos_sim = torch.nn.functional.cosine_similarity(z_i.unsqueeze(1), z_j.unsqueeze(0), dim=2)
    labels = torch.arange(cos_sim.size(0)).to(z_i.device)
    loss_fn = torch.nn.CrossEntropyLoss()
    loss = loss_fn(cos_sim / temperature, labels)
    return loss

Step 5: Training Loop第 5 步:训练循环

Integrate these components into your training loop.将这些组件集成到您的训练循环中。

import torch.optim as optim

# Define model, optimizer, and device setup
model = YourModel()  # Define your model architecture
optimizer = optim.Adam(model.parameters(), lr=0.001)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

for images1, images2, labels in dataloader:
    images1, images2 = images1.to(device), images2.to(device)
    optimizer.zero_grad()
    outputs1 = model(images1)
    outputs2 = model(images2)
    loss = contrastive_loss(outputs1, outputs2, temperature=0.1)
    loss.backward()
    optimizer.step()

此设置对每个样本应用两种不同的转换,使用输出来计算考虑正对(相同类别)和负对(不同类别)的对比损失,并反向传播误差以有效地训练模型。


5.5 修改 supConloss

要修改提供的 SupConLoss 来处理不同类别被视为负对、同一类别的样本被视为正对的情况,在使用真实类别标签时,我们需要确保掩码创建过程正确反映这些情况关系。现有的实现已经处理了这些关系,但让我们回顾并澄清以确保它符合您的需求:

Explanation of Mask in SupConLoss: SupConLoss 中掩码的说明:

  • Positive Pairs Mask: 正对掩码:现有实现构造一个掩码,如果两个样本属于同一类别(正对),则条目为 1 ,否则为 0 (负对)。这是通过使用标签比较 torch.eq(labels, labels.T) 来实现的,它将每个标签与其他标签进行比较。

  • Masking Self-comparisons: 屏蔽自我比较:然后调整原始掩模以消除自我比较(样本与自身比较),这对于对比学习至关重要。这是使用 logits_mask 完成的,除了对角线条目(自我比较)之外,它在任何地方都被构造为 1

鉴于这种理解,实现似乎与所描述的要求一致。但是,为了确保清晰度并满足任何特定需求,让我们稍微重构现有代码以增强可读性并验证正确性:

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

class SupConLoss(nn.Module):
    def __init__(self, temperature=0.06, device="cuda:0"):
        super(SupConLoss, self).__init__()
        self.temperature = temperature
        self.device = device

    def forward(self, projection1, projection2, labels=None):
        # Normalize the projections
        projection1, projection2 = F.normalize(projection1), F.normalize(projection2)
        
        # Stack projections to form features matrix
        features = torch.cat([projection1.unsqueeze(1), projection2.unsqueeze(1)], dim=1)
        batch_size = features.shape[0]
        
        # Prepare the mask
        if labels is None:
            mask = torch.eye(batch_size, dtype=torch.float32, device=self.device)
        else:
            labels = labels.contiguous().view(-1, 1)
            mask = torch.eq(labels, labels.T).float().to(self.device)
        
        # Unbind features for contrastive comparison
        contrast_feature = torch.cat(torch.unbind(features, dim=1), dim=0)
        
        # Compute similarity score scaled by temperature
        anchor_dot_contrast = torch.matmul(contrast_feature, contrast_feature.T) / self.temperature
        
        # Numerical stability adjustment
        logits_max, _ = torch.max(anchor_dot_contrast, dim=1, keepdim=True)
        logits = anchor_dot_contrast - logits_max.detach()
        
        # Avoid self-comparisons
        logits_mask = torch.ones_like(mask) - torch.eye(batch_size * 2, device=self.device)
        mask = mask.repeat(2, 2) * logits_mask
        
        # Compute the log probabilities
        exp_logits = torch.exp(logits) * logits_mask
        log_prob = logits - torch.log(exp_logits.sum(1, keepdim=True))
        
        # Compute loss as negative log of probabilities
        mean_log_prob_pos = (mask * log_prob).sum(1) / mask.sum(1)
        loss = -mean_log_prob_pos.mean()

        return loss

Key Changes & Validation:主要变更和验证:

  1. Normalization: Explicit normalization to ensure that the embeddings are on a unit sphere, which improves the stability of cosine similarity calculations.归一化:显式归一化确保嵌入在单位球面上,从而提高余弦相似度计算的稳定性。
  2. Mask Handling: Refactored to ensure it’s clear that we are correctly handling both the exclusion of self-comparisons and ensuring positive comparisons are only between samples of the same category. 掩模处理:重构以确保我们清楚地正确处理自我比较的排除并确保仅在同一类别的样本之间进行积极比较。
  3. Loss Calculation: Ensures the calculation of contrastive loss based on masked log probabilities, averaged over all positive pairings.损失计算:确保基于屏蔽对数概率计算对比损失,对所有正配对进行平均。

此重构不会改变初始实现的基本机制,而是旨在澄清每个步骤并确保功能符合涉及分类数据的场景中监督对比损失的典型期望。这应该可以有效地用于使用平衡数据集的分类任务,重点关注类别之间的区分,同时使同一类别内样本的表示更加接近。

  • 17
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值