损失函数

sentence_transformers.cross_encoder.losses 定义了可用于在训练数据上微调交叉编码器模型的不同损失函数。损失函数的选择在微调模型时起着至关重要的作用。它决定了我们的模型在特定下游任务上的表现如何。

遗憾的是,没有“一刀切”的损失函数。选择哪种损失函数取决于可用的训练数据和目标任务。请查阅损失函数概览以帮助您缩小损失函数的选择范围。

BinaryCrossEntropyLoss (二元交叉熵损失)

class sentence_transformers.cross_encoder.losses.BinaryCrossEntropyLoss(model: CrossEncoder, activation_fn: Module = Identity(), pos_weight: Tensor | None = None, **kwargs)[source]

计算 CrossEncoder 模型的二元交叉熵损失。该损失函数用于训练模型为正例对预测高 logit,为负例对预测低 logit。模型应使用 num_labels = 1(即默认值)进行初始化,以预测一个类别。

它已被用于训练许多强大的CrossEncoder MS MARCO 重排序模型

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型。

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。默认为 Identity

  • pos_weight (Tensor, 可选) – 正例的权重。必须是 torch.Tensor 类型,例如 torch.tensor(4) 表示权重为 4。默认为 None。

  • **kwargs – 传递给底层 torch.nn.BCEWithLogitsLoss 的额外关键字参数。

参考文献

要求
  1. 您的模型必须使用 num_labels = 1(即默认值)进行初始化以预测一个类别。

输入

文本

标签

模型输出标签数量

(锚点, 正例/负例) 对

正例为 1,负例为 0

1

(句子_A, 句子_B) 对

0 到 1 之间的浮点相似度分数

1

建议
  • 使用 mine_hard_negativesoutput_format="labeled-pair",将问答对转换为带有 1 或 0 标签的 (锚点, 正例/负例) 格式,并使用难负例。

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What are pandas?"],
    "response": ["Pandas are a kind of bear.", "Pandas are a kind of fish."],
    "label": [1, 0],
})
loss = losses.BinaryCrossEntropyLoss(model)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()

CrossEntropyLoss (交叉熵损失)

class sentence_transformers.cross_encoder.losses.CrossEntropyLoss(model: CrossEncoder, activation_fn: Module = Identity(), **kwargs)[source]

计算 CrossEncoder 模型的交叉熵损失。该损失函数用于训练模型为给定的句子对预测正确的类别标签。类别数量应等于模型输出标签的数量。

参数:

参考文献

要求
  1. 您的模型可以使用 num_labels > 1 进行初始化以预测多个类别。

  2. 数据集的类别数量应等于模型输出标签的数量 (model.num_labels)。

输入

文本

标签

模型输出标签数量

(句子_A, 句子_B) 对

类别

num_classes

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base", num_labels=2)
train_dataset = Dataset.from_dict({
    "sentence1": ["How can I be a good geologist?", "What is the capital of France?"],
    "sentence2": ["What should I do to be a great geologist?", "What is the capital of Germany?"],
    "label": [1, 0],  # 1: duplicate, 0: not duplicate
})
loss = losses.CrossEntropyLoss(model)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()

LambdaLoss

class sentence_transformers.cross_encoder.losses.LambdaLoss(model: ~sentence_transformers.cross_encoder.CrossEncoder.CrossEncoder, weighting_scheme: ~sentence_transformers.cross_encoder.losses.LambdaLoss.BaseWeightingScheme | None = NDCGLoss2PPScheme(   (ndcg_loss2): NDCGLoss2Scheme()   (lambda_rank): LambdaRankScheme() ), k: int | None = None, sigma: float = 1.0, eps: float = 1e-10, reduction_log: ~typing.Literal['natural', 'binary'] = 'binary', activation_fn: ~torch.nn.modules.module.Module | None = Identity(), mini_batch_size: int | None = None)[source]

用于排序指标优化的 LambdaLoss 框架。此损失函数实现了用于排序指标优化的 LambdaLoss 框架,该框架提供了包括 LambdaRank 和 NDCG 变体在内的各种加权方案。该实现经过优化,通过在模型推理期间仅处理有效文档来高效地处理填充文档。

