参数:W、b
超参数:
比如算法中的learning rate (学习率)、iterations(梯度下降法循环的数量)、L(隐藏层数目)、n(隐藏层单元数目)、choice of activation function(激活函数的选择)都需要你来设置,这些数字实际上控制了最后的参数W和b的值,所以它们被称作超参数。其他的还有一些:如momentum、mini batch size、regularization parameters等等。
使用一个神经网络时,需要决定使用哪种激活函数用隐藏层上,哪种用在输出节点上。
sigmoid激活函数:除了输出层是一个二分类问题基本不会用它。
tanh激活函数:tanh是非常优秀的,几乎适合所有场合。
ReLu激活函数:最常用的默认函数,,如果不确定用哪个激活函数,就使用ReLu或者Leaky ReLu。
sigmoid函数和tanh函数两者共同的缺点是,在特别大或者特别小的情况下,导数的梯度或者函数的斜率会变得特别小,最后就会接近于0,造成梯度弥散,导致降低梯度下降的速度。在实践中,使用ReLu激活函数神经网络通常会比使用sigmoid或者tanh激活函数学习的更快。
唯一可以用线性激活函数的通常就是输出层。
反向传播:
当你训练神经网络时,权重随机初始化是很重要的。对于逻辑回归,把权重初始化为0当然也是可以的。但是对于一个神经网络,如果你把权重或者参数都初始化为0,那么梯度下降将不会起作用。
如果你要初始化成0,由于所有的隐含单元都是对称的,无论你运行梯度下降多久,他们一直计算同样的函数。这没有任何帮助,因为你想要两个不同的隐含单元计算不同的函数,这个问题的解决方法就是随机初始化参数。你应该这么做:把W设为np.random.randn(2,2)(生成高斯分布),通常再乘上一个小的数,比如0.01;b可以初始化为0。
我们通常会将数据划分成几部分,一部分作为训练集,一部分作为简单交叉验证集,也称之为验证集(dev set),最后一部分则作为测试集。
当数据量较小时,通常按照70%训练集,30%测试集来划分,如果没有明确设置验证集,也可以按照60%训练,20%验证和20%测试集来划分。
但是在大数据时代,我们现在的数据量可能是百万级别,那么验证集和测试集占数据总量的比例会趋向于变得更小。因为验证集的目的就是验证不同的算法,检验哪种算法更有效;测试集的主要目的是正确评估分类器的性能。假设我们有100万条数据,其中1万条作为验证集,1万条作为测试集,100万里取1万,比例是1%,即:训练集占98%,验证集和测试集各占1%。对于数据量过百万的应用,训练集可以占到99.5%,验证和测试集各占0.25%,或者验证集占0.4%,测试集占0.1%。
如果给这个数据集拟合一条直线,可能得到一个逻辑回归拟合,但它并不能很好地拟合该数据,这是高偏差(high bias)的情况,我们称为欠拟合(underfitting)。
相反的如果我们拟合一个非常复杂的分类器,比如深度神经网络或含有隐藏单元的神经网络,分类器高方差(high variance),数据过拟合(overfitting)。
上图是在两者之间,复杂程度适中,数据拟合适度的分类器,这个数据拟合看起来更加合理,我们称之为适度拟合(just right)是介于过度拟合和欠拟合中间的一类。
高偏差(欠拟合):
神经网络初始模型训练完成后,首先要知道算法的偏差高不高,如果偏差较高,试着评估训练集或训练数据的性能。如果偏差的确很高,甚至无法拟合训练集,那么你要做的就是选择一个新的网络,比如含有更多隐藏层或者隐藏单元的网络(扩大网络规模),或者花费更多时间来训练网络,或者尝试更先进的优化算法。不断尝试这些方法,直到解决掉偏差问题,可以拟合数据为止,至少能够拟合训练集。
高方差(过拟合):
一旦偏差降低到可以接受的数值,检查一下方差有没有问题,为了评估方差,我们要查看验证集性能,我们能从一个性能理想的训练集推断出验证集的性能是否也理想,如果方差高,最好的解决办法就是采用更多数据,但可能没办法获得那么多数据,这时也可以尝试通过正则化来减少过拟合,但是如果能找到更合适的神经网络框架,有时它可能会一箭双雕,同时减少方差和偏差。
除了正则化,还有几种方法可以减少神经网络中的过拟合:
1.数据扩增
假设你正在拟合猫咪图片分类器,如果你想通过扩增训练数据来解决过拟合,但扩增数据代价高,而且有时候我们无法扩增数据,但我们可以通过翻转图片、裁剪图片,并添加到训练集。通过翻转图片,训练集则可以增大一倍,因为训练集有冗余,这虽然不如我们额外收集一组新图片那么好,但这样做节省了获取更多猫咪图片的花费。
2.early stopping
early stopping要做就是在中间点停止迭代过程,我们得到一个值中等大小的弗罗贝尼乌斯范数。
如果神经网络过度拟合了数据,即存在高方差问题,那么最先想到的方法可能是正则化,正则化有助于避免过度拟合,或者减少网络误差。另一个解决高方差的方法就是准备更多数据,这也是非常可靠的办法,但有时可能无法获得更多的数据。
以逻辑回归为例,一般使用L2正则化,其中λ是正则化参数,我们通常使用验证集或交叉验证集来配置这个参数,尝试各种各样的数据,寻找最好的参数,我们要考虑训练集之间的权衡,把参数设置为较小值,这样可以避免过拟合,所以λ是另外一个需要调整的超级参数。
在神经网络中,使用的是“弗罗贝尼乌斯范数”,它表示一个矩阵中所有元素的平方和。
用backprop计算出的值,backprop会给出J对W的偏导数,现在我们在dW后边加上了这个正则化项。
W的系数小于等于1,所以L2范数正则化也被称为“权重衰减”,它就像一般的梯度下降。
如果正则化λ设置得足够大,权重矩阵W被设置为接近于0的值(L2正则化的权重更大了,为了使总误差J更小,需要W更小。),直观理解就是把多隐藏单元的权重设为0,神经网络的所有隐藏单元依然存在,但是它们的影响变得更小了。
总结一下,如果正则化参数变得很大,参数W很小,z也会相对变小,此时忽略b的影响,z会相对变小,实际上,z的取值范围很小,这个激活函数,也就是曲线函数会相对呈线性,整个神经网络会计算离线性函数近的值,这个线性函数非常简单,并不是一个极复杂的高度非线性函数,不会发生过拟合。
除了L2正则化,还有一个非常实用的正则化方法——“Dropout(随机失活)”,Dropout是一种正则化方法,它有助于预防过拟合。
如果神经网络中存在过拟合,dropout会遍历网络的每一层,并设置神经网络中每个节点得以保留和消除的概率都是0.5。之后我们会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个节点更少,规模更小的网络,然后用backprop方法进行训练。
单个神经元不能依靠任何特征,因为特征都有可能被随机清除,或者说该单元的输入也都可能被随机清除。我不愿意把所有赌注都放在一个节点上,不愿意给任何一个输入加上太多权重,因为它可能会被删除。
keep-prob的选择:
它代表每一层上保留单元的概率。所以不同层的keep-prob也可以变化。第一层,矩阵W1是7×3,第二个权重矩阵W2是7×7,第三个权重矩阵W3是3×7,以此类推,W2是最大的权重矩阵,因为W2拥有最大参数集,即7×7,为了预防矩阵的过拟合,对于第二层,它的keep-prob值应该相对较低,假设是0.5。对于其它层,过拟合的程度可能没那么严重,它们的keep-prob值可能高一些,可能是0.7,这里是0.7。如果在某一层,我们不必担心其过拟合的问题,那么keep-prob可以为1,每层keep-prob的值可能不同。
注意keep-prob的值是1,意味着保留所有单元,并且不在这一层使用dropout,对于有可能出现过拟合,且含有诸多参数的层,我们可以把keep-prob设置成比较小的值,以便应用更强大的dropout。
训练神经网络,其中一个加速训练的方法就是归一化输入。归一化需要两个步骤:
1.零均值化
2.归一化方差
也就是每个z值减去均值再除以标准偏差,为了使数值稳定,通常将ε作为分母,以防σ=0的情况。Batch归一化发生在z的计算a和之间,即把z归一化后将其输入激活函数中得到a。
在神经网络中间层也进行归一化处理,使训练效果更好的方法,就是批归一化Batch Normalization(BN)。
在CNN中,BN应作用在非线性映射前。在神经网络训练时遇到收敛速度很慢,或梯度爆炸等无法训练的状况时可以尝试BN来解决。另外,在一般使用情况下也可以加入BN来加快训练速度,提高模型精度。
比方说六层楼,每层布局一样,BatchNorm是一层楼,LayerNorm是不同楼层的同一部位取。
训练神经网络,尤其是深度神经所面临的一个问题就是梯度消失或梯度爆炸,也就是你训练神经网络的时候,导数或坡度有时会变得非常大,或者非常小,甚至于以指数方式变大/小,这加大了训练的难度。
权重W大于1,L层的网络W要乘L-1次,所以深度神经网络的激活函数将爆炸式增长,同理,W<1,激活函数将呈指数递减。