Matlab:在反向传播中接近 realmin 时处理非范数性能成本转换
Matlab: Dealing with denorm performance cost conversion when close to realmin in backprop
我知道如果一个数字比 realmin
更接近零,那么 Matlab 会将双精度转换为 denorm 。我注意到这会导致显着的性能成本。特别是我使用的是梯度下降算法,当接近收敛时,梯度(在我的定制神经网络的反向传播中)下降到 realmin
以下,这样算法会产生沉重的性能成本(我假设是由于类型转换幕后)。我使用以下代码来验证我的梯度矩阵,以便没有数字低于 realmin
:
function mat= validateSmallDoubles(obj, mat, threshold)
mat= mat.*(abs(mat)>threshold);
end
这是通常的做法吗?threshold
应该取什么值(显然你希望它尽可能接近 realmin
,但不要太接近,否则任何额外的除法运算都会发送一些元素 mat
低于 realmin
验证后)?。此外,特别是对于神经网络,在不破坏网络学习能力的情况下进行梯度验证的最佳位置在哪里?我很想知道有训练神经网络经验的人有什么解决方案?我相信这对所有语言都是一个问题。暂定 threshold
值破坏了我的网络学习。
我追踪到 Adam SGD 优化器出现的梯度递减 - Adam 优化器中有偏差的移动平均矩阵计算导致 matlab 执行非范数运算。在这些计算之后,我简单地将每一层的矩阵元素阈值化,threshold=10*realmin
,对学习没有任何影响。我还没有调查为什么我的移动平均线变得如此接近于零,因为我的架构和权重初始化先验通常会减轻这种情况。
我不知道它是否与你的问题有某种关系,但我在做梯度的指数加权平均时遇到了类似的下溢问题(比如在实现 Momentum 或 Adam 时)。
特别是,在某些时候你会做这样的事情:
v := 0.9*v + 0.1*gradient
其中 v
是梯度 g
的指数加权平均值。如果在许多连续迭代中,您的 g
矩阵的相同元素保持为 0,则您的 v
很快变得非常小并且您达到了微分正态。
所以问题是为什么所有这些零?在我的例子中, ReLu
单元输出大量零的罪魁祸首(如果 x<0 , relu(x) 为零)。因为当 Relu
在给定神经元上输出零时,相关权重没有影响,这意味着相应的偏导数在 g
中将为零。所以我碰巧在很多连续的迭代中那个特定的神经元没有被激发。
为了避免零激活(和导数),我使用 "leaky relu" 来代替一个非常小的导数。
另一种解决方案是在应用加权平均值将梯度阈值设为最小值之前使用梯度裁剪。这与您所做的非常相似。
我知道如果一个数字比 realmin
更接近零,那么 Matlab 会将双精度转换为 denorm 。我注意到这会导致显着的性能成本。特别是我使用的是梯度下降算法,当接近收敛时,梯度(在我的定制神经网络的反向传播中)下降到 realmin
以下,这样算法会产生沉重的性能成本(我假设是由于类型转换幕后)。我使用以下代码来验证我的梯度矩阵,以便没有数字低于 realmin
:
function mat= validateSmallDoubles(obj, mat, threshold)
mat= mat.*(abs(mat)>threshold);
end
这是通常的做法吗?threshold
应该取什么值(显然你希望它尽可能接近 realmin
,但不要太接近,否则任何额外的除法运算都会发送一些元素 mat
低于 realmin
验证后)?。此外,特别是对于神经网络,在不破坏网络学习能力的情况下进行梯度验证的最佳位置在哪里?我很想知道有训练神经网络经验的人有什么解决方案?我相信这对所有语言都是一个问题。暂定 threshold
值破坏了我的网络学习。
我追踪到 Adam SGD 优化器出现的梯度递减 - Adam 优化器中有偏差的移动平均矩阵计算导致 matlab 执行非范数运算。在这些计算之后,我简单地将每一层的矩阵元素阈值化,threshold=10*realmin
,对学习没有任何影响。我还没有调查为什么我的移动平均线变得如此接近于零,因为我的架构和权重初始化先验通常会减轻这种情况。
我不知道它是否与你的问题有某种关系,但我在做梯度的指数加权平均时遇到了类似的下溢问题(比如在实现 Momentum 或 Adam 时)。
特别是,在某些时候你会做这样的事情:
v := 0.9*v + 0.1*gradient
其中 v
是梯度 g
的指数加权平均值。如果在许多连续迭代中,您的 g
矩阵的相同元素保持为 0,则您的 v
很快变得非常小并且您达到了微分正态。
所以问题是为什么所有这些零?在我的例子中, ReLu
单元输出大量零的罪魁祸首(如果 x<0 , relu(x) 为零)。因为当 Relu
在给定神经元上输出零时,相关权重没有影响,这意味着相应的偏导数在 g
中将为零。所以我碰巧在很多连续的迭代中那个特定的神经元没有被激发。
为了避免零激活(和导数),我使用 "leaky relu" 来代替一个非常小的导数。
另一种解决方案是在应用加权平均值将梯度阈值设为最小值之前使用梯度裁剪。这与您所做的非常相似。