注意

使用 LambdaLoss 时,每个查询的文档数量可以在样本之间变化。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型

  • weighting_scheme (BaseWeightingScheme, 可选) –

    用于损失的加权方案。

    默认为 NDCGLoss2PPScheme。在原始的 LambdaLoss 论文中,NDCGLoss2PPScheme 被证明能达到最强的性能,NDCGLoss2Scheme 紧随其后。

  • k (int, 可选) – 用于 NDCG@K 的文档数量。默认为 None(使用所有文档)。

  • sigma (float) – Sigmoid 中使用的得分差异权重

  • eps (float) – 用于数值稳定性的小常数

  • reduction_log (str) – 使用的对数类型 - “natural”: 自然对数 (log) - “binary”: 二进制对数 (log2)

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。默认为 Identity

  • mini_batch_size (int, 可选) –

    每次前向传播中处理的样本数量。这对内存消耗和训练过程的速度有显著影响。可能出现三种情况:

    • 如果 mini_batch_size 为 None,则 mini_batch_size 设置为批大小。

    • 如果 mini_batch_size 大于 0,则将批次拆分为大小为 mini_batch_size 的小批次。

    • 如果 mini_batch_size <= 0,则一次性处理整个批次。

    默认为 None。

参考文献

要求
  1. 带有多个文档的查询(列表式方法)

  2. 文档必须有相关性分数/标签。支持二进制和连续标签。

输入

文本

标签

模型输出标签数量

(查询, [文档1, 文档2, …, 文档N])

[分数1, 分数2, …, 分数N]

1

建议
  • 使用 mine_hard_negativesoutput_format="labeled-list",将问答对转换为所需的输入格式,并使用难负例。

关系
  • 据传闻,LambdaLoss 在相同输入格式下比其他损失函数表现更好。

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "docs": [
        ["Pandas are a kind of bear.", "Pandas are kind of like fish."],
        ["The capital of France is Paris.", "Paris is the capital of France.", "Paris is quite large."],
    ],
    "labels": [[1, 0], [1, 1, 0]],
})
loss = losses.LambdaLoss(model)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()
class sentence_transformers.cross_encoder.losses.LambdaLoss.BaseWeightingScheme(*args, **kwargs)[source]

在 LambdaLoss 中实现加权方案的基类。

class sentence_transformers.cross_encoder.losses.NoWeightingScheme(*args, **kwargs)[source]

无加权方案的实现(权重 = 1.0)。

class sentence_transformers.cross_encoder.losses.NDCGLoss1Scheme(*args, **kwargs)[source]

NDCG Loss1 加权方案的实现。

它用于优化 NDCG 指标,但不推荐使用此加权方案,因为在原始的 LambdaLoss 论文中,NDCGLoss2Scheme 和 NDCGLoss2PPScheme 已被证明能达到更优的性能。

class sentence_transformers.cross_encoder.losses.NDCGLoss2Scheme(*args, **kwargs)[source]

NDCG Loss2 加权方案的实现。

该方案使用比 NDCGLoss1Scheme 更紧的界限,并在原始 LambdaLoss 论文中被证明能达到更优的性能。它用于优化 NDCG 指标。

class sentence_transformers.cross_encoder.losses.LambdaRankScheme(*args, **kwargs)[source]

LambdaRank 加权方案的实现。

这种加权方式优化了 NDCG 的一个粗略上界。

class sentence_transformers.cross_encoder.losses.NDCGLoss2PPScheme(mu: float = 10.0)[source]

NDCG Loss2++ 加权方案的实现。

它是一种混合加权方案,结合了 NDCGLoss2 和 LambdaRank 方案。在原始的 LambdaLoss 论文中,它被证明能达到最强的性能。

ListMLELoss

class sentence_transformers.cross_encoder.losses.ListMLELoss(model: CrossEncoder, activation_fn: Module | None = Identity(), mini_batch_size: int | None = None, respect_input_order: bool = True)[source]

