aaaaaa

分类任务输出层激活函数损失函数
二分类 s i g m o i d ( ) sigmoid() sigmoid() b i n a r y _ c r o s s e n t r o p y ( ) binary\_crossentropy() binary_crossentropy()
多分类 s o f t m a x ( ) softmax() softmax() c a t e g o r i c a l _ c r o s s e n t r o p y categorical\_crossentropy categorical_crossentropy
多标签二分类 s i g m o i d ( ) sigmoid() sigmoid() b i n a r y _ c r o s s e n t r o p y ( ) binary\_crossentropy() binary_crossentropy()
BCELoss
import torch

output = torch.full([10, 64], 1.5)  # (batch_size, nums_classes)
target = torch.ones([10, 64], dtype=torch.float32)

criterion = torch.nn.BCELoss()(
    torch.nn.Sigmoid()(output),
    target
)
print(criterion)  # tensor(0.2014)

criterion = torch.nn.BCEWithLogitsLoss()(output, target)
print(criterion)  # tensor(0.2014)

$$
假设x为模型预测输出,y为样本标签(第n个样本的模型预测输出x_n与样本标签y_n) \
l(x,y) = L = { l_1, \dots, l_N }^T,\
\begin{equation}
l(x,y)=
\begin{cases}
L& \text{if reduction is None}\
mean(L)& \text{if reduction is ‘mean’}\
sum(L)& \text{if reduction is ‘sum’}
\end{cases}
\end{equation} \

l_n = -w_n[y_n \cdot log\sigma(x_n) + (1-y_n)log\sigma(1-x_n)]为第n个样本的loss \
\
l_{n,c} = -w_{n,c}[p_cy_{n,c} \cdot log\sigma(x_{n,c}) + (1-y_{n,c}\cdot log(1-\sigma(x_{n,c})))] \
$$

c c c: class number (c=1 for single-label binary classification, c>1 for multi-label binary classification.)

n n n: the number of sample in the batch

p c p_c pc: the weight of the positive answer for the class c c c ( p c > 1 p_c>1 pc>1 increase the recall, p c < 1 p_c<1 pc<1 increase the precision.)

样本不均衡问题
多标签间的样本不均衡问题 weight
weight = torch.ones(64)
weight[1] *= 3  # 假设标签1的样本数量同其他标签的样本数量差三倍
criterion = torch.nn.BCEWithLogitsLoss(weight=weight)(output, target)
print(criterion)  # tensor(0.2077)
每类标签的正负样本不均衡问题 pos_weight

当数据集中某个单类的正负样本比例为 n u m s _ p o s i t i v e n u m s _ n e g a t i v e = 1 R \frac{nums\_positive}{nums\_negative}=\frac{1}{R} nums_negativenums_positive=R1,并将pos_weight向量中对应该类的值设为 R R R时,表示在计算loss时该类的 n u m s _ p o s i t i v e = n u m s _ p o s i t i v e × R nums\_positive = nums\_positive \times R nums_positive=nums_positive×R

pos_weight = torch.ones(64) * 2  # 假设所有标签的正样本是其负样本数量的1/2
criterion = torch.nn.BCEWithLogitsLoss(pos_weight=pos_weight)(output, target)
print(criterion)  # tensor(0.4028)

PyTorch自动混合精度(AMP)

PyTorch1.6起内置torch.cuda.amp启用自动混合精度训练,无需加载第三方NVIDIA的apex库(仅启用在支持tensor core的CUDA硬件)

  • 自动:Tensor的dtype自动变换
  • 混合精度:一个Tensor的dtype可能同时包含torch.FloatTensor, torch.HalfTensor
FP16, FP32

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PHX2SW83-1663843108368)(C:\Users\ww0054688\AppData\Roaming\Typora\typora-user-images\image-20220922171730143.png)]

FP16的优劣:

  • 优势

    1. 减少显存占用
    2. 加快训练和推断的计算(提速一倍)
    3. 张量核心(NVIDIA tensor core)的普及(低精度计算将是未来趋势)
  • 劣势

    1. 溢出错误:FP16的动态范围<<FP32,在计算过程中易出现上溢出、下溢出后导致NaN。由于激活函数的梯度往往比权重梯度小,故更易出现下溢出。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MYczJXgR-1663843108370)(C:\Users\ww0054688\AppData\Roaming\Typora\typora-user-images\image-20220922173141258.png)]

    2. 舍入误差:当梯度小于FP16表示的最小固定间隔时,该次梯度更新可能失败。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lcziv9eJ-1663843108370)(C:\Users\ww0054688\AppData\Roaming\Typora\typora-user-images\image-20220922173351860.png)]

改进

  1. 混合精度训练:在内存中仅用FP16做储存、乘法,用FP32做累加以避免舍入误差。

    在pytorch1.6的amp上下文中,以下操作中Tensor会自动转为Fp16:__matmul__

    addbmm
    addmm
    addmv
    addr
    baddbmm
    bmm
    chain_matmul
    conv1d
    conv2d
    conv3d
    conv_transpose1d
    conv_transpose2d
    conv_transpose3d
    linear
    matmul
    mm
    mv
    prelu
    
  2. 损失放大:由于激活梯度的值太小导致的下溢出,通过放大loss的值防止梯度underflow(只在BP传递梯度信息时发生,真正更新权重时要将放大的梯度再unscale回去)

    BP前:放大损失值 2 k 2^k 2k倍,此时反向传播中的激活函数梯度信息为放大过后的中间变量,防止下溢出

    BP后:将权重梯度缩小 2 k 2^k 2k倍,恢复正常值。

    动态损失放大:为了充分利用FP16的范围,缓解舍入误差,尽量使用最高放大倍数 2 24 2^{24} 224。此时若产生上溢出,则跳出参数更新、缩小放大倍数使其不溢出,并在一定步数后再次尝试大scale以充分利用Fp16的范围。

用例
NVIDIA apex.amp
from apex import amp

...  # define model, criterion, optimizer

model, optimizer = amp.initial(model, optimizer, opt_level='O1')

...

with amp.scale_loss(criterion, optimizer) as scaled_loss:
    scaled_loss.backward()
# the above statement replace 'loss.backward()'

opt_level

  • 'O0':纯FP32训练,可作为accuracy的baseline
  • 'O1':amp训练,根据黑白名单自动决定使用FP16还是FP32计算
  • 'O2':几乎FP16训练,不存在黑白明白,除了bacthnorm几乎都是FP16计算
  • 'O3':纯FP16计算,不稳定,可作为speed的baseline
PyTorch1.6+
autocast
from torch.cuda.amp import autocast

...  # define model, criterion, optimizer, data

for input, target in data:
    optimizer.zero_grad()
    
    with autocast():  # autocast的context managers语义
        output = model(input)
        loss = criterion(output, target)
    loss.backward()
    optimizer.step()
from torch.cuda.amp import autocast

@autocast()  # autocast的decorators语义
def train(data, model):
    for input, target in data:
        optimizer.zero_grad()
        output = model(input)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()

autocast的context managers语义,只能包含网络的前向过程(包括loss的计算),不能包含反向传播???

Gradscaler
from torch.cuda.amp import GradScaler, autocast

...  # define model, criterion, optimizer, data

scaler = GradScaler()

for input, target in data:
    optimizer.step()
    
    with autocast:
        output = model(input)
        loss = criterion(output, target)
    scaler.scale(loss).backward()  # 
    scaler.step(optimizer)  # 
    scaler.update()

ref:Pytorch自动混合精度(AMP)介绍与使用 - jimchen1218 - 博客园 (cnblogs.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值