梯度的概念和例子说明
梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。其中,方向导数是各个方向上的导数。函数 z=f(x,y) 在点 P0 处的梯度方向是函数变化率(即方向导数)最大的方向。
举个例子,对于多维变量函数(这里以三维为例)来说,假设 f = x 2 + 3 x y + y 2 + z 3 f=x^2+3xy+y^2+z^3 f=x2+3xy+y2+z3,点A处的梯度为:
可理解为,站在向量点A(1, 2, 3),如果想让函数 f 的值增长得最快,那么它的下一个前进的方向,就是朝着向量点B(8,7,27)方向进发。
hessian矩阵
黑塞矩阵(Hessian Matrix),是一个多元函数的二阶偏导数构成的方阵,描述了函数的局部曲率。黑塞矩阵常用于牛顿法解决优化问题,利用黑塞矩阵可判定多元函数的极值问题。在工程实际问题的优化设计中,所列的目标函数往往很复杂,为了使问题简化,常常将目标函数在某点邻域展开成泰勒多项式来逼近原函数,此时函数在某点泰勒展开式的矩阵形式中会涉及到黑塞矩阵。
Hessian Matrix,它有着广泛的应用,如在牛顿方法、求极值以及边缘检测、消除边缘响应等方面的应用,图像处理里,可以抽取图像特征,在金融里可以用来作量化分析。
参考文章
凸函数的数学定义
函数 f : R n → R f: R^n \rightarrow {R} f:Rn→R 是凸的,如果 d o m f dom f domf (即函数 f f f 的定义域)是凸集,且对于任意 x , y ∈ d o m f x,y \in dom f x,y∈domf 和任意 θ ∈ [ 0 , 1 ] \theta \in [0,1] θ∈[0,1],有
f ( θ x + ( 1 − θ ) y ) ≤ θ f ( x ) + ( 1 − θ ) f ( y ) f(\theta{x}+(1-\theta)y) \le \theta{f(x)}+(1-\theta)f(y) f(θx+(1−θ)y)≤θf(x)+(1−θ)f(y)
如果把 ≤ 换成 <,则是严格凸函数的数学定义。
凸函数的几何解释:
所谓凸函数,其实指的是下凸函数,从几何意义上看,凸函数就是任意两点之间的弦(即这两点构成的线段)都在该函数图像(此处是指这两点之间的函数图像,而非全部的函数图像)的上方。
上面的公式,完全可以推广到多元函数。在数据科学的模型求解中,如果优化的目标函数是凸函数,则局部极小值就是全局最小值。这也意味着我们求得的模型是全局最优的,不会陷入到局部最优值。例如支持向量机的目标函数 ∣ ∣ w ∣ ∣ 2 2 \frac{||w||^2}{2} 2∣∣w∣∣2 就是一个凸函数。
凸集的数学定义
给定集合 S S S,对任意元素 x 1 , x 2 x_1,x_2 x1,x2 属于该集合 S S S,若对于任意 θ ∈ [ 0 , 1 ] \theta\in[0,1] θ∈[0,1],有
x = θ x 1 + ( 1 − θ ) x 2 x = \theta{x_1}+(1-\theta)x_2 x=θx1+(1−θ)x2
即 x x x 也在集合 S S S 中,则集合 S S S 是凸集。
以向量的角度来理解,就是点 x 1 x_1 x1 和 x 2 x_2 x2 在集合 S S S 中,两点的连线也在该集合中。
怎么判断一个函数是否是凸函数
对于一元函数 f ( x ) f(x) f(x),我们可以通过其二阶导数 f ′ ′ ( x ) f^{′′}(x) f′′(x) 的符号来判断。如果函数的二阶导数总是非负,即 f ′ ′ ( x ) ≥ 0 f^{′′}(x)≥0 f′′(x)≥0 ,则 f ( x ) f(x) f(x) 是凸函数。
对于多元函数 f ( X ) f(X) f(X),我们可以通过其 Hessian 矩阵(Hessian矩阵是由多元函数的二阶导数组成的方阵)的正定性来判断。如果 Hessian 矩阵是半正定矩阵,则 f ( X ) f(X) f(X) 是凸函数。
Jensen不等式
对于凸函数,我们可以推广出一个重要的不等式,即 Jensen 不等式。如果 f f f 是凸函数, X X X 是随机变量,那么 f ( E ( X ) ) ≤ E ( f ( X ) ) f(E(X))≤E(f(X)) f(E(X))≤E(f(X)),上式就是 Jensen 不等式的一般形式。
我们还可以看它的另一种描述。假设有 n n n 个样本 { x 1 , x 2 , . . . , x n x_1,x_2,...,x_n x1,x2,...,xn} 和对应的权重 { α 1 , α 2 , . . . , α n \alpha_1,\alpha_2,...,\alpha_n α1,α2,...,αn},权重满足 α i ⩾ 0 , ∑ α i = 1 \alpha_i⩾0,\sum{\alpha_i}=1 αi⩾0,∑αi=1,对于凸函数 f f f,以下不等式成立:
f ( ∑ i = 1 n α i x i ) ≤ ∑ i = 1 n α i f ( x i ) f(\sum_{i=1}^n\alpha_i{x_i}) \le \sum_{i=1}^n\alpha_i{f(x_i)} f(i=1∑nαixi)≤i=1∑nαif(xi)
参考文章
1. 向量点乘(内积)
向量的点乘,也叫内积,是对两个向量对应位一一相乘之后求和的操作,点乘的结果是一个标量。
2. 向量叉乘(外积)
两个向量的叉乘,又叫外积、叉积,叉乘的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量组成的坐标平面垂直。
2.2 几何意义
在3D图像学中,叉乘的概念非常有用,可以通过两个向量的叉乘,生成第三个垂直于a,b的法向量,从而构建X、Y、Z坐标系。如下图所示:
在二维空间中,叉乘还有另外一个几何意义就是:a × \times ×b等于由向量a和向量b构成的平行四边形的面积。
3. 总结
所以,两个相同向量的积在内积上达到最大,把外积方向给挤没了,所以外积中如果两个向量相同则为0。因为向量相同外积为0,所以才有交换变号,即反对称性。
参考文章
正则化是一类通过限制模型复杂度,从而避免过拟合,提高泛化能力的方法,比如引入约束、增加先验(数据增强)、提前停止、Dropout、模型集成等。
Dropout是指在深度网络的训练中,以一定的概率随机的“临时丢弃”一部分神经元节点。具体来讲,Dropout作用于每份下批量训练数据,由于其随机丢弃部分神经元的机制,相当于每次迭代都在训练不同的神经网络。类比于Bagging方法,Dropout可被认为是一种实用的大规模深度神经网络的模型集成方法。
Dropout的具体实现中,要求某个神经元节点激活值以一定的概率被“丢弃”,即该神经元暂时停止工作。因此对于包含 N 个神经元的网络,在Dropout的作用下可看作为 2 N 2^N 2N 个模型的集成。这 2 N 2^N 2N 个模型可被认为是原始网络的子网络,它们共享部分权值,并且具有相同的网络层数,而模型整体的参数数目不变,这就大大简化了运算。对于任意神经元,每次训练中都与一组随机挑选的不同的神经元集合共同进行优化,这个过程会减弱全体神经元之间的联合适应性,减少过拟合的风险,增加泛化能力。
Dropout实现原理
每次选择丢弃的神经元是随机的。最简单的方法是设置一个固定的概率 p p p。对每一个神经元都以概率 p p p 来判定要不要保留。对于一个神经层 y = f ( W x + b ) \pmb{y}=f(\pmb{Wx}+\pmb{b}) yyy=f(WxWxWx+bbb),我们可以引入一个掩码函数 m a s k ( ⋅ ) mask(\cdot) mask(⋅) 使得 y = f ( W m a s k ( x ) + b ) \pmb{y}=f(\pmb{W}mask(\pmb{x})+\pmb{b}) yyy=f(WWWmask(xxx)+bbb)。掩码函数 m a s k ( ⋅ ) mask(\cdot) mask(⋅) 的定义为
m a s k ( x ) = { m ⨀ x 当训练阶段时 p x 当测试阶段时 mask(\pmb{x})= \begin{cases} \pmb{m} \bigodot \pmb{x}& \text{当训练阶段时}\\ p\pmb{x}& \text{当测试阶段时} \end{cases} mask(xxx)={mmm⨀xxxpxxx当训练阶段时当测试阶段时
其中, m ∈ { 0 , 1 } D \pmb{m} \in \text{\textbraceleft}0,1\text{\textbraceright}^D mmm∈{0,1}D 是丢弃掩码,通过以概率为 p p p 的伯努利分布随机生成,代表每个神经元是否需要被丢弃。如果取值为0,则该神经元将不会计算梯度或参与后面的误差传播。在训练时,激活神经元的平均数量是原来的 p p p 倍。而在测试时,所有的神经元都是可以激活的,这会造成训练和测试时网络的输出不一致。为了缓解这个问题,在测试时需要将神经层的输入 x \pmb{x} xxx 乘以 p p p,也相当于把不同的神经网络作了平均,以恢复在训练中该神经元只有 p p p 的概率被用于整个神经网络的前向传播计算。
参考文章
Batch Normmalization(批量归一化方法)是针对每一批数据,在网络的每一层输入之前增加归一化处理(均值为0,标准差为1),将所有批数据强制在统一的数据分布下。
1. Batch Norm 为什么有效?
深度学习的话尤其是在CV上都需要对数据做归一化,因为深度神经网络主要就是为了学习训练数据的分布,并在测试集上达到很好的泛化效果。
但是,如果我们每一个batch输入的数据都具有不同的分布,显然会给网络的训练带来困难。
另一方面,数据经过一层层网络计算后,其数据分布也在发生着变化,此现象称为Internal Covariate Shift(内部协变量偏移),接下来会详细解释,会给下一层的网络学习带来困难。
batch norm 直译过来就是批规范化,就是为了解决这个分布变化问题。
补充两个知识点
1.1 Internal Covariate Shift
Internal Covariate Shift :此术语是google小组在论文Batch Normalizatoin中提出来的,其主要描述的是:训练深度网络的时候经常发生训练困难的问题,因为,每一次参数迭代更新后,上一层网络的输出数据经过这一层网络计算后,数据的分布会发生变化,为下一层网络的学习带来困难(神经网络本来就是要学习数据的分布,要是分布一直在变,学习就很难了),此现象称之为Internal Covariate Shift。
Batch Normalizatoin 之前的解决方案就是使用较小的学习率,和小心的初始化参数,对数据做白化处理,但是显然治标不治本。
1.2 covariate shift
Internal Covariate Shift 和Covariate Shift具有相似性,但并不是一个东西,Internal发生在神经网络的内部,后者发生在输入数据上。Covariate Shift主要描述的是由于训练数据和测试数据存在分布的差异性,给网络的泛化性和训练速度带来了影响,我们经常使用的方法是做归一化或者白化。
2. Batch Norm步骤如下
3. Batch Norm的 两个参数有什么作用?
3.1 如果只做归一化,为什么是学不到任何东西的?
如果在每一层之后都归一化成0-1的高斯分布(减均值除方差)那么数据的分布一直都是高斯分布,数据分布都是固定的了,这样即使加更多层就没有意义了,深度网络就是想学习数据的分布发现规律性,BN就是不让学习的数据分布偏离太远,详细细节可以去看论文。beta gama都是学习的(怎么学的还不清楚?),代码里他们定义的是variable, trainable是True
3.2 两个参数的作用
为了减小Internal Covariate Shift,对神经网络的每一层做归一化不就可以了,假设将每一层输出后的数据都归一化到0均值,1方差,满足正太分布,但是,此时有一个问题,如果每一层的数据分布都是标准正太分布,导致其完全学习不到输入数据的特征,因为,费劲心思学习到的特征分布被归一化了,因此,直接对每一层做归一化显然是不合理的。
但是如果稍作修改,加入可训练的参数做归一化,那就是 Batch Norm 实现的了。
接下来详细介绍一下这额外的两个参数,之前也说过如果直接做归一化不做其他处理,神经网络是学不到任何东西的,但是加入这两个参数后,事情就不一样了。先考虑特殊情况下,如果γ 和β 分别等于此batch的标准差和均值,那么yi 就还原到归一化前的x了吗,也即是缩放平移到了归一化前的分布,相当于batchnorm没有起作用,β 和γ 分别称之为平移参数和缩放参数 。这样就保证了每一次数据经过归一化后还保留的有学习来的特征,同时又能完成归一化这个操作,加速训练。
3.3 两个参数是怎么学习的(γ 和β )?
注意momentum的定义
Pytorch中的BN层的动量平滑和常见的动量法计算方式是相反的,默认的momentum=0.1
BN层里的表达式为:
其中γ和β是可以学习的参数。在Pytorch中,BN层的类的参数有:
CLASS torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
具体计算是:
running_mean = momentum * running_mean + (1 - momentum) * x_mean
running_var = momentum * running_var + (1 - momentum) * x_var
这篇有提到: Pytorch Batch Normalizatin layer的坑
4. Batch Norm 训练和测试的区别?
训练阶段:首先计算均值和方差(每次训练给一个批量,计算批量的均值方差),然后归一化,然后缩放和平移,完事!
测试阶段:每次只输入一张图片,这怎么计算批量的均值和方差,于是,就有了代码中下面两行,在训练的时候实现计算好mean、 var,测试的时候直接拿来用就可以了,不用计算均值和方差。
running_mean = momentum * running_mean + (1 - momentum) * x_mean
running_var = momentum * running_var + (1 - momentum) * x_var
5. Batch Norm 可以防止过拟合吗?
在dropout部分,我们已经解释过,之所以dropout可以抑制overfitting,是因为在训练阶段, 我们引入了随机性(随机cancel一些Neuron),减少网络的匹配度,在测试阶段, 我们去除掉随机性, 并通过期望的方式marginalize随机影响。
在BatchNormalization中, 训练阶段, 我们随机选取了Batch进行Normalization, 并计算runningmean等, 在测试阶段, 应用running_mean这些训练参数来进行整体Normalization, 本质上是在Marginalize训练阶段的随机性。 因此, Batch Normalization也提供了Regularization的作用, 实际应用中证明, NB在防止过拟合方面确实也有相当好的表现。
Batch Norm 总结
优点
缺点
参考文章
大多数机器学习问题最终都会涉及一个最优化问题,只是有的是基于最大化后验概率,例如贝叶斯算法,有的是最小化类内距离,例如k-means,而有的是根据预测值和真实值构建一个损失函数,用优化算法来最优化这个损失函数达到学习模型参数的目的。
优化算法有很多种,如果按梯度的类型进行分类,可以分为有梯度优化算法和无梯度优化算法,有梯度优化算法主要有梯度下降法、动量法momentum、Adagrad、RMSProp、Adadelta、Adam等,无梯度优化算法也有很多,像粒子群优化算法、蚁群算法群体智能优化算法,也有贝叶斯优化、ES、SMAC这一类的黑盒优化算法,这篇文章主要介绍一下有梯度优化算法。
梯度下降法
梯度下降法主要分为三种
1. 梯度下降:
梯度下降使用整个训练数据集来计算梯度,因此它有时也被称为批量梯度下降。
下面就以均方误差讲解一下,假设损失函数如下:
其中 y ^ \hat{y} y^ 是预测值, y y y 是真实值,那么要最小化上面损失 J J J ,需要对每个参数 θ 0 , θ 1 , . . . θ n \theta_0,\theta_1,...\theta_n θ0,θ1,...θn 运用梯度下降法:
其中 ∂ ∂ θ i J ( θ 0 , θ 1 , . . . , θ n ) \frac{\partial}{\partial{\theta_i}}J(\theta_0,\theta_1,...,\theta_n) ∂θi∂J(θ0,θ1,...,θn) 是损失函数对参数 θ i \theta_i θi 的偏导数、 α \alpha α 是学习率,也是每一步更新的步长。
2. 随机梯度下降法
在机器学习\深度学习中,目标函数的损失函数通常取各个样本损失函数的平均,那么假设目标函数为:
其中 J ( x i ) J(x_i) J(xi) 是第 x i x_i xi 个样本的目标函数,那么目标函数在在 x x x 处的梯度为:
如果使用梯度下降法(批量梯度下降法),那么每次迭代过程中都要对 n n n 个样本进行求梯度,所以开销非常大,随机梯度下降的思想就是随机采样一个样本 J ( x i ) J(x_i) J(xi) 来更新参数,那么计算开销就从 O ( n ) O(n) O(n) 下降到 $(1) 。
3. 小批量梯度下降法
随机梯度下降虽然提高了计算效率,降低了计算开销,但是由于每次迭代只随机选择一个样本,因此随机性比较大,所以下降过程中非常曲折(图片来自《动手学深度学习》),
所以,样本的随机性会带来很多噪声,我们可以选取一定数目的样本组成一个小批量样本,然后用这个小批量更新梯度,这样不仅可以减少计算成本,还可以提高算法稳定性。小批量梯度下降的开销为 O ( ∣ B ∣ ) O(|B|) O(∣B∣) 其中 ∣ B ∣ |B| ∣B∣ 是批量大小。
该怎么选择?
当数据量不大的时候可以选择批量梯度下降法,当数据量很大时可以选择小批量梯度下降法。
动量法momentum
梯度下降法的缺点是每次更新沿着当前位置的梯度方向进行,更新仅仅取决于所在的位置。举个例子,假设一个二维的问题, f ( x ) = 0.001 x 1 2 + 1 x 2 2 f(x)=0.001x_1^2+1x_2^2 f(x)=0.001x12+1x22,目标函数在某一点处 x 1 x_1 x1 方向的梯度要远小于 x 2 x_2 x2 ,那么在 方向更新的幅度就会很快,震荡就很严重,降低学习率 α \alpha α 可以减小 x 2 x_2 x2 方向的幅度,但是整体的更新速度也就随着变慢了(图片来源于《动手学深度学习》)。
以 g t g_t gt 来代表小批量的梯度,那么小批量梯度下降法的为:
动量法在梯度下降法的基础上结合指数加权平均的思想加入一个动量变量 v t v_t vt 来控制不同方向的梯度,使得各个方向的梯度移动一致,
v t ← γ v t − 1 − α g t v_t \leftarrow \gamma v_{t-1} - \alpha g_t vt←γvt−1−αgt
也就是把小批量梯度下降法中的 g t g_t gt 变成 v t v_t vt ,其中 0 < γ < 1 0<\gamma<1 0<γ<1。
Adagrad
前面所介绍的方法都是针对梯度进行改进,而保持一个固定的学习率,例如动量法是通过指数加权平均使得各个方向的梯度尽可能的保持一致,减少梯度在各个方向的发散,而Adagrad算法是根据自变量在每个维度的梯度值的大小来调整各个维度上的学习率,从而避免统一的学习率难以适应所有维度的问题。
Adagrad在原来的基础上加入了一个梯度的累加变量 s t s_t st ,
其中 ⊙ \odot ⊙ 是按元素乘积,接下来对学习率根据累加梯度进行调整,
其中 ϵ \epsilon ϵ 是一个很小的数字,为了维持数值的稳定性。
可以看出Adagrad与小批量梯度下降法的不同之处在于把原来的固定学习率 α \alpha α 改为根据累加变量自适应修改的学习率。
RMSProp
Adagrad算法在原来的基础上加上了累加变量 s t s_t st, 作为自适应调节学习率的参数会逐渐增大,因此会导致学习率逐渐减小或不变,这会导致一种现象,前期学习率下降非常快,但是如果在学习率下降到很小的时候依然没有找到一个比较好的解时,到后期会非常缓慢,甚至找不到一个有用的解,RMSProp在Adagrad的基础上做了一些修改。
RMSProp使用了和动量法类似的思想,对梯度和累加变量利用指数加权平均,
和 Adagrad 一样,RMSProp 将目标函数自变量中每个元素的学习率通过按元素运算重新调整,然后更新自变量,
Adadelta
Adadelta和RMSProp一样,是针对Adagrad后期有可能较难找到有用解的问题进行改进,和RMSProp不同的是,Adadelta没有学习率这个参数。
和RMSProp相同点是,Adadelta也维护了一个累加变量 s t s_t st ,
s t ← ρ s t − 1 + ( 1 − ρ ) ⊙ g t s_t \leftarrow \rho s_{t-1} + (1-\rho) \odot g_t st←ρst−1+(1−ρ)⊙gt
和RMSProp不同的是,Adadelta还维护了一个变量 △ x t \vartriangle{x_t} △xt ,
梯度更新公式就变成了:
现在回过头看一下,可以发现,Adadelta和RMSProp的不同之处就是把学习率 α \alpha α 修改为了
Adam
这个算法在深度学习中用的比较多,Adam是在RMSProp的基础上进行改进的,该算法与RMSProp不同的是,Adam不仅对累加状态变量 s t s_t st 进行指数加权平均,还对每一个小批量的梯度 g t g_t gt 进行指数加权平均。
Adam加入了动量变量 v t v_t vt ,
状态变量的指数加权平均为,
需要注意的是,当迭代次数 t t t 较小时,过去的权值之和会较小,假设时间步 t = 1 t=1 t=1 , β 1 = 0.99 \beta_1=0.99 β1=0.99 ,那么 v 1 = 0.01 β 1 v_1=0.01 \beta_1 v1=0.01β1,为了消除这个影响Adam算法采用对变量 v t v_t vt, s t s_t st 进行修正,
更新公式为:
参考文章
激活函数的性质
为了增强网络的表示能力和学习能力,激活函数需要具备以下几点性质:
神经网络为什么需要激活函数:首先数据的分布绝大多数是非线性的,而一般神经网络的计算是线性的,引入激活函数,是在神经网络中引入非线性,强化网络的学习能力。所以激活函数的最大特点就是非线性。
不同的激活函数,根据其特点,应用也不同:Sigmoid和tanh的特点是将输出限制在(0,1)和(-1,1)之间,说明Sigmoid和tanh适合做概率值的处理,例如LSTM中的各种门;而ReLU就不行,因为ReLU无最大值限制,可能会出现很大值。同样,根据ReLU的特征,Relu适合用于深层网络的训练,而Sigmoid和tanh则不行,因为它们会出现梯度消失。
1. Sigmoid
Sigmoid函数也称为Logistic函数,因为Sigmoid函数可以从Logistic回归(LR)中推理得到,也是LR模型指定的激活函数。具体推理参考:具体推理参考:Datartisan:机器学习系列-广义线性模型
Sigmod函数的取值范围在(0, 1)之间,可以将网络的输出映射在这一范围,方便分析。
Sigmoid公式及导数:
Sigmoid及其导数曲线:
Sigmoid作为激活函数的特点:
优点:平滑、易于求导。
缺点:
2. tanh
tanh为双曲正切函数,其英文读作Hyperbolic Tangent。tanh和 sigmoid 相似,都属于饱和激活函数,区别在于输出值范围由 (0,1) 变为了 (-1,1),可以把 tanh 函数看做是 sigmoid 向下平移和拉伸后的结果。
tanh公式:
从公式2中,可以更加清晰看出tanh与sigmoid函数的关系(平移+拉伸)。
相比Sigmoid函数,
3.ReLU
Relu(Rectified Linear Unit)——修正线性单元函数:该函数形式比较简单,
公式:relu=max(0, x)
ReLU及其导数曲线:
从上图可知,ReLU的有效导数是常数1,解决了深层网络中出现的梯度消失问题,也就使得深层网络可训练。同时ReLU又是非线性函数,所谓非线性,就是一阶导数不为常数;对ReLU求导,在输入值分别为正和为负的情况下,导数是不同的,即ReLU的导数不是常数,所以ReLU是非线性的(只是不同于Sigmoid和tanh,relu的非线性不是光滑的)。
ReLU在x>0下,导数为常数1的特点:
导数为常数1的好处就是在“链式反应”中不会出现梯度消失,但梯度下降的强度就完全取决于权值的乘积,这样就可能会出现梯度爆炸问题。解决这类问题:一是控制权值,让它们在(0,1)范围内;二是做梯度裁剪,控制梯度下降强度,如ReLU(x)=min(6, max(0,x))
ReLU在x<0下,输出置为0的特点:
描述该特征前,需要明确深度学习的目标:深度学习是根据大批量样本数据,从错综复杂的数据关系中,找到关键信息(关键特征)。换句话说,就是把密集矩阵转化为稀疏矩阵,保留数据的关键信息,去除噪音,这样的模型就有了鲁棒性。ReLU将x<0的输出置为0,就是一个去噪音,稀疏矩阵的过程。而且在训练过程中,这种稀疏性是动态调节的,网络会自动调整稀疏比例,保证矩阵有最优的有效特征。
但是ReLU 强制将x<0部分的输出置为0(置为0就是屏蔽该特征),可能会导致模型无法学习到有效特征,所以如果学习率设置的太大,就可能会导致网络的大部分神经元处于‘dead’状态,所以使用ReLU的网络,学习率不能设置太大。
ReLU作为激活函数的特点:
4. Leaky ReLU, PReLU(Parametric Relu), RReLU(Random ReLU), ELU
为了防止模型的‘Dead’情况,后人将x<0部分并没有直接置为0,而是给了一个很小的负数梯度值 α \alpha α 。
Leaky ReLU中的 α \alpha α 为常数,一般设置 0.01。这个函数通常比 Relu 激活函数效果要好,但是效果不是很稳定,所以在实际中 Leaky ReLu 使用的并不多。
PRelu(参数化修正线性单元) 中的 α \alpha α 作为一个可学习的参数,会在训练的过程中进行更新。
RReLU(随机纠正线性单元)也是Leaky ReLU的一个变体。在RReLU中,负值的斜率在训练中是随机的,在之后的测试中就变成了固定的了。RReLU的亮点在于,在训练环节中,aji是从一个均匀的分布U(I,u)中随机抽取的数值。
ReLU及其变体图像:
另外,ELU 激活函数也是为了解决 ReLU 的 0 区间带来的影响,其数学表达为:
其函数及其导数数学形式为:
但是 ELU 相对于Leaky ReLU 来说,计算要更耗时间一些。
参考文章
损失函数用来评价模型的预测值和真实值不一样的程度,损失函数越好,通常模型的性能越好。不同的模型用的损失函数一般也不一样。
损失函数分为经验风险损失函数和结构风险损失函数。经验风险损失函数指预测结果和实际结果的差别,结构风险损失函数是指经验风险损失函数加上正则项。
常见的损失函数以及其优缺点如下:
1. 0-1损失函数(zero-one loss)
0-1损失是指预测值和目标值不相等为1, 否则为0:
特点:
(1) 0-1损失函数直接对应分类判断错误的个数,但是它是一个非凸函数,不太适用.
(2) 感知机就是用的这种损失函数。但是相等这个条件太过严格,因此可以放宽条件,即满足 ∣ Y − f ( X ) ∣ < T |Y - f(X)| < T ∣Y−f(X)∣<T 时认为相等,
2. 绝对值损失函数
绝对值损失函数是计算预测值与目标值的差的绝对值:
3. log对数损失函数
log对数损失函数的标准形式如下:
特点:
(1) log对数损失函数能非常好的表征概率分布,在很多场景尤其是多分类,如果需要知道结果属于每个类别的置信度,那它非常适合。
(2) 健壮性不强,相比于hinge loss对噪声更敏感。
(3) 逻辑回归的损失函数就是log对数损失函数。
4. 平方损失函数
平方损失函数标准形式如下:
特点:
(1) 经常应用于回归问题
5. 指数损失函数(exponential loss)
指数损失函数的标准形式如下:
特点:
(1)对离群点、噪声非常敏感。经常用在AdaBoost算法中。
6. Hinge 损失函数
Hinge损失函数标准形式如下:
特点:
(1) hinge损失函数表示如果被分类正确,损失为0,否则损失就为 1 − y f ( x ) 1-yf(x) 1−yf(x) 。SVM就是使用这个损失函数。
(2) 一般的 f ( x ) f(x) f(x) 是预测值,在-1到1之间, y y y 是目标值(-1或1)。其含义是, f ( x ) f(x) f(x) 的值在-1和+1之间就可以了,并不鼓励 ∣ f ( x ) ∣ > 1 |f(x)| > 1 ∣f(x)∣>1 ,即并不鼓励分类器过度自信,让某个正确分类的样本距离分割线超过1并不会有任何奖励,从而使分类器可以更专注于整体的误差。
(3) 健壮性相对较高,对异常点、噪声不敏感,但它没太好的概率解释。
7. 感知损失(perceptron loss)函数
感知损失函数的标准形式如下:
L ( y , f ( x ) ) = m a x ( 0 , − y f ( x ) ) L(y, f(x)) = max(0, -yf(x)) L(y,f(x))=max(0,−yf(x))
特点:
(1) 是Hinge损失函数的一个变种,Hinge loss对判定边界附近的点(正确端)惩罚力度很高。而perceptron loss只要样本的判定类别正确的话,它就满意,不管其判定边界的距离。它比Hinge loss简单,因为不是max-margin boundary,所以模型的泛化能力没hinge loss强。
8. 交叉熵损失函数 (Cross-entropy loss function)
交叉熵损失函数的标准形式如下:
注意公式中 x x x 表示样本, y y y 表示实际的标签, a a a 表示预测的输出, n n n 表示样本总数量。
特点:
(1) 本质上也是一种对数似然函数,可用于二分类和多分类任务中。
二分类问题中的loss函数(输入数据是softmax或者sigmoid函数的输出):
多分类问题中的loss函数(输入数据是softmax或者sigmoid函数的输出):
(2) 当使用sigmoid作为激活函数的时候,常用交叉熵损失函数而不用均方误差损失函数,因为它可以完美解决平方损失函数权重更新过慢的问题,具有“误差大的时候,权重更新快;误差小的时候,权重更新慢”的良好性质。
补充:对数损失函数和交叉熵损失函数应该是等价的!说明如下:
9. Contrastive Loss (对比损失)
在caffe的孪生神经网络(siamese network)中,其采用的损失函数是contrastive loss,这种损失函数可以有效的处理孪生神经网络中的paired data的关系。contrastive loss的表达式如下:
L = 1 2 N ∑ n = 1 N [ y d 2 + ( 1 − y ) m a x ( m a r g i n − d , 0 ) 2 ] L = \frac{1}{2N} \sum_{n=1}^N[yd^2 + (1-y)max(margin - d, 0)^2] L=2N1n=1∑N[yd2+(1−y)max(margin−d,0)2]
其中 d = ∣ ∣ a n − b n ∣ ∣ 2 d=||a_n−b_n||^2 d=∣∣an−bn∣∣2,代表两个样本特征的欧氏距离,y为两个样本是否匹配的标签,y=1代表两个样本相似或者匹配,y=0则代表不匹配,margin为设定的阈值。
这种损失函数最初来源于Yann LeCun的Dimensionality Reduction by Learning an Invariant Mapping,主要是用在降维中,即本来相似的样本,在经过降维(特征提取)后,在特征空间中,两个样本仍旧相似;而原本不相似的样本,在经过降维后,在特征空间中,两个样本仍旧不相似。
观察上述的contrastive loss的表达式可以发现,这种损失函数可以很好的表达成对样本的匹配程度,也能够很好用于训练提取特征的模型。1)当y=1(即样本相似)时,损失函数只剩下 ∑ y d 2 \sum yd^2 ∑yd2,即原本相似的样本,如果在特征空间的欧式距离较大,则说明当前的模型不好,因此加大损失。2)而当y=0时(即样本不相似)时,损失函数为 ∑ ( 1 − y ) m a x ( m a r g i n − d , 0 ) 2 \sum (1-y)max(margin-d, 0)^2 ∑(1−y)max(margin−d,0)2,即当样本不相似时,其特征空间的欧式距离反而小的话,损失值会变大,这也正好符号我们的要求。
这张图表示的就是损失函数值与样本特征的欧式距离之间的关系,其中红色虚线表示的是相似样本的损失值,蓝色实线表示的不相似样本的损失值。
10. focal loss
facal loss是加权的二分类交叉熵损失,用来解决样本不均衡和困难样本学习的问题。
记:
那么focal loss的表达式为:
其中, γ \gamma γ 越大,越关注难样本。某个类别 α \alpha α 越大,越关注该类别。
在原论文中正样本的 α = 0.25 , γ = 2 \alpha=0.25,\gamma=2 α=0.25,γ=2 , 其实是为了缓和 γ \gamma γ 增加正样本的权重,所以给正样本一个较小的值。
参考文章
1. 梯度不稳定问题:
什么是梯度不稳定问题:深度神经网络中的梯度不稳定性,前面层中的梯度或会消失,或会爆炸。
原因:前面层上的梯度是来自于后面层上梯度的乘积。当存在过多的层次时,就出现了内在本质上的不稳定场景,如梯度消失和梯度爆炸。
2. 梯度消失和梯度爆炸的产生原因
梯度消失经常出现,一是在深层网络中,二是采用了不合适的损失函数,比如sigmoid。梯度爆炸一般出现在深层网络和权值初始化值太大的情况下。
2.1 梯度消失(vanishing gradient problem):
因为通常神经网络所用的激活函数是sigmoid函数,这个函数有个特点,就是能将负无穷到正无穷的数映射到0和1之间,并且对这个函数求导的结果是f′(x)=f(x)(1−f(x))。因此两个0到1之间的数相乘,得到的结果就会变得很小了。神经网络的反向传播是逐层对函数偏导相乘,因此当神经网络层数非常深的时候,最后一层产生的偏差就因为乘了很多的小于1的数而越来越小,最终就会变为0,从而导致层数比较浅的权重没有更新,这就是梯度消失。
例如三个隐层、单神经元网络:
则可以得到:
然而,sigmoid方程的导数曲线为:
可以看到,sigmoid导数的最大值为1/4,通常abs(w)<1,则:
前面的层比后面的层梯度变化更小,故变化更慢,从而引起了梯度消失问题。
2.2 梯度爆炸(exploding gradient problem):
当初始化权值过大时,前面层会比后面层梯度变化的更快,导致权值越来越大,进而引起梯度爆炸问题。
在深层网络或循环神经网络中,误差梯度可在更新中累积,变成非常大的梯度,然后导致网络权重的大幅更新,并因此使网络变得不稳定。在极端情况下,权重的值变得非常大,以至于溢出,导致 NaN 值。
网络层之间的梯度(值大于 1.0)重复相乘导致的指数级增长会产生梯度爆炸。
如何确定是否出现梯度爆炸?
训练过程中出现梯度爆炸会伴随一些细微的信号,如:
小结:在反向传播过程中需要对激活函数进行求导,如果导数大于1,那么随着网络层数的增加梯度更新将会朝着指数爆炸的方式增加这就是梯度爆炸。同样如果导数小于1,那么随着网络层数的增加梯度更新信息会朝着指数衰减的方式减少这就是梯度消失。因此,梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足。
3. 梯度消失和梯度爆炸的解决办法
3.1 重新设计网络模型
梯度爆炸可以通过重新设计层数更少的网络来解决。使用更小的批尺寸对网络训练也有好处。另外也许是学习率过大导致的问题,减小学习率。
3.2 使用 ReLU 激活函数
梯度爆炸的发生可能是因为激活函数,如之前很流行的 Sigmoid 和 Tanh 函数。使用 ReLU 激活函数可以减少梯度爆炸。采用 ReLU 激活函数是最适合隐藏层的,是目前使用最多的激活函数。
relu函数的导数在正数部分是恒等于1的,因此在深层网络中使用relu激活函数就不会导致梯度消失和爆炸的问题。
ReLU的主要贡献在于:
同时也存在一些缺点:
Leaky ReLU:Leaky ReLU就是为了解决 ReLU 的 0 区间带来的影响,而且包含了 ReLU 的所有优点
ELU:ELU激活函数也是为了解决 ReLU 的 0 区间带来的影响
3.3 使用长短期记忆网络
在循环神经网络中,梯度爆炸的发生可能是因为某种网络的训练本身就存在不稳定性,使用长短期记忆(LSTM)单元和相关的门类型神经元结构可以减少梯度爆炸问题。采用 LSTM 单元是适合循环神经网络的序列预测的最新最好实践。
3.4 使用梯度截断(Gradient Clipping)
梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。
3.5 使用权重正则化(Weight Regularization)
如果梯度爆炸仍然存在,可以尝试另一种方法,即检查网络权重的大小,并惩罚产生较大权重值的损失函数。该过程被称为权重正则化,通常使用的是 L1 惩罚项(权重绝对值)或 L2 惩罚项(权重平方)。比如在tensorflow中,若搭建网络的时候已经设置了正则化参数,则调用以下代码可以直接计算出正则损失:
regularization_loss = tf.add_n(tf.losses.get_regularization_losses(scope='my_resnet_50'))
正则化是通过对网络权重做正则限制过拟合,仔细看正则项在损失函数的形式:
其中,α 是指正则项系数,如果发生梯度爆炸,权值的范数就会变的非常大,通过正则化项,可以部分限制梯度爆炸的发生。
注:事实上,在深度神经网络中,往往是梯度消失出现的更多一些。
3.6 预训练加finetunning
其基本思想是每次训练一层隐藏层节点,将上一层隐藏层的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,这就是逐层预训练。在预训练完成后,再对整个网络进行“微调”(fine-tunning)。Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。现在基本都是直接拿imagenet的预训练模型直接进行finetunning。
3.7 批量归一化
Batchnorm具有加速网络收敛速度,提升训练稳定性的效果,Batchnorm本质上是解决反向传播过程中的梯度问题。batchnorm全名是batch normalization,简称BN,即批规范化,通过规范化操作将输出信号x规范化保证网络的稳定性。from:Batch Normalization批量归一化
3.8 残差结构
残差网络的出现导致了image net比赛的终结,自从残差提出后,几乎所有的深度网络都离不开残差的身影,相比较之前的几层,几十层的深度网络,残差可以很轻松的构建几百层,一千多层的网络而不用担心梯度消失过快的问题,原因就在于残差的捷径(shortcut)部分,残差网络通过加入 shortcut connections,变得更加容易被优化。包含一个 shortcut connection 的几层网络被称为一个残差块(residual block),如下图所示:
相比较于以前网络的直来直去结构,残差中有很多这样的跨层连接结构,这样的结构在反向传播中具有很大的好处,见下式:
式子的第一个因子 ∂ l o s s ∂ x l \frac{\partial loss}{\partial x_l} ∂xl∂loss 表示的损失函数到达 L 的梯度,小括号中的1表明短路机制可以无损地传播梯度,而另外一项残差梯度则需要经过带有weights的层,梯度不是直接传递过来的。残差梯度不会那么巧全为-1,而且就算其比较小,有1的存在也不会导致梯度消失。所以残差学习会更容易。from:CNN经典模型:深度残差网络(DRN)ResNet
参考文章
神经网络权重不能初始化为常数,更不能全部初始化为0。
考虑全连接的深度神经网络,同一层中的任意神经元都是同构的,他们拥有相同的输入和输出,如果再将参数全部初始化为同样的值,那么无论前向传播还是反向传播的取值都是完全相同的。学习过程将永远无法打破这种对称性,最终同一网络层中的各个参数仍然是相同的。
因此,我们需要随机初始化神经网络参数的值,以打破这种对称性。简单来说,可以初始化参数为取值范围 ( − 1 d , 1 d ) (-\frac{1}{\sqrt{d}},\frac{1}{\sqrt{d}}) (−d1,d1) 的均匀分布,其中 d d d 是一个神经元接受的输入维度。偏置可以被简单地设为0,并不会导致参数对称的问题。
参考文章
Embedding:用一个低维的向量来表示一个物体,可以是一个词,或是一个商品,一个用户。这个embedding向量的性质是能使距离相近的向量对应的物体又相近的含义。
Embedding的作用
无论embedding在模型中最终起到哪些重要的作用,在对embedding的本质理解上,它自始至终都是用一个多维稠密向量来对事物从多维度进行的特征刻画。
训练方法
Word Embedding的训练方法大致可以分为两类:
以上回答来自知乎~
参考文章
embedding的size我一般采用个经验值,假如embedding对应的原始feature的取值数量为 n n n,那么我一般会采用 l o g s ( n ) log_s(n) logs(n) 或者 k n 4 ( k ≤ 16 ) k\sqrt[4]{n}(k \leq 16) k4n(k≤16) 来做初始的size,然后2倍扩大或缩小,实验几次,一般就能得到一个相对较好的值。另外,embedding的初始化也是非常重要的,需要精细调参。
以上回答来自知乎
参考文章
待补充