timm documentation
损失
损失
本页包含 timm 中分类损失的 API 参考文档,并概述了如何通过损失工厂创建和配置这些损失。
用法
损失函数通过名称使用 create_classification_loss 创建。multi_label 用于在单标签目标(类别索引,或来自 Mixup/CutMix 的稠密软分布)和多标签目标(形状为 (B, C) 的稠密独立二值标签)之间进行选择。当 loss_type=None 时,工厂方法会根据情况选择 ce 或 bce。特定于损失函数的参数以损失名称为前缀(asl_*、poly_*、db_*、…),其他损失函数会忽略这些参数。如果组合不被某个损失函数支持,工厂方法会抛出异常,例如:对于除 bce / 多标签 asl 以外的损失函数使用类别权重,对于其他损失函数使用 bce_* 或 class_counts 参数,或者在未设置 multi_label 的情况下使用仅限多标签的损失函数(或在设置了 multi_label 的情况下使用仅限单标签的损失函数)。
import torch
import timm
from timm.data import Mixup
from timm.loss import PolyCrossEntropy, create_classification_loss
# Single-label, class index targets. Label smoothing selects LabelSmoothingCrossEntropy.
criterion = create_classification_loss(smoothing=0.1)
loss = criterion(torch.randn(8, 1000), torch.randint(0, 1000, (8,)))
# Mixup/CutMix output dense soft targets with the smoothing already applied, SoftTargetCrossEntropy.
mixup_fn = Mixup(mixup_alpha=0.8, cutmix_alpha=1.0, label_smoothing=0.1, num_classes=1000)
criterion = create_classification_loss(smoothing=0.1, soft_targets=True)
images, target = mixup_fn(torch.randn(8, 3, 224, 224), torch.randint(0, 1000, (8,)))
loss = criterion(torch.randn(8, 1000), target)
# Multi-label, dense (B, C) binary targets. BCE by default, other losses by name.
criterion = create_classification_loss(multi_label=True)
criterion = create_classification_loss('asl', multi_label=True, asl_gamma_neg=4., asl_gamma_pos=1., asl_clip=0.05)
loss = criterion(torch.randn(8, 6), torch.randint(0, 2, (8, 6)).float())
# The training tasks create their criterion with the factory, multi_label is set by the task.
from timm.task import MultiLabelClassificationTask
model = timm.create_model('resnet18', num_classes=6)
task = MultiLabelClassificationTask(model, criterion_kwargs=dict(loss_type='zlpr'))
# Losses can also be constructed directly, note the class defaults can differ from the factory's (below).
criterion = PolyCrossEntropy(epsilon=2.)训练脚本(train.py)将其选项映射到损失工厂的方式如下:
| CLI 选项或条件 | 工厂参数或效果 |
|---|---|
--loss | loss_type |
--task multilabel | multi_label=True |
--smoothing | smoothing,单标签训练的默认值为 0.1,多标签训练的默认值为 0 |
| 已启用 Mixup 或 CutMix | soft_targets=True |
--asl-* | 对应的 asl_* 参数 |
--poly-* | 对应的 poly_* 参数 |
--twoway-* | 对应的 twoway_* 参数 |
--db-* | 对应的 db_* 参数 |
--bce-sum | bce_sum |
--bce-target-thresh | bce_target_thresh |
--aug-splits | jsd_splits |
--class-stats | 以下类权重函数的类别计数,以及 db 的 class_counts / num_samples |
--loss-pos-weight | pos_weight,由下方的类权重函数解析 |
--loss-class-weight | class_weight,由下方的类权重函数解析 |
--loss-weight-* | 以下类权重函数的选项 |
有关命令行用法,请参阅训练文档。
损失类型
LOSS_TYPES 包含工厂接受的名称,MULTI_LABEL_LOSS_TYPES 包含可与 multi_label=True 一起使用的名称。
loss_type | 类 | 目标 | 备注 |
|---|---|---|---|
ce | nn.CrossEntropyLoss, LabelSmoothingCrossEntropy, SoftTargetCrossEntropy | 单标签 | Softmax 交叉熵,类别取决于 smoothing 和 soft_targets。单标签默认 |
bce | BinaryCrossEntropy | 两者 | Sigmoid BCE,多标签默认值。类别索引目标采用 one-hot 编码,bce_target_thresh 用于将软目标二值化,bce_sum 在按批次取平均之前对类别求和 |
asl | AsymmetricLossMultiLabel, AsymmetricLossSingleLabel | 两者 | 非对称损失,对正样本(asl_gamma_pos)和负样本(asl_gamma_neg)分别进行聚焦,并对负样本设置概率间隔(asl_clip,仅适用于多标签)。单标签(softmax)变体需要类别索引目标,不支持 Mixup/CutMix |
poly | PolyBinaryCrossEntropy, PolyCrossEntropy | 两者 | Poly-1,在 BCE / CE 的基础上添加 poly_epsilon * (1 - p_t),当 0 时退化为 BCE / CE。针对多标签任务,可选的焦点项(poly_gamma)和平衡项(poly_alpha) |
jsd | JsdCrossEntropy | 单标签 | 在干净划分上的 CE + 在 jsd_splits 个增强划分上的 Jensen-Shannon 散度(AugMix) |
twoway | TwoWayLoss | 多标签 | 双向多标签损失,温度 twoway_tp / twoway_tn,仅限二分类目标 |
zlpr | ZlprLoss | 多标签 | ZLPR,softmax CE 的多标签扩展,无需超参数,仅支持二值目标 |
db | DistributionBalancedLoss | 多标签 | 用于长尾数据的分布平衡损失,需要class_counts和num_samples |
标签平滑和软目标
smoothing 在工厂中默认为 0。对于单标签目标,目标类别的值为 1 - s + s / C,其他类别为 s / C(LabelSmoothingCrossEntropy 等价于 nn.CrossEntropyLoss(label_smoothing=s)),bce 对类别索引目标使用相同的 one-hot 平滑。对于多标签目标,每个二元标签都会向 0.5 移动,即 y * (1 - s) + 0.5 * s。
timm.data.Mixup 在混合过程中应用其 label_smoothing,并输出稠密目标(当 multi_label=True 时,它会混合并平滑稠密的多标签目标)。在这种情况下,创建损失函数时请使用 soft_targets=True:
ce变为SoftTargetCrossEntropy。bce、多标签asl、poly和db不会再次对目标进行平滑。- 单标签
asl在使用soft_targets时会抛出异常。 twoway/zlpr在使用soft_targets或smoothing时会引发错误,因为它们会将目标二值化为 0.5。
直接构造这些类时,它们各自拥有默认值:BinaryCrossEntropy、LabelSmoothingCrossEntropy 和 JsdCrossEntropy 的默认值为 smoothing=0.1,而 AsymmetricLossSingleLabel 的默认值为 eps=0.1(即其标签平滑参数)。
类别权重
pos_weight 会乘以每个类别的正项,用于在类别内部平衡正样本与负样本。class_weight 会乘以每个类别的整体损失,用于平衡不同类别之间的关系。两者均接受单个值或每个类别一个值,并受 bce 和多标签 asl 支持。可以显式指定这些权重,也可以通过 compute_class_weights 根据每个类别的正样本数量推导得出,该函数会返回权重所对应的损失参数以及权重本身。没有正样本的类别会被计为一个正样本,且 max_weight 会对最终权重设置上限。
method | 参数 | 包含 n 个正样本的类别的权重 |
|---|---|---|
neg_pos | pos_weight | ((num_samples - n) / n) ** power |
inv_freq | class_weight | (num_samples / n) ** power,归一化至均值为 1 |
effective_num | class_weight | (1 - beta) / (1 - beta ** n)(class-balanced),归一化至均值为 1 |
这些方法位于 CLASS_WEIGHT_METHODS 中,CLASS_WEIGHT_METHOD_KINDS 将每个方法映射到其对应的损失参数。
load_class_stats从 JSON 文件中读取计数,该文件包含pos_counts和num_samples条目,由仓库根目录中的class_weights.py写入。load_class_weights解析显式权重(一个数字、逗号分隔的字符串、一个列表,或一个 JSON / 文本文件)。resolve_class_weights接受方法名称或显式权重,正如train.py对其标志所做的那样。
db 损失直接采用计数。
import torch
from timm.loss import compute_class_weights, create_classification_loss, resolve_class_weights
pos_counts = [120, 3400, 560, 45, 980, 2100] # positives per class
num_samples = 5000
kind, weights = compute_class_weights(pos_counts, num_samples, method='neg_pos', power=0.5) # kind == 'pos_weight'
criterion = create_classification_loss(multi_label=True, pos_weight=weights)
# Method names (w/ class stats) or explicit weights, class_stats can be loaded w/ load_class_stats('stats.json')
class_stats = (torch.tensor(pos_counts), num_samples)
class_weight = resolve_class_weights('effective_num', 'class_weight', class_stats=class_stats, beta=0.999)
pos_weight = resolve_class_weights('2.0', 'pos_weight')
criterion = create_classification_loss('asl', multi_label=True, class_weight=class_weight, pos_weight=pos_weight)
criterion = create_classification_loss('db', multi_label=True, class_counts=pos_counts, num_samples=num_samples)损失说明
精度。多标签 ASL、Poly-1、DB、Two-way 和 ZLPR 损失函数始终在
float32精度下计算,与 logit 的数据类型无关;否则,低精度(float16)下的 ASL 概率会导致其对数钳位运算发生下溢。归约。 多标签 ASL 支持以下
asl_reduction值:值 在类上 在批次上 备注 batchmean求和 均值 默认 sum求和 求和 原始 ASL 归约方式;损失值随批大小缩放 mean均值 均值 与 BCE 单标签 ASL 对类别求和并对批次取平均,工厂仅接受
batchmean。bce、多标签poly和db对批次和类别取平均(bce_sum对bce的类别求和)。双向对比每个样本各类别中最难负样本的 logit 与最难正样本的 logit,以及每个类别各样本中最难负样本的 logit 与最难正样本的 logit,仅包含正样本的样本/类别会参与计算。其 logit 是排序分数,而非经过校准的 sigmoid 概率,因此基于阈值的指标(F1)没有意义,请使用 mAP。
ZLPR 将每个正样本的 logit 推高到超过所有负样本的 logit,并以 0 作为决策阈值,因此 logit > 0(sigmoid > 0.5)预测为正样本。
DB 根据类别级与实例级采样概率的比值对每个(样本,类别)项进行加权,并考虑标签共现情况,通过类别先验(
db_init_bias)平移 logits,并对负 logits 进行缩放(db_neg_scale)。计数值被截断至[1, num_samples - 1]。重平衡映射参数和 focal balance 是类参数,未通过工厂方法暴露。JSD 要求将批次划分为
jsd_splits个相等的部分,且干净图像排在前面(如fast_collate对AugMixDataset样本的排列方式),CE 项仅使用干净部分。JSD 权重(alpha=12)是一个类参数。
API
工厂函数
timm.loss.create_classification_loss
< source >( loss_type: typing.Optional[str] = Nonemulti_label: bool = Falsesmoothing: float = 0.0soft_targets: bool = Falseclass_weight: typing.Union[torch.Tensor, float, typing.Sequence[float], NoneType] = Nonepos_weight: typing.Union[torch.Tensor, float, typing.Sequence[float], NoneType] = Nonebce_target_thresh: typing.Optional[float] = Nonebce_sum: bool = Falseasl_gamma_pos: float = 1.0asl_gamma_neg: float = 4.0asl_clip: typing.Optional[float] = 0.05asl_reduction: str = 'batchmean'poly_epsilon: float = 2.0poly_gamma: float = 0.0poly_alpha: typing.Optional[float] = Nonejsd_splits: int = 0twoway_tp: float = 4.0twoway_tn: float = 1.0class_counts: typing.Union[torch.Tensor, typing.Sequence[float], NoneType] = Nonenum_samples: typing.Optional[int] = Nonedb_neg_scale: float = 2.0db_init_bias: float = 0.05db_focal_gamma: float = 2.0 )
参数
- loss_type — LOSS_TYPES 之一,None 表示多标签目标选择 ‘bce’,单标签目标选择 ‘ce’。 ‘ce’:softmax 交叉熵(根据需要支持标签平滑 / 软目标变体), ‘bce’:二元交叉熵(bce 参数), ‘asl’:非对称损失,多标签目标使用 AsymmetricLossMultiLabel,否则使用 softmax AsymmetricLossSingleLabel,仅支持类别索引目标,不支持 Mixup/CutMix(asl_ 参数), ‘poly’:Poly-1 损失,多标签目标使用 PolyBinaryCrossEntropy(sigmoid),否则使用 softmax PolyCrossEntropy(poly* 参数), ‘jsd’:Jensen-Shannon 散度 + 增强分割上的 CE,仅限单标签(jsd_splits), ‘twoway’:双向损失,仅限二元多标签目标(twoway 参数), ‘zlpr’:ZLPR 损失,仅限二元多标签目标, ‘db’:分布平衡损失,多标签(classcounts, num_samples, db 参数)。
- multi_label — 目标为形状为 (B, C) 的稠密独立二分类标签。
- smoothing — 标签平滑因子。当设置了 soft_targets 时将被忽略,因为 Mixup/CutMix 在生成软标签时已经应用了它。
- soft_targets — 目标以来自 Mixup/CutMix 的稠密软分布形式提供,而非类别索引。
- class_weight — 每个类别的损失权重,可以是单个值,也可以是每个类别一个值(适用于‘bce’和多标签‘asl’)。
- pos_weight — 正项权重,单个值或每个类别一个值(‘bce’ 和多标签 ‘asl’)。
- bce_target_thresh — 将此值以上的软标签二值化(仅限‘bce’)。
- bce_sum — 在按批次取平均之前,先对各类别的损失求和(仅适用于‘bce’)。
- asl_gamma_pos — 正样本目标的聚焦参数(仅限 ‘asl’)。
- asl_gamma_neg — 负样本目标的聚焦参数(仅限 ‘asl’)。
- asl_clip — 概率边距向负样本偏移,设为 None 或 0 可禁用(仅适用于多标签 'asl')。
- asl_reduction — ‘batchmean’(对类别求和,对批次求平均)、‘sum’(原始 ASL)或 ‘mean’ (仅适用于多标签 ‘asl’,单标签 ASL 始终使用 ‘batchmean’)。
- poly_epsilon — Poly-1 系数,设为 0 时退化为 CE / BCE(仅适用于 ‘poly’)。
- poly_gamma — 聚焦参数,设为 0 可禁用聚焦项(仅适用于多标签的“poly”)。
- poly_alpha — 正负样本平衡权重,设为 None 可禁用(仅适用于多标签 'poly')。
- jsd_splits — 增强分割的数量,必须 > 1(仅限 ‘jsd’)。
- twoway_tp — 正 logit 温度(仅限 ‘twoway’)。
- twoway_tn — 负对数温度(仅限“twoway”)。
- class_counts — 每个类别的正样本训练数量(仅限 ‘db’)。
- num_samples — 用于计算 class_counts 的训练样本数量(仅限 ‘db’)。
- db_neg_scale — 负值容忍的 logit 缩放,设为 1 时禁用(仅适用于 ‘db’)。
- db_init_bias — 类别先验对数几率偏移因子,设为 0 可禁用(仅限 ‘db’)。
- db_focal_gamma — 聚焦参数,设为 0 可禁用聚焦项(仅限 ‘db’)。
为分类任务创建训练准则。
类权重函数
timm.loss.compute_class_weights
< source >( pos_counts: typing.Union[torch.Tensor, typing.Sequence[float]]num_samples: intmethod: str = 'neg_pos'power: float = 1.0beta: float = 0.999max_weight: typing.Optional[float] = None )
参数
- pos_counts — 每个类别的正样本数量(对于单标签目标,即类别频率)。
- num_samples — 用于统计计数的样本数量。
- method — 以下之一 ‘neg_pos’:pos_weight = (negatives / positives) 的 power 次方,用于平衡每个类别的正项和负项, ‘inv_freq’:class_weight 与 (num_samples / positives) 的 power 次方成正比,均值为 1, ‘effective_num’:基于有效样本数 (1 - beta ** n) / (1 - beta) 的类别平衡 class_weight,https://arxiv.org/abs/1901.05555,均值为 1。
- power — ‘neg_pos’ 和 ‘inv_freq’ 的指数,0.5 表示更柔和(平方根)的重新加权。
- beta — “effective_num” 的有效数量超参数。
- max_weight — 应用于最终权重的上限。
根据正样本标签数量计算每个类别的损失权重。
没有正样本的类别被视为有一个正样本,如果设置了 max_weight,则每个权重都会被限制在 max_weight 以内。
timm.loss.load_class_stats
< source >( path: typing.Optional[str] )
从 class_weights.py 统计文件中加载每个类别的正样本数量和样本总数。
timm.loss.load_class_weights
< source >( value: typing.Union[str, float, typing.Sequence[float], torch.Tensor, NoneType]key: str = 'class_weight' )
从数字、逗号分隔的列表或文件中解析损失权重。
文件为 JSON 格式(一个列表,或一个将列表存储在 key 下的对象,如 class_weights.py 所写入的),或为以逗号/空白分隔的数字文本。
timm.loss.resolve_class_weights
< source >( value: typing.Union[str, float, typing.Sequence[float], torch.Tensor, NoneType]kind: str = 'class_weight'class_stats: typing.Optional[typing.Tuple[torch.Tensor, int]] = Nonepower: float = 1.0beta: float = 0.999max_weight: typing.Optional[float] = None )
参数
解析以方法名称(根据类统计信息计算)或显式权重形式给出的损失权重。
单标签损失类
带标签平滑的 NLL 损失。
class timm.loss.AsymmetricLossSingleLabel
< source >( gamma_pos = 1gamma_neg = 4eps: float = 0.1reduction = 'mean' )
Jensen-Shannon 散度 + 交叉熵损失
基于此处的实现:https://github.com/google-research/augmix/blob/master/imagenet.py 来自论文:‘AugMix: A Simple Data Processing Method to Improve Robustness and Uncertainty - https://arxiv.org/abs/1912.02781
由 / 2020 年 Ross Wightman 版权所有
class timm.loss.PolyCrossEntropy
< source >( epsilon: float = 2.0smoothing: float = 0.0reduction: str = 'mean' )
Poly-1 软最大交叉熵,CE + epsilon * (1 - p_t),用于单标签分类。
p_t 是目标加权 softmax 概率 sum_c(t_c * p_c),因此标签平滑和软(Mixup/CutMix)目标同时作用于这两项,与参考实现一致。
forward
< source >( x: Tensortarget: Tensor )
多标签损失类
类 timm.loss.BinaryCrossEntropy
< source >( smoothing = 0.1target_threshold: typing.Optional[float] = Noneweight: typing.Optional[torch.Tensor] = Nonereduction: str = 'mean'sum_classes: bool = Falsepos_weight: typing.Union[torch.Tensor, float, NoneType] = Nonesmooth_dense: bool = False )
BCE,支持从稠密目标中可选地生成 one-hot,标签平滑,阈值处理 注意:对于比较 CE 与带标签平滑的 BCE 的实验,可能会移除
class timm.loss.AsymmetricLossMultiLabel
< source >( gamma_neg: float = 4gamma_pos: float = 1clip: typing.Optional[float] = 0.05eps: float = 1e-08disable_torch_grad_focal_loss: bool = Falsesmoothing: float = 0.0reduction: str = 'batchmean'weight: typing.Optional[torch.Tensor] = Nonepos_weight: typing.Union[torch.Tensor, float, NoneType] = None )
参数
- gamma_neg — 负目标的聚焦参数。
- gamma_pos — 正样本目标的聚焦参数。
- clip — 应用于负样本的概率偏移量(非对称裁剪),若为 None 或 0 则禁用。
- eps — 在对数运算之前,概率被钳制到的最小值。
- disable_torch_grad_focal_loss — 不通过聚焦权重进行反向传播。
- smoothing — 标签平滑,将每个(稠密、独立二值)目标向 0.5 移动。
- reduction — ‘batchmean’ 对类别求和并对批次求平均,‘sum’ 对批次和类别求和 (原始 ASL 归约方式,随批次大小缩放),‘mean’ 对批次和类别求平均, ‘none’ 保留逐元素损失。
- weight — 每类的重新缩放权重。
- pos_weight — 正项的权重,可以是单个值,也可以是每个类别一个值。
用于多标签分类的非对称损失(ASL),https://arxiv.org/abs/2009.14119
forward
< source >( x: Tensory: Tensor )
class timm.loss.PolyBinaryCrossEntropy
< source >( epsilon: float = 2.0gamma: float = 0.0alpha: typing.Optional[float] = Nonesmoothing: float = 0.0reduction: str = 'mean' )
Poly-1 sigmoid(focal)损失,FL + epsilon * (1 - p_t) ** (gamma + 1),用于多标签分类。
当 gamma = 0 时,每个类别的损失为 BCE + epsilon * (1 - p_t)。当设置 alpha 时,正样本在两项中均按 alpha 加权,负样本按 1 - alpha 加权,与参考实现一致。
forward
< source >( x: Tensortarget: Tensor )
class timm.loss.DistributionBalancedLoss
< source >( class_counts: typing.Union[torch.Tensor, typing.Sequence[float]]num_samples: intmap_alpha: float = 0.1map_beta: float = 10.0map_mu: float = 0.2neg_scale: float = 2.0init_bias: float = 0.05focal_gamma: float = 2.0focal_balance: float = 2.0smoothing: float = 0.0reduction: str = 'mean' )
参数
- class_counts — 训练集中每个类别的正样本数量。
- num_samples — 统计计数所基于的训练样本数量。
- map_alpha — 再平衡映射的最小权重。
- map_beta — 再平衡映射的尺度。
- map_mu — 再平衡映射的阈值。
- neg_scale — 负对数几率缩放(lambda),设为 1 可禁用负值容差缩放。
- init_bias — 类别先验对数几率偏移因子(kappa),设为 0 可禁用。
- focal_gamma — 聚焦参数,设为 0 可禁用聚焦项(以及 focal_balance)。
- focal_balance — 焦点损失的恒定缩放系数。
- smoothing — 标签平滑,将每个目标值向 0.5 移动。
- reduction — ‘mean’ 对 batch 和类别取平均值(参考尺度),‘batchmean’ 对类别求和并对 batch 取平均值,‘sum’ 对两者求和,‘none’ 保留逐元素的损失。
用于长尾多标签分类的分布平衡(DB)损失。
带有两项附加项的 Sigmoid BCE:
- 重新平衡的权重:每个(样本,类别)项的权重为类别级采样概率 1 / n_i 与该样本实例级概率 sum_j(y_j / n_j) 的比值,该比值考虑了每个样本的标签共现情况,并以 alpha + sigmoid(beta * (r - mu)) 进行平滑处理。
- 负样本容忍正则化:logits 会加上一个类别先验偏置,负样本项使用缩放后的 logit,即 softplus(neg_scale * z) / neg_scale,以避免稀有类别的大量负样本被过度抑制。 可选的 focal 项 (1 - p_t) ** gamma 遵循参考 DB 配置。
Soft targets(Mixup/CutMix)对正项和负项进行加权,而再平衡权重则直接使用给定的 targets。对于二分类 targets,两者均与参考实现一致。
forward
< source >( x: Tensortarget: Tensor )
class timm.loss.TwoWayLoss
< source >( tp: float = 4.0tn: float = 1.0 )
双向多标签损失。
在两个方向上,将最难的(soft-max)负 logit 与最难的(soft-min)正 logit 进行对比,分别针对每个样本的类别以及批次中每个类别的样本。只有至少包含一个正样本的样本/类别才会对相应方向做出贡献。
目标值被二值化,大于 0.5 的条目为正样本。Logits 是排序分数,它们并非作为独立的 sigmoid 概率进行校准。
forward
< source >( x: Tensortarget: Tensor )
ZLPR 损失,softmax 交叉熵的多标签扩展。
每个样本的值为 log(1 + sum_neg exp(s_j)) + log(1 + sum_pos exp(-s_i))。每个正类 logit 都被推高到所有负类 logit 之上,且 0 充当决策阈值,因此 logit > 0(sigmoid > 0.5)预测为正类。该损失函数没有超参数,且不会像逐类 BCE 那样随负类数量的增加而增大。
目标值会被二值化,大于 0.5 的条目被视为正样本。
forward
< source >( x: Tensortarget: Tensor )