损失函数与优化器

十七个损失函数

L1loss
class torch.nn.L1Loss(size_average=None, reduce=None)
计算 output 和 target 之差的绝对值,可选返回同维度的 tensor 或者是一个标量。

MSELoss
class torch.nn.MSELoss(size_average=None, reduce=None, reduction='elementwise_mean')
计算 output 和 target 之差的平方,可选返回同维度的 tensor 或者是一个标量。

NLLLoss
class torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean')
对应类别上的输出,取一个负号

CrossEntropyLoss
class torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean')
将输入经过 softmax 激活函数,将向量“归一化”成概率形式,再计算其与 target 的交叉熵损失。 即该方法将nn.LogSoftmax()(相当于激活函数)和 nn.NLLLoss()(损失函数)进行了结合。严格意义上的交叉熵损失函数应该是nn.NLLLoss()。

拓展:在多分类任务中,经常采用 softmax 激活函数+交叉熵损失函数,因为交叉熵描述了两个概率分布的差异,然而神经网络输出的是向量,并不是概率分布的形式。所以需要 softmax激活函数将一个向量进行“归一化”成概率分布的形式,再采用交叉熵损失函数计算 loss。

PoissonNLLLoss
class torch.nn.PoissonNLLLoss(log_input=True, full=False, size_average=None, eps=1e-08, reduce=None, reduction='elementwise_mean')
用于 target 服从泊松分布的分类任务。

KLDivLoss
class torch.nn.KLDivLoss(size_average=None, reduce=None, reduction='elementwise_mean')
计算 input 和 target 之间的 KL 散度( 描述两个概率分布之间的差异) 。

BCELoss
class torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='element wise_mean')
二分类任务时的交叉熵计算函数。

BCEWithLogitsLoss
class torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='elementwise_mean', pos_weight=None)
Sigmoid 与 BCELoss 结合,类似于 CrossEntropyLoss ( 将 nn.LogSoftmax()和 nn.NLLLoss()进行结合)。即 input 会经过 Sigmoid 激活函数,将 input 变成概率分布的形式。

MarginRankingLoss
class torch.nn.MarginRankingLoss(margin=0, size_average=None, reduce=None, reduction='elementwise_mean')
计算两个向量之间的相似度,当两个向量之间的距离大于 margin,则 loss 为正,小于margin, loss 为 0。

HingeEmbeddingLoss
class torch.nn.HingeEmbeddingLoss(margin=1.0, size_average=None, reduce=None, reduction='elementwise_mean')
为折页损失的拓展,主要用于衡量两个输入是否相似

MultiLabelMarginLoss
class torch.nn.MultiLabelMarginLoss(size_average=None, reduce=None, reduction='element wise_mean')
用于一个样本属于多个类别时的分类任务。例如一个四分类任务,样本 x 属于第 0类,第 1 类,不属于第 2 类,第 3 类。

SmoothL1Loss
class torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='elementwise_mean')
计算平滑 L1 损失,属于 Huber Loss 中的一种(因为参数 δ 固定为 1 了)。

拓展:Huber Loss 常用于回归问题,其最大的特点是对离群点(outliers)、噪声不敏感,具
有较强的鲁棒性。

SoftMarginLoss
class torch.nn.SoftMarginLoss(size_average=None, reduce=None, reduction='elementwise_mean')
Creates a criterion that optimizes a two-class classification logistic loss between input tensor xand target tensor y (containing 1 or -1).

MultiLabelSoftMarginLoss
class torch.nn.MultiLabelSoftMarginLoss(weight=None, size_average=None, reduce=None, reduction='elementwise_mean')
SoftMarginLoss 多标签版本。

CosineEmbeddingLoss
class torch.nn.CosineEmbeddingLoss(margin=0, size_average=None, reduce=None, reduction ='elementwise_mean')
用 Cosine 函数来衡量两个输入是否相似

MultiMarginLoss
class torch.nn.MultiMarginLoss(p=1, margin=1, weight=None, size_average=None, reduce=None, reduction='elementwise_mean')
计算多分类的折页损失。

TripletMarginLoss
class torch.nn.TripletMarginLoss(margin=1.0, p=2, eps=1e-06, swap=False, size_average=None, reduce=None, reduction='elementwise_mean')
计算三元组损失,人脸验证中常用。

十个优化器

基类 Optimizer

PyTorch 中所有的优化器(如: optim.Adadelta、 optim.SGD、 optim.RMSprop 等)均是Optimizer 的子类,Optimizer 中定义了一些常用的方法:

参数组(param_groups)

# 一个参数组
optimizer_1 = optim.SGD([w1, w3], lr=0.1)
# 两个参数组
optimizer_2 = optim.SGD([{'params': w1, 'lr': 0.1},
                         {'params': w2, 'lr': 0.001}])

optimizer 对参数的管理是基于组的概念,可以为每一组参数配置特定的lr,momentum,weight_decay 等等。
参数组在 optimizer 中表现为一个 list(self.param_groups),其中每个元素是dict,表示一个参数及其相应配置,在 dict 中包含’params’、 ‘weight_decay’、 ‘lr’ 、'momentum’等字段。

zero_grad()
梯度清零。由于 PyTorch 不会自动清零梯度,所以在每一次更新前会进行此操作。

state_dict()
获取模型当前的参数,以一个有序字典形式返回。key 是各层参数名, value 就是参数。

