Setting up your ML application

神经网络和深度学习[1-2]
神经网络和深度学习[1-3]
神经网络和深度学习[1-4]
改善深层神经网络:超参数调试、正则化以及优化【2-1】
改善深层神经网络:超参数调试、正则化以及优化【2-2】
改善深层神经网络:超参数调试、正则化以及优化【2-3】
结构化机器学习项目 3
Ng的深度学习视频笔记,长期更新

1.1 Train/dev/test/sets

数据一部分作为训练集,一部分作为交叉验证集(验证集),最后一部分作为测试集;通过训练集来训练模型,通过验证集来选择最好的模型,然后在测试集上进行评估(无偏估计)【测试集的目的是对神经网络系统做出无偏估计,如果不需要无偏估计,可以不设置测试集】
在实际应用中,没有测试集的情况,人们将简单的交叉验证集当测试集来使用,并没有完全实现该术语的功能,因为将验证集过度拟合到测试集中了。

1.2 Bias/Variance

之前分析过,见下面这张图:
dl0501
对于Cat classification来说,假设人类识别错误率为0%
训练集上的结果是1%,而在测试集上的结果却是11%,显然过拟合了,即高方差,可以这么理解:该模型对不同的数据的结果有较大的差异就是高方差,但是对于结果而言效果还是比较好的(低偏差);
训练集上的结果是15%,测试集上的结果是16%,不管是训练集和测试集的效果都不是很好,即欠拟合(高偏差),但是模型对不同的数据的预测结果差别不大,即低方差;
训练集上的结果是15%,测试集上的结果是30%,这个就是高方差,高偏差;
训练集上的结果是0.5%,测试集上的结果是1%,这个就是低方差,低偏差。【这种情况在视频中有讲到,就是有的地方过拟合,而有的地方欠拟合】

1.3 Basic “recipe” for machine learning

当我们训练神经网络时,初始化模型完成后,当模型的偏差过高,就需要对训练集进行再次分析,或者是选择一个新的网络(如含有更多隐藏层的网络),或者花费更多时间来训练算法,或者尝试更先进的优化算法,直到可以拟合数据为止(有一个小得偏差),这是第一步。一旦偏差小到可以接受的值后,就可以检查一下方差是否有问题,即需要对验证集预测,如果方差过大,解决办法是训练集使用更多的数据,或者使用正则化等等,然后不断的尝试,直到找到一个低偏差,低方差的模型,我们就成功了。
在深度学习的早期,我们没有太多工具可以做到减少偏差或方差,而不影响另一方,现在的工具可以做到在减小偏差或方差的同时,不对另一方产生过多不良的影响,这个是深度学习对监督式学习大有裨益的一个重要原因,也是我们不用太过关注如何平衡偏差和方差的一个重要原因。

1.4 Regularization

详细可以参考UFLDL教程,至于正则化为什么只用W而不用b,视频中讲到W几乎涵盖了全部参数,b只是众多参数中的一部分,加上没有太大的影响,所以通常省略不计。
加上正则化后,神经网络的成本函数变为

其中由于的维度为,因此
继续分析为什么加上正则化后,会让W变小(是W的绝对值变小,即趋近于0),分析反向传播过程,可以发现添加正则项后,只是对多添加了一个项,那么对于权重更新时,假设之前的$dW^{[l]}=(for backprop)$,则现在的变为,即

注意到恒小于1,也就是说加上正则项后,对W的影响是将W变为趋近于0的数。

1.5 Why regularization reduces overfitting

为什么正则化有利于预防过拟合呢,即为什么可以减少方差问题?
添加正则项可以避免数据权值矩阵过大,为什么L2正则可以减少过拟合,直观的理解是当设置很大的时候,权重矩阵会被设置为接近于0的值,即把多层隐藏单元的权重设置为0,消除了这些隐藏单元的影响,这样神经网络就会变成一个很小的网络,如同一个logistic回归单元,这样就将一个过拟合的网络变成了高偏差的网络,如下图红色箭头所示:
dl0502
但是很显然我们不会这样做,我们会选取一个,使得模型接近于上图的中间模型“just right”。
继续看下面这个例子,假设我们用的是双曲激活函数,如果z非常小,即当正则化参数很大时,激活函数的参数会相对小(即W会小,而z=wa+b),那么双曲激活函数对于z而言,就是线性函数,每层激活都是线性的,那么深层网络也只能计算线性函数,不适合非常复杂的决策以及允许过度拟合数据集的非线性决策边界(原文:very non-linear decision boundaries that allow it to really overfit right to data sets)。
可以看到代价函数对于梯度下降的每一个调幅都单调递减,如果你实现的是正则化,J有一个新的定义,而原来的不带正则项的J可能看不到单调递减的现象,为了调试梯度下降,应该使用带有正则化项的J函数,否则J可能不会在所有调幅范围内都单调递减。【这一段没太明白???】

1.6 Dropout regularization

除了L2正则外,还有一个非常实用的正则化方法—“dropout”
假设训练的神经网络存在过拟合,dropout会遍历网络中的每一层,并设置消除神经网络中节点的概率,即假设每个节点被保留下来的概率是0.5,使用dropout后,就会将没被保留的节点删除,及其连线,如下图所示:
dl0503
实施dropout的方法:inverted dropout
以第三层为例,给定一个keep-prob(保留率)

1
2
3
d3=np.random.rand(a3.shape[0],a3.sharp[1])<keep-prob
a3=np.multiply(a3,d3)
a3/=keep-prob