此损失函数实现了 ListMLE 学习排序算法,该算法使用基于最大似然估计的列表式方法来估计排列。它最大化了由真实标签引起的排列的似然性。

注意

使用 ListMLELoss 时,每个查询的文档数量可以在样本之间变化。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。默认为 Identity

  • mini_batch_size (int, 可选) –

    每次前向传播中处理的样本数量。这对内存消耗和训练过程的速度有显著影响。可能出现三种情况:

    • 如果 mini_batch_size 为 None,则 mini_batch_size 设置为批大小。

    • 如果 mini_batch_size 大于 0,则将批次拆分为大小为 mini_batch_size 的小批次。

    • 如果 mini_batch_size <= 0,则一次性处理整个批次。

    默认为 None。

  • respect_input_order (bool) – 是否尊重原始输入文档的顺序。如果为 True,则假定输入文档已按相关性排序(最相关的在前)。如果为 False,则按标签值对文档进行排序。默认为 True。

参考文献

要求
  1. 带有多个文档的查询(列表式方法)

  2. 文档必须有相关性分数/标签。支持二进制和连续标签。

  3. 文档必须按定义的排名顺序排序。

输入

文本

标签

模型输出标签数量

(查询, [文档1, 文档2, …, 文档N])

[分数1, 分数2, …, 分数N]

1

建议
  • 使用 mine_hard_negativesoutput_format="labeled-list",将问答对转换为所需的输入格式,并使用难负例。

关系

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "docs": [
        ["Pandas are a kind of bear.", "Pandas are kind of like fish."],
        ["The capital of France is Paris.", "Paris is the capital of France.", "Paris is quite large."],
    ],
    "labels": [[1, 0], [1, 1, 0]],
})

# Standard ListMLE loss respecting input order
loss = losses.ListMLELoss(model)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()

PListMLELoss

class sentence_transformers.cross_encoder.losses.PListMLELoss(model: CrossEncoder, lambda_weight: PListMLELambdaWeight | None = PListMLELambdaWeight(), activation_fn: Module | None = Identity(), mini_batch_size: int | None = None, respect_input_order: bool = True)[source]

用于带位置感知加权的学习排序的 PListMLE 损失。此损失函数实现了 ListMLE 排序算法,该算法使用基于最大似然估计的列表式方法来估计排列。它通过位置感知加权最大化了由真实标签引起的排列的似然性。

这种损失也被称为位置感知 ListMLE 或 p-ListMLE。

注意

使用 PListMLELoss 时,每个查询的文档数量可以在样本之间变化。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型

  • lambda_weight (PListMLELambdaWeight, 可选) – 使用的加权方案。指定时,实现位置感知 ListMLE,它对不同的排名位置应用不同的权重。默认为 None(标准的 PListMLE)。

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。默认为 Identity

  • mini_batch_size (int, 可选) –

    每次前向传播中处理的样本数量。这对内存消耗和训练过程的速度有显著影响。可能出现三种情况:

    • 如果 mini_batch_size 为 None,则 mini_batch_size 设置为批大小。

    • 如果 mini_batch_size 大于 0,则将批次拆分为大小为 mini_batch_size 的小批次。

    • 如果 mini_batch_size <= 0,则一次性处理整个批次。

    默认为 None。

  • respect_input_order (bool) – 是否尊重原始输入文档的顺序。如果为 True,则假定输入文档已按相关性排序(最相关的在前)。如果为 False,则按标签值对文档进行排序。默认为 True。

参考文献

要求
  1. 带有多个文档的查询(列表式方法)

  2. 文档必须有相关性分数/标签。支持二进制和连续标签。

  3. 文档必须按定义的排名顺序排序。

输入

文本

标签

模型输出标签数量

(查询, [文档1, 文档2, …, 文档N])

[分数1, 分数2, …, 分数N]

1

建议
  • 使用 mine_hard_negativesoutput_format="labeled-list",将问答对转换为所需的输入格式,并使用难负例。

