最初实现BP神经网络的时候,我只是简单地用梯度检验法检验了一下,验证自己的求导计算应该是没有问题的。
采用的是标准minist手写数字数据集,就是60000个训练样本和10000个测试样本那个。真的上实际数据测试,一跑,正确率居然只有10%左右!而我在读的Michael A. Nielsen的教程中,他通过Python构建的那个简单的网络,只运行一个世代就有90%以上的正确率,这个结果让我一度十分沮丧。如果我写一个简单的程序,每次都猜这个数字是0,正确率大概也会是10%吧。这真的是个很悲惨的正确率,否定了我的全部劳动成果!
那个时候我对“超参”这个概念还没有特别深入的体会,因为是自己造的轮子,我首先依然是从bug检查,首先发现的问题是,W2矩阵,也就是第一层隐藏层前的权重矩阵内的值居然都近乎为0,我想起看过但还没开始学习的概念“导数消失”。当时我的理解是,如果输入层到第一个隐藏层的权重几乎都是0,这不就意味着输入对最终结果的影响不大吗?
0.1.标准化(normalization)
我第一个想到的点是输入的取值范围为0~255,但事实上网络接受的值最好还是0~1之间或者-1到+1之间的吧?如果你采用的是随机(-1~+1)初始化参数,所以假如你不做标准化,这部分的运算就会纳入参数迭代的过程中,通过梯度更新的方式来迭代变化。我做出的第一个改变是对输入作了标准化,特征值载入前将其除以255,使得特征值的取值范围在0~1之间。
然而,结果并没有太大的改变。不过这样的尝试还是在我心中构建了一个标准化的概念,同时还让我产生了这样的思考,认为之所以图像识别用计算机来处理这么方便,其实就是因为图像很容易描述成一串量纲等价的向量。目前成熟的机器学习形式最认可的输入也正是这种天然就具有标准、独立、量纲等价的向量。
0.2.世代(epoch)
即样本集遍历次数。显然,世代与运行时间呈线性关系。
这个概念是吴恩达的机器学习视频课里没有提及的。他讲mini-batch的时候,并没有说世代。以至于我最开始的学习一直都是以“世代=1”的方式进行的,