神经网络学习_实验

经过数学公式的洗礼,是时候上手看看我们的代码效果如何了。

数据集

MNIST,下载地址:http://yann.lecun.com/exdb/mnist/

小数据集

  • mnist_train_100.csv:100个训练数据
  • mnist_test_10.csv:10个测试数据

完整数据集

  • mnist_train.csv:60000个训练数据
  • mnist_test.csv:10000个测试数据

实验代码

首先我们设定常量参数 input_nodesoutput_nodes。输入神经元数量受到数据格式的限制,由于数据集中每条记录都是一张 28x28 的灰度图,因此输入每个像素的灰度值需要 784 个神经元。而神经网络输出的格式更灵活,不过这里我们设定为 10 个神经元,分别代表阿拉伯数字 0~9。

还可以使用 5 个神经元输出,用来代表 0~9 的二进制位。不过这样的话,1层隐藏层足够吗?

可变参数就是隐藏层神经元个数学习率训练世代数

训练世代数,指对于一个数据集,重复多次地进行训练。值得注意的是,我们使用的梯度下降法只走了一步,也就是在下山过程中,朝着最陡峭的方向走了有限的一步,这当然几乎不能达到极小值点。因此我们多训练几个世代,让它有更多的机会向下走,一定程度上有助于收敛。

if __name__ == "__main__":
    ###################### 训练 ####################
    # 输入数据为 28x28 的灰度图,共 784 个灰度数据(0 ~ 255)
    input_nodes = 784
    # 输出层数为 10 (Question)
    output_nodes = 10
​
    ########## 参数修改 ##########
    # 改变中间层层数
    hidden_nodes = 50
    # 改变学习率
    learning_rate = 0.08
    # 改变训练世代数
    epochs = 5
    ########## 参数修改 ##########
​
    n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
    
    # 100 个数据,用于快速得到结果,测试、修改代码
    # training_data_file = open("./mnist_train_100.csv", 'r')
    # 全部训练数据
    training_data_file = open("./mnist_train.csv", 'r')
    # 逐行读取数据
    training_data_list = training_data_file.readlines()
    training_data_file.close()
    
    for e in range(epochs):
        for record in training_data_list:
            all_values = record.split(',')
            # 将灰度值转为 0.01 ~ 0.99 (Question)
            inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
            # 构造正确的标签
            Label = np.zeros(output_nodes) + 0.01
            Label[int(all_values[0])] = 0.99
            # 开始对该样本进行训练
            n.train(inputs, Label)

Learning Rate

实验数据

No.Hidden NodesLearning RateepochsScore
150.0150.4836
250.0550.6688
350.0850.8011
450.150.7691
550.250.7557
650.350.6935
750.450.6076
850.550.5803
Learning Rate

随着学习率的增大,模型的表现先升高再降低,峰值出现在 之间。过高和过低的学习率都会造成模型的正确率下降,可以从 神经网络学习_反向传播与梯度下降(1)一文中得到解释。

Hidden_Nodes

实验数据

No.Hidden NodesLearning RateepochsScore
150.150.7691
2100.150.8905
3500.150.9582
41000.150.9666
52000.150.9739
63000.150.9741
75000.150.9747
Hidden Nodes

随着隐藏层节点数量的增多,模型的正确率越来越好,正确率上升的速度逐渐减慢。若将权重矩阵视作模型储存的知识,那么10个结点能储存的知识显然比100个结点储存的知识要少。但是训练时隐藏层结点数量越多,计算起来越慢,且正确率的提升效果越差。

Epochs

实验数据

No.Hidden NodesLearning RateepochsScore
1100.110.8664
2100.130.8781
3100.150.8905
4100.170.8872
5100.1100.9003
6100.1150.9084
7100.1200.9014
8100.1250.9011
9100.1300.8962
Epochs

由于对每一个样本进行训练时,梯度下降法只走一步,因此多轮训练能够给予更多的梯度下降的机会。但是过高或过低的训练世代数都会使得模型表现差,这是因为训练少了难以下降到局部最优,训练多了模型会学习过多的训练样本的特征,对于没有训练过的样本的表现不好。

注意

由于权重矩阵初始值是随机得到的的,因此每次对于同样的样本训练,得到的正确率也不一定相同。另外笔者发现,当隐藏层节点数量较少时(例如5个),同样的样本和参数进行训练,得到的正确率极差较大。

横向对比

使用如下参数训练模型:

  • Hidden_Nodes = 200
  • epochs = 5;
  • Learning_Rate = 0.09

模型在测试集上的正确率为 0.9760

THE MNIST DATABASEof handwritten digits 上的记录进行对比,在 Neutral Nets 一栏也可以排在中等偏上水平。并且此次训练只使用了2层神经网络(输入层未计入)和200个隐藏层节点,训练了5个世代。

上图左起第3列均为错误率(%)

     

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

购物车
There are no products in the cart!
Subtotal
¥0.00
Total
¥0.00
Continue Shopping
0