关系

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "docs": [
        ["Pandas are a kind of bear.", "Pandas are kind of like fish."],
        ["The capital of France is Paris.", "Paris is the capital of France.", "Paris is quite large."],
    ],
    "labels": [[1, 0], [1, 1, 0]],
})

# Either: Position-Aware ListMLE with default weighting
lambda_weight = losses.PListMLELambdaWeight()
loss = losses.PListMLELoss(model, lambda_weight=lambda_weight)

# or: Position-Aware ListMLE with custom weighting function
def custom_discount(ranks): # e.g. ranks: [1, 2, 3, 4, 5]
    return 1.0 / torch.log1p(ranks)
lambda_weight = losses.PListMLELambdaWeight(rank_discount_fn=custom_discount)
loss = losses.PListMLELoss(model, lambda_weight=lambda_weight)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()
class sentence_transformers.cross_encoder.losses.PListMLELambdaWeight(rank_discount_fn=None)[source]

在位置感知 ListMLE 损失中实现加权方案的基类。

为 PListMLE 损失初始化一个 lambda 权重。

参数:

rank_discount_fn – 为每个排名位置计算折扣的函数。如果为 None,则使用默认折扣 2^(文档数 - 排名) - 1。

ListNetLoss

class sentence_transformers.cross_encoder.losses.ListNetLoss(model: CrossEncoder, activation_fn: Module | None = Identity(), mini_batch_size: int | None = None)[source]

用于学习排序的 ListNet 损失。此损失函数实现了 ListNet 排序算法,该算法使用列表式方法学习排序模型。它最小化了预测排名分布与真实排名分布之间的交叉熵。该实现经过优化,通过在模型推理期间仅处理有效文档来高效地处理填充文档。

注意

使用 ListNetLoss 时,每个查询的文档数量可以在样本之间变化。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。默认为 Identity

  • mini_batch_size (int, 可选) –

    每次前向传播中处理的样本数量。这对内存消耗和训练过程的速度有显著影响。可能出现三种情况:

    • 如果 mini_batch_size 为 None,则 mini_batch_size 设置为批大小。

    • 如果 mini_batch_size 大于 0,则将批次拆分为大小为 mini_batch_size 的小批次。

    • 如果 mini_batch_size <= 0,则一次性处理整个批次。

    默认为 None。

参考文献

要求
  1. 带有多个文档的查询(列表式方法)

  2. 文档必须有相关性分数/标签。支持二进制和连续标签。

输入

文本

标签

模型输出标签数量

(查询, [文档1, 文档2, …, 文档N])

[分数1, 分数2, …, 分数N]

1

建议
  • 使用 mine_hard_negativesoutput_format="labeled-list",将问答对转换为所需的输入格式,并使用难负例。

关系
  • LambdaLoss 接受相同的输入,并且通常优于此损失函数。

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "docs": [
        ["Pandas are a kind of bear.", "Pandas are kind of like fish."],
        ["The capital of France is Paris.", "Paris is the capital of France.", "Paris is quite large."],
    ],
    "labels": [[1, 0], [1, 1, 0]],
})
loss = losses.ListNetLoss(model)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()

MultipleNegativesRankingLoss (多负例排序损失)

class sentence_transformers.cross_encoder.losses.MultipleNegativesRankingLoss(model: CrossEncoder, num_negatives: int | None = 4, scale: int = 10.0, activation_fn: Module | None = Sigmoid())[source]

给定一个 (anchor, positive) 对或 (anchor, positive, negative) 三元组列表,此损失函数优化以下目标

  • 给定一个锚点(例如一个问题),在批次中的每一个正例和负例(例如所有答案)中,为对应的正例(即答案)赋予最高的相似度。

如果您提供了可选的负例,它们都将作为额外选项使用,模型必须从中选择正确的正例。在合理范围内,这种“选择”越困难,模型就会变得越强大。因此,更高的批次大小会导致更多的批内负例,从而(在一定程度上)提高性能。

此损失函数非常适合训练用于检索设置的嵌入,其中您有正例对(例如 (查询, 答案)),因为它会在每个批次中随机抽样 n-1 个负例文档。

