引入鲁棒性作为连续参数,这种新损失函数实现了自适应、随时变换( 二 )


自适应损失及其导数
下图对于理解此损失函数及其导数非常重要 。 在下图 2 中 , 尺度参数 c 固定为 1.1 。 当 x = 6.6 时 , 可以将其视为 x = 6×c 。 可以得出以下有关损失及其导数的推论:
1. 当 x、α和 c>0 时 , 损失函数是光滑的 , 因此适合于基于梯度的优化;
2. 损失函数总是在原点为零 , 并且在 | x |>0 时单调增加 。 损失的单调性也可以与损失的对数进行比较;
3. 损失也随着α的增加而单调增加 。 此属性对于损失函数的鲁棒性很重要 , 因为可以从较高的α值开始 , 然后在优化过程中逐渐减小(平滑)以实现鲁棒的估计 , 从而避免局部最小值;
4. 当 | x |
5. 对于α= 2 , 导数始终与残差的大小成正比 。 通常 , 这是 MSE(L2)损失的特性;
6. 对于α=1(L1 损失) , 我们看到导数的幅度在 | x |>c 之外饱和至一个常数值(正好是 1/c) 。 这意味着残差的影响永远不会超过一个固定的量;
7. 对于αc 而减小 。 这意味着当残差增加时 , 它对梯度的影响较小 , 因此异常值在梯度下降过程中的影响较小 。
引入鲁棒性作为连续参数,这种新损失函数实现了自适应、随时变换
本文插图
图 2:损失函数及其导数与α的关系 。

引入鲁棒性作为连续参数,这种新损失函数实现了自适应、随时变换
本文插图
图 3:自适应损失函数(左)及其导数(右)的曲面图 。
鲁棒损失的实现:Pytorch 和 Google Colab
关于鲁棒损失的理论掌握了 , 怎么实现呢?使用的代码在 Jon Barron 的 GitHub 项目「robust_loss_pytorch」中稍加修改 。 此外还创建了一个动画来描述随着迭代次数的增加 , 自适应损失如何找到最佳拟合线 。
GitHub 地址:https://github.com/jonbarron/arom_loss_pytorch
不需要克隆存储库 , 我们可以使用 Colab 中的 pip 在本地安装它 。
此外还创建了一个简单的线性数据集 , 包括正态分布的噪声和异常值 。
首先 , 由于使用了 Pythorch 库 , 利用 torch 将 x, y 的 numpy 数组转换为张量 。
其次 , 使用 pytorch 模块定义线性回归类 , 如下所示:
接下来 , 用线性回归模型拟合自创建的线性数据集 , 首先使用损失函数的一般形式 。 这里使用一个固定值α(α=2.0) , 它在整个优化过程中保持不变 。 正如在α=2.0 时看到的 , 损失函数等效 L2 损失 , 这对于包括异常值在内的问题不是最优的 。 对于优化 , 使用学习率为 0.01 的 Adam 优化器 。
利用鲁棒损失函数的一般形式和固定α值 , 可以得到拟合线 。 原始数据、真直线(生成数据点时使用的具有相同斜率和偏差的线 , 排除异常值)和拟合线如下图 4 所示:

引入鲁棒性作为连续参数,这种新损失函数实现了自适应、随时变换
本文插图
图 4:一般损失函数
损失函数的一般形式不允许α发生变化 , 因此必须手动微调α参数或执行网格搜索进行微调 。
此外 , 正如上图所示 , 由于使用了 L2 损失 , 拟合受到异常值的影响 。 这是一般的情况 , 但如果使用损失函数的自适应版本 , 会发生什么呢?调用自适应损失模块 , 并初始化α , 让α在每个迭代步骤中自适应 。
此外 , 还有一些额外的代码使用 celluloid 模块 , 见下图 5 。 在这里 , 可以清楚地看到 , 随着迭代次数的增加 , 自适应损失如何找到最佳拟合线 。 这个结果接近真实的线 , 对于异常值的影响可以忽略不计 。
引入鲁棒性作为连续参数,这种新损失函数实现了自适应、随时变换
本文插图
图 5:自适应损失函数如何达到最佳拟合的动画 。