训练集,验证集,测试集
训练集:训练模型
验证集:选择最好的模型
测试集:无偏评估算法的运行状况。
要确保验证集和测试集的数据来自同一分布
如果不需要无偏估计,也可以不设置测试集。
搭建训练验证集和测试集能够加速神经网络的集成,也可以更有效地衡量算法的偏差和方差,从而帮助我们更高效地选择合适方法来优化算法。
偏差与方差
- 假设这就是数据集,如果给这个数据集拟合一条直线,可能得到一个逻辑回归拟合,但它并不能很好地拟合该数据,这是高偏差(high bias)的情况,我们称为“欠拟合” (underfitting)。如上图
- 相反的如果我们拟合一个非常复杂的分类器,比如深度神经网络或含有隐藏单元的神经网络,可能就非常适用于这个数据集,但是这看起来也不是一种很好的拟合方式分类器方差较高(high variance),数据过度拟合(overfitting)。如上图
- 在两者之间,可能还有一些像图中这样的,复杂程度适中,数据拟合适度的分类器,这个数据拟合看起来更加合理,我们称之为“适度拟合”(just right)是介于过度拟合和欠拟合中间的一类。
在这样一个只有x1和x2两个特征的二维数据集中,我们可以绘制数据,将偏差和方差可视化。在多维空间数据中,绘制数据和可视化分割边界无法实现,但我们可以通过训练集误差和验证集误差来分析偏差和方差。
假定训练集误差是 1%,验证集误差是 11%,可以看出训练集设置得非常好,而验证集设置相对较差,我们可能过度拟合了训练集,在某种程度上,验证集并没有充分利用交叉验证集的作用,像这种情况,我们称之为“高方差”。
可以采取的方法:最好的解决办法就是采用更多数据;我们也可以尝试通过正则化来减少过拟合
假设训练集误差是 15%,验证集误差是 16%,假设该案例中人的错误率几乎为 0%,人们浏览这些图片,分辨出是不是猫。算法并没有在训练集中得到很好训练,如果训练数据的拟合度不高,就是数据欠拟合,就可以说这种算法偏差比较高。相反,它对于验证集产生的结果却是合理的,验证集中的错误率只比训练集的多了 1%,所以这种算法偏差高。
可以采取的方法:选择一个新的网络,比如含有更多隐藏层或者隐藏单元的网络,或者花费更多时间来训练网络,或者尝试更先进的优化算法。
训练集误差是 15%,偏差相当高,但是,验证集的评估结果更糟糕,错误率达到 30%。因此,这种算法偏差高,因为它在训练集上结果不理想,而且方差也很高,这是方差偏差都很糟糕的情况。
以上分析的前提是假设基本误差很小,训练集和验证集数据来自相同分布
正则化
正则化会导致模型在训练集上的表现变差,因为它削弱了网络拟合的能力,从而解决了过拟合,提供了测试集的正确率
L2正则化
逻辑回归实现正则化
求成本函数𝐾的最小值,它是我们定义的成本函数,参数包含一些训练数据和不同数据中个体预测的损失,w和b是逻辑回归的两个参数,w是一个多维度参数矢量,b是一个实数。在逻辑回归函数中加入正则化,只需添加参数 ,如下图。L2正则化。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fVk1PUBC-1666101811888)(https://cdn.jsdelivr.net/gh/DaoChenLiu/images/learning_report3/202210101119630.png)]
为什么只正则化w?
因为w是一个多维参数,而b只是一个实数,如果加了b,并没有多大影响。
L1正则化,参数就是:
在神经网络中实现正则化
该矩阵范数被称作“弗罗贝尼乌斯范数”。
该如何使用该范数实现梯度下降呢?
L2正则化也被称为“权重衰减”。
为什么正则化可以消除过拟合
直观上理解就是如果正则化λ设置得足够大,权重矩阵W被设置为接近于 0 的值,直观理解就是把多隐藏单元的权重设为 0,于是基本上消除了这些隐藏单元的许多影响。如果是这种情况,这个被大大简化了的神经网络会变成一个很小的网络,小到如同一个逻辑回归单元,可是深度却很大,它会使这个网络从过度拟合的状态更接近左图的高偏差状态。
但是λ会存在一个中间值,于是会有一个接近“Just Right”的中间状态。
λ太大,会导致高偏差
dropout正则化
思想:随机让一部分神经元失效,生成一个简化的子神经网络。
通过dropout正则化,使得神经元之间的联系变弱,因为其他神经元可能会被删除。
假设你在训练上图这样的神经网络,它存在过拟合,这就是 dropout 所要处理的,我们复制这个神经网络,dropout 会遍历网络的每一层,并设置消除神经网络中节点的概率。设置完节点概率,我们会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个节点更少,规模更小的网络,然后用 backprop 方法进行训练。
这是网络节点精简后的一个样本,对于其他样本,以同样的方式执行
步骤
假设有一个三层的神经网络
在正向传播上应用dropout
在第三层如何实施?
- 首先定义三层的 dropout 向量d[3]
'''
a3的第三层的激活函数的输出,keep-prob是不大于1的正数
假设keep-prob=0.8,最终d3中的元素小于0.8的被置为1,大于等于0.8的被置为0
'''
d3=np.random.rand(a3.shape[0],a3.shape[1])<keep_prob
注意点
np.random.rand()
通过本函数可以返回一个或一组服从“0~1”均匀分布的随机样本值(正的浮点数)。随机样本取值范围是[0,1),不包括1。
np.random.randn()
1. 当函数括号内没有参数时,则返回一个浮点数;
2. 当函数括号内有一个参数时,则返回秩为1的数组,不能表示向量和矩阵;
3. 当函数括号内有两个及以上参数时,则返回对应维度的数组,能表示向量或矩阵;
4. np.random.standard_normal()函数与np.random.randn()类似,但是np.random.standard_normal()的输入参数为元组(tuple)。
5. np.random.randn()的输入通常为整数,但是如果为浮点数,则会自动直接截断转换为整数。
作用:通过本函数可以返回一个或一组服从标准正态分布的随机样本值。
d[3] 是一个矩阵,对应每个样本和每个隐藏单元,其中d[3] 中的对应值为 1 的概率都是 0.8,对应为 0 的概率是 0.2。
- 然后就是从第三层中获取激活函数a[3]
a3=np.multiply(a3,d3)
该语句的作用就是将a3对应位置的元素置0
- 最后a3/keep-prob
a3/=keep_prob
为什么要这么做?
假设第三隐藏层上有50 个神经元,在一维上a[3]是 50,我们通过因子分解将它拆分成50 × m维的,保留和删除它们的概率分别为 80%和 20%,这意味着最后被删除或归零的单元平均有 10(50×20%=10)个,现在我们看下𝑨[4] ,𝑨[4] = w[4] a[3] + b[4] ,现在a[3] 中有 20%的元素被归零,为了不影响𝑨[4] 的期望值,我们需要用 w[4] a[3] /0.8,它将会修正我们所需的那 20%.
在反向传播上应用dropout
- 关闭和正向传播相同的神经元
dA2=np.multiply(dA2,D2)
- 修正
dA2/=keep_prob
总结
如果要实施dropout,正向传播和反向传播都要改变
在不同层上实施dropout时,不同层的keep-prob可以不同,keep-prob越小,表示过拟合程度越大。
当keep-prob等于1时,相当于不实施dropout
数据扩增
通过对训练集数据做各种处理,从而增加数据集的规模。方法如下:
- 水平翻转图片
- 随意翻转加裁剪
early stopping
将J函数和dev error画在一个图上,然后在要发生过拟合的附近终止训练即可。
优点:简单快速。
缺点:无法发挥出其他工具的力量,试图使用一个方法同时降低bias和variance,难以取得极致的效果。
归一化
训练神经网络,其中一个加速训练的方法就是归一化输入。假设一个训练集有两个特征,输入特征为 2 维,归一化需要两个步骤:
假设训练集如下:
- 零均值,作用就是移动训练集到原点位置,具体流程如下图
执行后的训练集如下图:
- 归一化方差,具体操作如下图
执行后的训练集如下图:
无论是训练集和测试集都是通过相同的u和𝜎2 定义的数据转换,这两个是由训练集得出来的。
为什么要归一化输入特征?
如果使用非归一化的输入特征,代价函数如下图:
如果使用归一化的输入特征,代价函数如下图:
使用归一化的好处在于,不论从哪个位置开始,梯度下降法都能够更直接地找到最小值,且可以在梯度下降法中使用较大
步长。
权重W的元素比1略大,激活函数将指数级增长;比1略小,激活函数将指数级递减
神经网络的权重初始化
如果本层的激活函数是tanh,W初始化:
W[l] =np.random.randn(n[l] ,n[l-1] ) * np.sqrt(1/n[l-1])
如果本层的激活函数是Relu,W初始化:
W[l] =np.random.randn(n[l] ,n[l-1] ) * np.sqrt(2/n[l-1])
梯度检验
检验梯度是否计算正确。
假设你的网络中含有下列参数,W[1]和b[1] ……W[L]和b[L] ,为了执行梯度检验,首先要做的就是,把所有W矩阵转换成向量之后,做连接运算,得到一个巨型向量θ,代价函数J是所有W和b的函数,现在你得到了一个θ的代价函数J(即J(θ))。接着,你得到与W和b顺序相同的数据,你同样可以把dW[1]和db[1] ……dW[L]和db[L] 转换成一个新的向量,用它们来初始化大向量dθ,它与θ具有相同维度。
dθapprox [i]应该等于dθ[i],我们要做的就是验证这两个向量是否接近。可以通过计算两个向量间的距离(L2范数)来衡量
代码笔记
norm()
np.linalg.norm()用于求范数,linalg本意为linear(线性) + algebra(代数),norm则表示范数。
np.linalg.norm(x, ord=None, axis=None, keepdims=False)
1.x: 表示矩阵(一维数据也是可以的)
2.ord: 表示范数类型
ord | norm for matrices | norm for vectors |
---|---|---|
None | Frobenius norm(各个元素的平方和再开根) | 2-norm |
np.inf | max(sum(abs(x), axis=1)),计算每一行绝对值总和,然后返回最大的那个 | max(abs(x)),绝对值最大的 |
-np.inf | min(sum(abs(x), axis=1)) | min(abs(x) |
1 | max(sum(abs(x), axis=0)),计算每一列绝对值总和,然后返回最大的那个 | as below |
-1 | min(sum(abs(x), axis=0)) | as below |
2 | 2-norm (largest sing. value) | as below |
-2 | smallest singular value | as below |
other | – | sum(abs(x) ** ord)**(1./ord) |
3.axis
0:表示按列向量来进行处理,求多个列向量的范数
1:表示按行向量来进行处理,求多个行向量的范数
4.keepdims:表示是否保持矩阵的二维特性,True表示保持,False表示不保持,默认为False
copy()
np.copy()属于深拷贝,拷贝前的地址和拷贝后的地址不一样. 而 " = " 属于浅拷贝,拷贝后的地址和拷贝前的地址一样.