这里之所以要做第三行的代码,是因为需要在删除后的效果和原来的一样,即不影响后面的期望,需要弥补神经元为0的元素
这里补充一下:为什么dropout可以降低过拟合?
直观的理解就是,每个节点都有可能被删除,因此网络不愿意将所有的赌注全部放在一个节点上,即不会给任意的输入加上过多的权重,因为它可能被删除。和L2正则的效果一样,实施dropout的结果就是它会压缩权重,并完成一些预防过拟合的外层正则化。
每层的keep-prob的值可能不同,对于含有很多神经元的层,可以将keep-prob设置成比较小的值。dropout是一种正则化方法,目的是为了预防过拟合,所以除非算法过拟合,不然不应该使用dropout,因此该方法在其它领域用的比较少(之于计算机视觉,因为视觉模型会有很多的参数,但是训练样本有很有限)。
dropout的一大缺点是代价函数J不再被明确定义,因为每次迭代都会随机移除一些节点,很难核查梯度下降,对于定义明确的代价函数J每次迭代后都会下降….因此使用Dropout时,先关闭dropout的功能(设置keep-prob=1),确保J函数代缴递增,然后开启dropout函数。【关于此处,我不是太明白,后期实践实践】

1.8 Other regularzation methods

可以作为正则化的方法有:

  1. 数据扩增:可以对原有的样本进行处理后作为新的样本,当然也可以添加更多数据了
  2. early stopping :代价函数在训练集会越来越小,但是对于验证集却会在某一个点上开始上升,提前结束优化,可以解决过拟合问题,但是同时也会停止优化而带来偏差。

如果不用early stopping,另一种方法就是L2正则化,这样训练网络的时间就会很长,必须尝试很多正则化参数的值,计算代价太高。early stopping的优点是只运行一次坡度下降,就可以找到W,而不需要尝试L2正则化。

1.9 Normalizing inputs

训练神经网络的一个加速训练的方法就是归一化输入,即将数据0均值化,1方差化,如下处理:

这里也很容易验证,将变换后的结果代入计算均值和方差的公式中,就会发现数据的均值为0,方差为1(这里Ng的视频中我觉得写错了,应该是除以标准差),如下图所示,一个二维的数据集,在每一维上作归一化处理后的结果:
dl0504
继续,为什么归一化后就会加速训练呢,下面这张图,假设特征x1的取值范围是0到100,而特征x2的取值范围是0到1,那么w1和w2的范围就会很不一样,这里用下图的w和b表示,对应的下面的图中显示的梯度下降曲线就会是z字型(这里这样理解:从起点到最小值的直线是梯度下降训练时间最短的路线,但是该线上每走一步,对应的dw1方向上要做过的大小和dw2方向上要走过的大小很显然是不一样的,但是我们在梯度训练的过程中,每次对w1和w2的变化都是相同的,即,所以导致实际的路线并不是按照最短路线来走,而是呈现z字型);归一化的数据各方向都是圆,这样梯度下降训练的时候就会沿着最短路径走,见下图:
dl0505

1.10 Vanishing/exploding gradients

梯度消失和梯度爆炸
dl0506
这里举一个简单的例子,如上图所示,每一层省略了很多神经元,假设,对于目标输出有:

这里假设为大于1的情况,即,让其它的W也都为该值,这样的多层叠加相乘后,就会出现一个很大的值,也就是说梯度函数出现爆炸。
相应的,如果W是小于1的情况,多层叠加的后果就是梯度函数接近于0,即梯度消散。

那么怎么解决上面的问题呢,见下面的图:
dl0507
以单个神经元为例,忽略b,这里有:

视频中说为了预防z值过大或者过小(为什么不让z过大或过小呢,因为z过大或者过小,表明W矩阵过大或者过小,那么就会出现上面讲到的梯度爆炸和梯度消失),即对于输入n越大(这里n代表特征x的个数),希望越小,这样z就不会过大。那么最合理的方法就是使的方差为,即对于每层的权重矩阵作如下初始化:

1
WL = np.random.randn(WL.shape[0],WL.shape[1])* np.sqrt(1/n)

这里讲原因:上面的randn表示的是随机数服从均值为0方差为1的正太分布,我们要让其服从方差为的正太分布,需要对数据除以标准差,即。那么为什么要让其服从方差为的正太分布呢,我是这么理解的:我们知道方差决定了数据的离散程度,对于上图单个神经元的权重wi,如果我们对每个wi都初始化均值为0,方差为1的数据,这样z的值就服从均值为0,方差为n的正太分布,而如果我们将每个wi的初始化分布改为,那么z的值就服从N(0,1).
对于g(z)为ReLu函数,将其方差设置成比较好,视频中也提到了几种其它的公式。

Numerical approximation of gradients

这一节就讲了一个知识点,就是导数的定义:

讲到上面的双边导数比单边导数类比于导数的实际值来说更加精确。

Gradient Checking

这一节讲的是梯度验证,对于代价函数表示为,即组成。
对于,我们需要计算:

与反向传播的梯度核查:

上式的分子部分是计算相似度,即差的平方和开根号;分母部分是为了不让分子太小或太大(即规范因子)。
怎么验证呢,举个例子:当的时候,如果上式的结果Check接近于,那么说明梯度计算没有什么问题,如果差了几个数量级,比如,就可能有问题了。

第一周的课终于看完了,可真多啊,看了快一天了…

如果觉得有帮助,给我打赏吧!