load_state_dict(state_dict)
将 state_dict 中的参数加载到当前网络,常用于 finetune

add_param_group()
给 optimizer 管理的参数组中增加一组参数,可为该组参数定制 lr,momentum, weight_decay 等,在 finetune 中常用。

step(closure)
执行一步权值更新, 其中可传入参数 closure(一个闭包)。

十个优化器

这里都说的是 ** 优化器,并没有提 ** 优化方法,因为 PyTorch 中给出的优化器与原始论文中提出的优化方法,多多少少有改动,详细还需看优化器源码。

torch.optim.SGD
class torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)
可实现 SGD 优化算法,带动量 SGD 优化算法,带 NAG(Nesterov accelerated gradient)动量 SGD 优化算法,并且均可拥有 weight_decay 项。

拓展:pytroch 中使用 SGD 更新公式与其他框架略有不同!PyTorch 中是这样的:
v=ρ∗v+g
p=p−lr∗v = p - lr∗ρ∗v - lr∗g
其他框架:
v=ρ∗v+lr∗g
p=p−v = p - ρ∗v - lr∗g
ρ 是动量, v 是速率, g 是梯度, p 是参数,其实差别就是在 ρ∗v 这一项, PyTorch 中将此项也乘了一个学习率

torch.optim.ASGD
class torch.optim.ASGD(params, lr=0.01, lambd=0.0001, alpha=0.75, t0=1000000.0, weight_decay=0)
ASGD 也成为 SAG,均表示随机平均梯度下降(Averaged Stochastic Gradient Descent),简单地说 ASGD 就是用空间换时间的一种 SGD

torch.optim.Rprop
class torch.optim.Rprop(params, lr=0.01, etas=(0.5, 1.2), step_sizes=(1e-06, 50))
实现 Rprop 优化方法(弹性反向传播),该优化方法适用于 full-batch,不适用于 mini-batch,因而在 mini-batch 大行其道的时代
里,很少见到。

torch.optim.Adagrad
class torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0)
自适应优化方法,自适应的为各个参数分配不同的学习率。这个学习率的变化,会受到梯度的大小和迭代次数的影响。梯度越大,学习率越小;梯度越小,学习率越大。缺点是训练后期,学习率过小,因为 Adagrad 累加之前所有的梯度平方作为分母。

torch.optim.Adadelta
class torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)
Adadelta 是 Adagrad 的改进。Adadelta 分母中采用距离当前时间点比较近的累计项,这可以避免在训练后期,学习率过小。

torch.optim.RMSprop
class torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)
RMS 是均方根(root meam square)的意思。 RMSprop 和 Adadelta 一样,也是对 Adagrad 的一种改进。 RMSprop 采用均方根作为分母,可缓解 Adagrad 学习率下降较快的问题, 并且引入均方根,可以减少摆动。

torch.optim.Adam(AMSGrad)
class torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
Adam 是一种自适应学习率的优化方法, Adam 利用梯度的一阶矩估计和二阶矩估计动态的调整学习率。Adam 是结合了 Momentum 和 RMSprop,并进行了偏差修正。

torch.optim.Adamax
class torch.optim.Adamax(params, lr=0.002, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)
Adamax 是对 Adam 增加了一个学习率上限的概念,所以也称之为 Adamax。

torch.optim.SparseAdam
class torch.optim.SparseAdam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08)
针对稀疏张量的一种“阉割版”Adam 优化方法。

torch.optim.LBFGS
class torch.optim.LBFGS(params, lr=1, max_iter=20, max_eval=None, tolerance_grad=1e-05, tolerance_change=1e-09, history_size=100, line_search_fn=None)
实现 L-BFGS(Limited-memory Broyden–Fletcher–Goldfarb–Shanno)优化方法。L-BFGS 属于拟牛顿算法。 L-BFGS 是对 BFGS 的改进,特点就是节省内存

六个学习率调整方法

优化器中最重要的一个参数就是学习率,合理的学习率可以使优化器快速收敛。一般在训练初期给予较大的学习率,随着训练的进行,学习率逐渐减小。

有序调整

依一定规律有序进行调整,这一类是最常用的。

lr_scheduler.StepLR
class torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)
等间隔调整学习率。step 通常是指 epoch,不是 iteration。

lr_scheduler.MultiStepLR
class torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)
设定的间隔调整学习率。这个方法适合后期调试使用,观察 loss 曲线,为每个实验定制学习率调整时机。

lr_scheduler.ExponentialLR
class torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1)
指数衰减调整学习率。调整公式: lr = lr * gamma ** epoch。

lr_scheduler.CosineAnnealingLR
class torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1)
余弦函数为周期,并在每个周期最大值时重新设置学习率。以初始学习率为最大学习率,以 2*Tmax 为周期,在一个周期内先下降,后上升。

自适应调整

依训练状况伺机调整。

lr_scheduler.ReduceLROnPlateau
class torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
某指标不再变化(下降或升高),调整学习率

自定义调整

可以为不同的层设定不同的学习率调整方法,这在 finetune 中十分有用。

lr_scheduler.LambdaLR
class torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)
不同参数组设定不同学习率调整策略。调整规则为, lr = base_lr * lmbda(self.last_epoch) 。

摘自《Pytorch模型训练实用教程》。详情见:https://github.com/tensor-yu/PyTorch_Tutorial

你可能感兴趣的:(pytorch)