此损失函数也称为 InfoNCE 损失、SimCSE 损失、带批内负例的交叉熵损失,或简称为批内负例损失。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型。

  • num_negatives (int, 可选) – 为每个锚点抽样的批内负例数量。默认为 4。

  • scale (int, 可选) – 相似度函数的输出乘以缩放值。默认为 10.0。

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。默认为 Sigmoid

注意

当前的默认值将来可能会更改。鼓励进行实验。

参考文献

要求
  1. 您的模型必须使用 num_labels = 1(即默认值)进行初始化以预测一个类别。

输入

文本

标签

模型输出标签数量

(锚点, 正例) 对

1

(锚点, 正例, 负例) 三元组

1

(anchor, positive, negative_1, ..., negative_n)

1

建议
  • 使用 BatchSamplers.NO_DUPLICATES (文档) 确保批内负例不是锚点或正例样本的副本。

  • 使用 mine_hard_negativesoutput_format="n-tuple"output_format="triplet",将问答对转换为带有难负例的三元组。

关系
  • CachedMultipleNegativesRankingLoss 与此损失函数等效,但它使用缓存,允许在不增加额外内存使用的情况下实现更高的批次大小(从而获得更好的性能)。但是,它稍慢一些。

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "answer": ["Pandas are a kind of bear.", "The capital of France is Paris."],
})
loss = losses.MultipleNegativesRankingLoss(model)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()

CachedMultipleNegativesRankingLoss

class sentence_transformers.cross_encoder.losses.CachedMultipleNegativesRankingLoss(model: CrossEncoder, num_negatives: int | None = 4, scale: float = 10.0, activation_fn: Module | None = Sigmoid(), mini_batch_size: int = 32, show_progress_bar: bool = False)[source]

MultipleNegativesRankingLoss 的增强版,它缓存了 logit 相对于损失的梯度。这允许在不增加额外内存使用的情况下实现更高的批次大小。但是,它稍慢一些。

详细来说

  1. 它首先执行一个快速的预测步骤,没有梯度/计算图,以获取所有 logit;

  2. 计算损失,反向传播到 logit,并缓存相对于 logit 的梯度;

  3. 第二次预测步骤,带有梯度/计算图,并将缓存的梯度连接到反向传播链中。

注意:所有步骤都是以小批量方式完成的。在 GradCache 的原始实现中,步骤 (2) 不是以小批量方式完成的,当批次大小很大时需要大量内存。根据论文,梯度缓存会牺牲大约 20% 的计算时间。

给定一个 (anchor, positive) 对或 (anchor, positive, negative) 三元组列表,此损失函数优化以下目标

  • 给定一个锚点(例如一个问题),在批次中的每一个正例和负例(例如所有答案)中,为对应的正例(即答案)赋予最高的相似度。

如果您提供了可选的负例,它们都将作为额外选项使用,模型必须从中选择正确的正例。在合理范围内,这种“选择”越困难,模型就会变得越强大。因此,更高的批次大小会导致更多的批内负例,从而(在一定程度上)提高性能。

此损失函数非常适合训练用于检索设置的嵌入,其中您有正例对(例如 (查询, 答案)),因为它会在每个批次中随机抽样 n-1 个负例文档。

此损失也称为带 GradCache 的 InfoNCE 损失。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型。

  • num_negatives (int, 可选) – 为每个锚点抽样的批内负例数量。默认为 4。

  • scale (int, 可选) – 相似度函数的输出乘以缩放值。默认为 10.0。

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。默认为 Sigmoid

  • mini_batch_size (int, 可选) – 前向传播的小批量大小。这决定了内存使用情况。默认为 32。

  • show_progress_bar (bool, 可选) – 是否在前向传播期间显示进度条。默认为 False。

注意

当前的默认值将来可能会更改。鼓励进行实验。

参考文献

