声明:
对于上述情况,或者另一种垃圾输出的情况——预测值只是所有标签的平均值,再或者更差的情况,模型准确率非常低…我们应该从什么地方开始检查模型呢?
网络训练效果差,问题可能出在很多很多地方,但有些地方出问题的概率较大。所以,通常我会从以下几点开始:
保证你提供给网络的输入数据是有意义的。比如:我有时候弄混了图片的高和宽;或者不小心用全零的数据来训练网络;或者一直使用了同一个batch来不停的迭代训练。所以,你应该打印一组(输入,输出)并确保它们没有问题。
如果网络对随机输入的预测结果跟之前真实数据的预测结果差不多,那多半是网络某一层除了问题。这时,你需要一层一层的debug自己的网络。
可能你的数据集没有问题,但是在数据的读取和预处理中除了问题,所以要检查网络第一层的输入。
也就是说,训练集中的输入不能(或者尽可能少的)有错误的标定。同时记得在打乱数据集的时候,输入和输出的打乱方式相同。
用机器学习里的术语来说就是, y = f ( x ) y=f(x) y=f(x)中 f f f的假设空间(模型空间)太大了。
比如说股票数据,想学习这个太难了。因为股票的随机性太大了,虽然通过数据获得的股票走势有一定的参考意义,但因为随机性大于数据内部的规律,光凭数据很难做出正确的预测。
数据集不是完美的,比如对于MNIST手写数字识别数据集来说,可能有50%的样本时正确的可以学习的,而另外的50%的样本乱标定的噪声,那么这些乱标定的噪声会干扰网络的学习,应该实现被剔除。
当用网上爬来的数据进行机器学习或深度学习的时候,很容易出现这种问题。
不打乱数据集的话,会导致网络在学习过程中的偏向问题。
对于类别不平衡的分类问题,常规武器有:过采样、欠采样(不太好用)、调整损失函数等。
小样本学习时深度学习应用的一个重要问题。常规武器有迁移学习和生成网络(如GAN、VAE)法。如果是因为训练数据不足造成的网络学习效果不好,那将需要很大的精力来解决这个问题。
如果一个训练批次中只有一类的样本,网络将很难收敛到最优。一般来说只要随机打乱的训练集就不会出现这个问题。再保险一点可以将batch_size搞大一点,比如128,但不要太大。
我在实验中,就经常会出现用同一数据集和网络得到的准确率忽高忽低,比如70%-90%。所以,时间允许的话,建议每次实验过程中多训练几次。
(・◇・)?上面刚说batch size可以搞大一点,这里又要调小???
研究表明:太大的batch size会降低模型的泛化能力。详见论文——戳我跳转
当使用一种新型的网络结构式,应该先用经典数据集测试一下,而不是直接应用于自己的真实数据。因为这些经典数据集都有参考标准(baseline,或者说是准确率的最低要求),而且没有数据方面的问题(如噪声、不平衡、随机性过大导致难以学习的问题等等)
记得以下二选一:
正则化可以防止模型过拟合,但过量的正则化会导致欠拟合。
预处理的方式要跟你加载的预训练的网络一致,比如图片像素的大小是[0, 1], [-1, 1]还是[0, 255]?
引用斯坦福课程CS231n:
… any preprocessing statistics (e.g. the data mean) must only be computed on the training data, and then applied to the validation/test data. E.g. computing the mean and subtracting it from every image across the entire dataset and then splitting the data into train/val/test splits would be a mistake.
在数据预处理时,一些预处理需要的统计参数(如均值、标准差等)必须先从训练集中获得,再应用到验证集和测试集中。谨慎检查这一点,避免数据预处理中的错误。
比如说,如果目标输出是object class and coordinates
, 先试一下解决object class
。
引用斯坦福课程CS231n:
Initialize with small parameters, without regularization. For example, if we have 10 classes, at chance means we will get the correct class 10% of the time, and the Softmax loss is the negative log probability of the correct class so: -ln(0.1) = 2.302.
损失函数一般包括两部分:误分类的惩罚项和正则化项。我们应该先根据问题选择合适的惩罚项,然后在尝试正则化项
如果你自定义了损失函数,一定要检查它,还要进行单元测试。因为自定义的损失函数经常会有细小的错误,导致网络出现学习问题,而且这通常很难发现。
使用神经网络框架中的损失函数时,一定要注意损失函数的输入。比如,在PyTorch中,我经常会弄混NLLLoss
和CrossENtropyLoss
,前者的输入是一个softmax
输入(即在0到1之间),而后者不是。
如果你的损失函数由多个子损失加权而成,那就要注意它们的关联关系和权重。
有时候,损失函数的值并不是评价网络训练好坏的最好方式。如果可以的话,可以使用其他的评价标准,如准确率。
如果网络中有你自定义的网络层,多检查几遍…
可能你无意间关闭了某些层的权重更新。
有时候网络训练效果不好是因为网络的容量太小,增加全连接层数或隐藏层神经元数目。
如果你的输入数据维度(k, H, W) = (64, 64, 64),那确实很容易在维度上弄混。如果不放心维度上的问题,可义用几个容易分辨的数值试一下,检查一下它们在各个网络层中传递时的变化。不过这里一般不会出问题。
如果反向传递的求导是你自己算的,确实需要反复检查。
从当前数据集中选择极其少量的数据,用自己的网络模型过拟合这些数据,确定网络没有问题。
例如,先用2个样本训练,观察你的网络能否学到这两个样本之间的不同,然后逐步扩展到更多数据。
保险起见,可以使用Xavier
或He
初始化。有时候,不好的初始化确实会是网络的学习陷入一个局部最优解,所以也可以试一下其他的初始化方法,看看是否有用。
超参数的最优值可以通过经验或多次实验获得。如果时间允许的话,还可以通过交叉验证选择最优超参数。
过多的正则化会导致网络欠拟合。Dropout
, batchnormalization
, L2正则化作为正则化手段,当网络欠拟合时候应该先去掉这些方法。
可能你的网络需要更多的迭代次数才能获得有意义的预测。如果网络的损失函数值还在下降,务必让它继续迭代下去;如果网络的损失函数不再下降,也应该继续观察几轮确保训练没有卡在局部最小点。
有些网络层如BatchNormalization
和Dropout
层在训练模式和测试模式下是不一样的。
For weights, these histograms should have an approximately Gaussian (normal) distribution, after some time. For biases, these histograms will generally start at 0, and will usually end up being approximately Gaussian (One exception to this is for LSTM). Keep an eye out for parameters that are diverging to +/- infinity. Keep an eye out for biases that become very large. This can sometimes occur in the output layer for classification if the distribution of classes is very imbalanced
一般来说优化器的选择不会导致网络训练的结果太差,除非你选择的优化器超参数太糟了。当然,合适的优化器可以是网络训练的更快。常用的优化器有Adam
,SGD
, RMSprop
。
梯度爆炸和梯度弥散产生的根本原因是深度学习中多层梯度累积。如1.1的n次方无穷大,0.9的n次方无穷小。
学习率决定了网络训练的速度,但学习率不是越大越好,当网络趋近于收敛时应该选择较小的学习率来保证找到更好的最优点。
一般学习率的调整是乘以/除以10的倍数。
首先训练集中不能有空值!!其次,网络训练过程中也不能出现空值,几点建议:
assert