吴恩达deeplearning.ai《改善深层神经网络:超参数调试、正则化以及优化》-超参数调试,Batch正则化和程序框架(三)
调试处理
根据调参的重要程度排序,首要重要的是红色,即学习率α,其次重要为黄色,再次之为紫色。
当我们尝试参数的时候,尽量采用一定范围内随机取值。而不是划定网格,有规律的取值。因为面对很多维度参数时,很难说我们能直观衡量出哪一个参数对于整个学习更加重要。如果你随机取值,也就能探索更多超参数的潜在值。
当我们寻找在一个区域的参数表现很好的时候,我们可以划定一个范围,更加精细的随机尝试取值。即大范围粗略尝试,小范围精细尝试。
为超参数选择合适的范围
当我们选择参数时,一般要选定一个合理的范围。之后在这个范围内,做采样与尝试。
如果,我们设定的参数范围位于[0.0001,1]
采用整个区间随机取值的话,那么相比于[0.1,1]区间与[0.0001,0.1]区间,就会在[0.1,1]区间中随机取值更多。很明显可见1-0.1=0.9,0.1-0.0001=0.0998。
故我们一般采用区间划分小区间,然后再小区间中再进行随机取值。即[0.0001,0.001],[0.001,0.01],[0.01,0.1],[0.1,1]
指数平均数的参数取值
当取值区间位于[0.9000,0.9005]时,对算法的影响不大。当区间位于[0.999,0.9995]时,对算法的影响很大。因为1/1-β ,当β接近1的时候,函数图像变化会加大。
超参数训练的实践
当我们的数据集增大,等更新后我们需要定期更新的我们的参数。来让参数符合新的数据集
对于机器学习算法的尝试,我们有两种方法:babysitting one model,training many models in parallel。对于数据量大,计算能力有限的,我们一般采用babysitting法,即一次训练一个算法。多次调整让其达到效果最佳。对于计算能力充足的,我们可以同时尝试多个算法,并且取效果最好的那个。
正则化网络的**函数
batch normalization批规范化可以使神经网络对超参数的选择更加稳定。超参数的范围会扩大,提升效果。让你能够轻松训练深度神经网络。
传统的归一化,就是优化输入的特征向量。把问题的等高图,从椭圆编程圆形。从而更易于梯度下降算法的运行。
而我们引入神经网络之后,我们的中间节点,a[1],a[2]…也需要归一化的优化。例如:我们能优化a[2],就能更好的训练w[3],b[3]。(吴恩达课程中是优化z[2],优化a[2]还是z[2],学术界存在争议)
前几步类似于普通归一化的步骤。计算z[i]的均值与方差,然后用z[i]-均值 / 根号 方差 + ε。我们这里增加ε,是为了防止方差为0的情况,导致分母为0,除法无法进行计算。
我们不想让这些z的隐藏节点,总是平均值为0,方差为1。因为如果是平均值为0,方差为1,当我们将z放入sigmod等**函数中,出来的值会集中在函数的y轴附近的线性区间中。
故我们增加了zN(i),来防止产生平均值为0,方差为1的情况。其中,我们尽量避免γ和β参数,设为根号方差平方+ε,β设为μ。这样相当于zN(i) = z(i),失去了调整的意义。
将batch norm拟合进神经网络
传统的神经网络路径是:x -> z[1] -> a[1]
如果我们加入了barch norm的情况下:x -> z[1] -> zN[1] -> a[1]
即对z[1],我们加入了batch norm正则化方法,其中z[1] -> zN[1]的路径上,我们需要参数γ和β,来调控正则化的程度。在tensorflow框架中,我们使用tf.nn.batch-normalization,来实现batch norn归一化。
由于我们在归一化的过程中,需要让z[l],减去均值,除以方差。故,对于,从a[l]到z[l]公式中,w[l] a[l-1] + b[l] 可以去掉参数b[l]。因为之后归一化中,z[l]会减去其均值,导致加上b[l]没有了意义。剩下的调节功能,转移到β[l]。
注:我们可以看到,z[l],w[l],b[l],β[l],γ[l]其都是(n[l] , 1)维度的
我们也可以使用其他优化函数,来计算由batch norm算法,而新加入的两个参数,β和γ。如,momentum,RMSprop,Adam
batch norm为什么奏效
如果我们把整个数据集分为很多小batch。那么,我们每一个batch输入的数据都具有不同的分布,显然会给网络的训练带来困难。(比如第一个batch是训练集的左上角,第二个batch是训练集的右下角)
另一方面,数据经过一层层网络计算后,其每一层隐藏节点的数据分布也在发生着变化,此现象称为Internal Covariate Shift。(因为,隐藏节点的值由前一层和前前层的值决定。输入的batch分布不同,必然导致隐藏节点的分布也发生改变)故,我们需要引入batch norm。也就是虽然数据分布会改变,但是每一层向下一层传递的时候。其节点的值,都是均值为0,方差为1。也就是将均值和方差进行了统一。
补充:
举个简单线性分类栗子,假设我们的数据分布如a所示,参数初始化一般是0均值,和较小的方差,此时拟合的y=wx+b
如b图中的橘色线,经过多次迭代后,达到紫色线,此时具有很好的分类效果,但是如果我们将其归一化到0点附近,显然会加快训练速度,如此我们更进一步的通过变换拉大数据之间的相对差异性,那么就更容易区分了。
这种方式会减小图像之间的绝对差异,突出相对差异,加快训练速度。
batch norm还有轻微的正则化的作用。
因为每一个mini-batch中的均值和方差,都是自己batch中的均值和方差。并没有用到整体数据集的均值与方差。故,每一个batch中的均值与方差都是不同的。
类似于dropout算法,这些相当于给z[l]增加了噪音。也就类似于正则化中的惩罚项。故,使其有了轻微正则化作用。
注意:
在batch norm中,使用大的mini-batch的值。会导致batch中的噪音数量减少。也就是更大的mini-batch,会减弱正则化的力度。
测试时的batch norm
在训练时,我们将数据集分成batch来训练。但是在测试时,我们却是每一个单一数据来进行预测。(如,训练时一个batch大小为30,30个数据同时进行训练处理。但是测试中我们是单一,一个一个图片顺序进行预测)
我们可见batch norm算法的公式中,主要对我们测试产生影响的就是均值μ和方差β。因为单一一个数据,没有均值和方差。故我们需要引入一种方法,来估算均值和方差。在这里我们采用了指数加权平均(exponentially weighted averges)来估算μ和β。我们可以算出每一个batch,其均值和方差。故,我们的做法就是对所有的batch,产生的均值和方差,来计算指数加权平均数。最后,将估算的均值方差,引入整体公式即可。
注:
指数加权平均数计算方法:
其中,
θ_t:为第 t 天的实际观察值,
V_t: 是要代替 θ_t 的估计值,也就是第 t 天的指数加权平均值,
β: 为 V_{t-1} 的权重,是可调节的超参。( 0 < β < 1 )
softmax回归
我们平时使用的逻辑回归都是二分类问题。即,某个动物是不是猫。当我们需要解决多分类问题时,我们可以采用softmax回归。也就是某个动物,是猫,是狗,还是小鸡,还是其他。softmax回归,最后会输出一个向量。其每个节点,代表了预测分类,每个分类的概率。
计算过程是:
在z[l]的基础上,每个进行element-wise求指数,得到t向量。最后对每个t向量中每个元素,除以t节点的和,得到每个分类的概率(因为多分类所有概率加起来应该是1)
具体举例,可见下图的计算过程。
举例,当我们不加入其他隐藏节点的时候。即输入层,输出层。最后多分类结果如下:
即线性进行分类。当我们需要进行非线性的分类时,可以增加隐藏节点。
训练一个softmax分类器
softmax之所以叫这个名字,因为其对应的一个算法叫hardmax。也就是当某一类概率最大时,将其标为1,其余标为0。也就是为1的,代表预测的数据分到某一类。
而softmax就比较软,其只是输出了不同类别的概率。
另外,如果我们将分类数变为1。softmax回归可以转化为逻辑回归。
对于softmax我们的损失函数,不同于其他算法采用的最小二乘法。softmax损失函数,采用了-∑ yj log y^j ,即负的求和,yj成y预测值取对数。只管理解是,我们想要预测值y^最大化。即,预测值对于正确类的概率最大。(也可以采用最大似然估计来解释,这是其中一种估计)
注:
输入向量的维度是(4,m),输出向量的维度也是(4,m)
最后softmax算法,反向传播。来计算导数,最后完成整个过程。
深度学习框架
现有的深度学习框架如下:
tensorflow
tf.Variable来设定参数
tf.add函数中表达了公式:
tf.train.GradientDescentOptimizer(0.01)设定学习率为0.01
minimize(cost)目的是最小化损失函数
在下面几行是惯用表达
session.run(w)来评估w,因为一开始算法还没有运行。故初始值w为0
session.run(train)来运行一次梯度下降。获得w,b
我们再一次session.run(w)来评估w。此时w被更新为0.1
运行1000次,再一次评估w。此时w的值为4.9999,很接近w的最优值5
当我们训练神经网络的时候,训练数据集中x可能会随时改变。
故,我们将训练集x引入程序。
首先,x=tf.placeholder(tf.float32,[3,1]),3行一列的向量
接下来,损失函数
cost = x[0][0]*w**2 + x[1][0]*w + x[2][0] # w2-20w +100 (w-5)**2
定义数组
coefficient = np.array([[1], [-20], [25]])
之后我们需要将数组coefficient 和数据集x 联系起来
feed_dict={x:coefficients}
可见1000次迭代,最后w值为9.99998.十分接近w的最佳值10.
我们可以使用右边的with tf.Session() as session代替左边的代码
此外,如果我们想要更换其他优化方法,可以更换tf.train.GradientDescentOptimizer。如,可以采用Adam优化方法