要求
  1. 您的模型必须使用 num_labels = 1(即默认值)进行初始化以预测一个类别。

  2. 应与大的 per_device_train_batch_size 和小的 mini_batch_size 一起使用以获得更优的性能,但训练时间比 MultipleNegativesRankingLoss 慢。

输入

文本

标签

模型输出标签数量

(锚点, 正例) 对

1

(锚点, 正例, 负例) 三元组

1

(anchor, positive, negative_1, ..., negative_n)

1

建议
  • 使用 BatchSamplers.NO_DUPLICATES (文档) 确保批内负例不是锚点或正例样本的副本。

  • 使用 mine_hard_negativesoutput_format="n-tuple"output_format="triplet",将问答对转换为带有难负例的三元组。

关系

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "answer": ["Pandas are a kind of bear.", "The capital of France is Paris."],
})
loss = losses.CachedMultipleNegativesRankingLoss(model, mini_batch_size=32)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()

MSELoss (均方误差损失)

class sentence_transformers.cross_encoder.losses.MSELoss(model: CrossEncoder, activation_fn: Module = Identity(), **kwargs)[source]

计算计算出的查询-段落分数与目标查询-段落分数之间的均方误差损失。此损失用于从教师交叉编码器模型或黄金标签中蒸馏出交叉编码器模型。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型。

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。

  • **kwargs – 传递给底层 torch.nn.MSELoss 的额外关键字参数。

注意

请注意标签和模型产生的值的大小。如果教师模型使用 Sigmoid 函数将其 logits 限制在 [0, 1] 范围内,那么您可能希望在损失中使用 Sigmoid 激活函数。

参考文献

要求
  1. 您的模型必须使用 num_labels = 1(即默认值)进行初始化以预测一个类别。

  2. 通常在知识蒸馏设置中使用经过微调的 CrossEncoder 教师模型 M。

输入

文本

标签

模型输出标签数量

(句子_A, 句子_B) 对

相似度分数

1

关系
  • MarginMSELoss 与此损失类似,但通过一个负例对引入了边距。

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

student_model = CrossEncoder("microsoft/mpnet-base")
teacher_model = CrossEncoder("cross-encoder/ms-marco-MiniLM-L12-v2")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "answer": ["Pandas are a kind of bear.", "The capital of France is Paris."],
})

def compute_labels(batch):
    return {
        "label": teacher_model.predict(list(zip(batch["query"], batch["answer"])))
    }

train_dataset = train_dataset.map(compute_labels, batched=True)
loss = losses.MSELoss(student_model)

trainer = CrossEncoderTrainer(
    model=student_model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()

MarginMSELoss (边距均方误差损失)

class sentence_transformers.cross_encoder.losses.MarginMSELoss(model: CrossEncoder, activation_fn: Module = Identity(), **kwargs)[source]

计算 |sim(查询, 正例) - sim(查询, 负例)||gold_sim(查询, 正例) - gold_sim(查询, 负例)| 之间的均方误差损失。此损失通常用于从教师交叉编码器模型或黄金标签中蒸馏出交叉编码器模型。

MultipleNegativesRankingLoss 不同,这两个段落不必严格是正例和负例,它们都可以与给定的查询相关或不相关。这可能是 MarginMSELoss 相对于 MultipleNegativesRankingLoss 的一个优势。

注意

请注意标签和模型产生的值的大小。如果教师模型使用 Sigmoid 函数将其 logits 限制在 [0, 1] 范围内,那么您可能希望在损失中使用 Sigmoid 激活函数。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型。

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。

  • **kwargs – 传递给底层 torch.nn.MSELoss 的额外关键字参数。

参考文献

要求
  1. 您的模型必须使用 num_labels = 1(即默认值)进行初始化以预测一个类别。

  2. 通常在知识蒸馏设置中使用经过微调的 CrossEncoder 教师模型 M。

输入

文本

标签

模型输出标签数量

(查询, 段落_一, 段落_二) 三元组

gold_sim(查询, 段落_一) - gold_sim(查询, 段落_二)

1

(查询, 段落_一, 段落_二) 三元组

[gold_sim(查询, 段落一), gold_sim(查询, 段落二)]

1

(查询, 正例, 负例_1, ..., 负例_n)

[gold_sim(查询, 正例) - gold_sim(查询, 负例_i) for i in 1..n]

1

(查询, 正例, 负例_1, ..., 负例_n)

[gold_sim(查询, 正例), gold_sim(查询, 负例_1), …, gold_sim(查询, 负例_n)]

1

关系
  • MSELoss 与此损失类似,但没有通过负例对引入边距。

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

student_model = CrossEncoder("microsoft/mpnet-base")
teacher_model = CrossEncoder("cross-encoder/ms-marco-MiniLM-L12-v2")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "positive": ["Pandas are a kind of bear.", "The capital of France is Paris."],
    "negative": ["Pandas are a kind of fish.", "The capital of France is Berlin."],
})

