20180108
MLP(多层感知器)是最简单的神经网络,MNIST是一个经典的数据集,包括6万条训练数据和1万条测试数据,用于识别手写数字0到9,网址在:http://yann.lecun.com/exdb/mnist/
我们本节的目的就是使用CNTK C# MLP实现MNIST数据训练和识别,例子与上一节相同,就是CNTK的Example目录中的CsharpTrain程序。
1、准备训练文件和测试文件
准备过程很简单,找到Example目录中的Mnist目录,我的是C:\cntk23\Examples\Image\DataSets\MNIST,其下有install_mnist.py文件,命令行运行它就行了,
python install_mnist.py
如果出现如下错误,别忘了上一节的提醒,要先运行Scripts目录下的cntkpy35.bat程序设置python的cntk环境变量
Traceback (most recent call last): File "install_mnist.py", line 3, inimport mnist_utils as ut File "C:\cntk23\Examples\Image\DataSets\MNIST\mnist_utils.py", line 11, in import numpy as np
ModuleNotFoundError: No module named 'numpy'
运行后会生成两个新文件:Train-28x28_cntk_text.txt和Test-28x28_cntk_text.txt,一个是训练文件,一个是测试文件,内容格式都一样,如下:
|labels 0 0 0 0 0 0 0 1 0 0 |features 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 84 185 159
。。。。。。
151 60 36 0 0 0 0 0 0 222 254 254 254 254 241 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|labels 0 0 1 0 0 0 0 0 0 0 |features 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
。。。。。。
对数据文件不熟悉的,和对CNTK神经网络不熟悉的,可以先看看这篇文章,写的非常好很适合入门
2、CNTK C#神经网络创建
如果不知道CsharpTrain这个项目的,参见上一节,本节是对该项目中有关MLP的部分进行分析。
对于例子使用来说,其他的都不重要,直接照抄现成的就行,下面分析神经网络建立部分以及一些重要参数
1)创建神经网络
如下创建一个单隐层的MLP网络,第一行的意思就是说,以输入层网络函数(scaledInput)为上一层,建立包括本层(100个节点,使用Sigmoid激活函数)在内的一个新的网络函数(dense1 ),命名为空(""),device表示是使用CPU还是GPU,也就是说,dense1这个新的网络包括旧的网络(只包含输入层)和本层网络(隐藏层)。
第二行的意思就是建立一个新的网络,包括dense1和本层(输出层)。
两行加起来就是建立一个包括输入层、单隐层、输出层共三层的一个MLP网络。
Function dense1 = TestHelper.Dense(scaledInput, 100, device, Activation.Sigmoid, "");
Function classifierOutput = TestHelper.Dense(dense1, numClasses, device, Activation.None, classifierName);
如下创建一个双隐层的网络,第一个隐层包括100个节点,第二个隐层包括66个节点。
Function dense1 = TestHelper.Dense(scaledInput, 100, device, Activation.Sigmoid, "");
Function dense2 = TestHelper.Dense(dense1, 66, device, Activation.ReLU, "");
Function classifierOutput = TestHelper.Dense(dense2, numClasses, device, Activation.None, classifierName);
对上面两段进行对比就很容易明白是怎么回事了。
2)影响MLP模型识别率的重要参数
a、隐层层数
b、隐层节点数
c、激活函数
d、分组大小(minibatchSize)
单个样本之间差别较大,而两组平均之间差别就小,所以使用分组对模型参数改变就会小。用于随机梯度下降(SGD)的loss评估中。
e、重复训练次数(epochs)
f、学习率(learningRatePerSample)
3、实验及结论
实验1
单隐层(200节点)、激活Sigmoid、epochs=5、minibatchsize=64、learningRatePerSample=0.003125、正确率为94.19%
实验2
单隐层(100节点)、激活ReLu、epochs=20、minibatchsize=128、learningRatePerSample=0.003125、正确率为97.33%
还进行了其他许多单项测试,结论如下,对于MLP网络:
1)增加循环次数会提高正确率,例如5次改为10次会增加1个多点(以下均指百分点)
2)增加隐层节点不会提高正确率,例如100改为200
3)增加隐层层数不会提高正确率,实验了一层、两层、三层
4)增加minibatchsize,会提高正确率,例如32改为64会提高0.3个点
5)激活函数和学习率
ReLu对学习率很敏感,例如learningRatePerSample=0.003时很好,learningRatePerSample=0.03时很差,正确率会下降几十个点;
Sigmoid对学习率不太敏感,0.03和0.003时只相差一两个点。
下节我们用CNN训练MNIST,看看有何不同。