def compute_labels(batch):
    positive_scores = teacher_model.predict(list(zip(batch["query"], batch["positive"])))
    negative_scores = teacher_model.predict(list(zip(batch["query"], batch["negative"])))
    return {
        "label": positive_scores - negative_scores
    }

train_dataset = train_dataset.map(compute_labels, batched=True)
loss = losses.MarginMSELoss(student_model)

trainer = CrossEncoderTrainer(
    model=student_model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()

RankNetLoss

class sentence_transformers.cross_encoder.losses.RankNetLoss(model: CrossEncoder, k: int | None = None, sigma: float = 1.0, eps: float = 1e-10, reduction_log: Literal['natural', 'binary'] = 'binary', activation_fn: Module | None = Identity(), mini_batch_size: int | None = None)[source]

用于学习排序的 RankNet 损失实现。此损失函数实现了 RankNet 算法,该算法通过使用神经网络优化成对的文档比较来学习排序函数。该实现经过优化,通过在模型推理期间仅处理有效文档来高效地处理填充文档。

参数:
  • model (CrossEncoder) – 待训练的 CrossEncoder 模型

  • sigma (float) – Sigmoid 中使用的得分差异权重(默认值:1.0)

  • eps (float) – 用于数值稳定性的小常数(默认值:1e-10)

  • activation_fn (Module) – 在计算损失前应用于 logit 的激活函数。默认为 Identity

  • mini_batch_size (int, 可选) – 每次前向传播中处理的样本数量。这对内存消耗和训练过程的速度有显著影响。可能出现三种情况:- 如果 mini_batch_size 为 None,则 mini_batch_size 设置为批大小。- 如果 mini_batch_size 大于 0,则将批次拆分为大小为 mini_batch_size 的小批次。- 如果 mini_batch_size <= 0,则一次性处理整个批次。默认为 None。

参考文献

要求
  1. 带有多个文档的查询(成对方法)

  2. 文档必须有相关性分数/标签。支持二进制和连续标签。

输入

文本

标签

模型输出标签数量

(查询, [文档1, 文档2, …, 文档N])

[分数1, 分数2, …, 分数N]

1

建议
  • 使用 mine_hard_negativesoutput_format="labeled-list",将问答对转换为所需的输入格式,并使用难负例。

关系
  • LambdaLoss 可以看作是此损失的扩展,其中每个得分对都进行了加权。或者,此损失可以看作是 LambdaLoss 的一个特例,没有加权方案。

  • 据传闻,LambdaLoss 及其默认的 NDCGLoss2++ 加权方案在相同输入格式下比其他损失函数表现更好。

示例

from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
from datasets import Dataset

model = CrossEncoder("microsoft/mpnet-base")
train_dataset = Dataset.from_dict({
    "query": ["What are pandas?", "What is the capital of France?"],
    "docs": [
        ["Pandas are a kind of bear.", "Pandas are kind of like fish."],
        ["The capital of France is Paris.", "Paris is the capital of France.", "Paris is quite large."],
    ],
    "labels": [[1, 0], [1, 1, 0]],
})
loss = losses.RankNetLoss(model)

trainer = CrossEncoderTrainer(
    model=model,
    train_dataset=train_dataset,
    loss=loss,
)
trainer.train()