Keras(2):使用Keras构建神经网络进行Mnist手写字体分类,并定性分析各种超参数的影响
来源:互联网 发布:文艺知乎 编辑:程序博客网 时间:2024/05/22 04:29
实 验 报 告
0、BaseNet(三层、sigmoid、784-386-10) 1
1、Hidden_Net(784-112-10和784-543-10) 2
2、reluActivation_Net 3
3、DeepNet(四层、五层) 4
4、DeepNet(四层、五层;训练轮数增加) 5
5、DeepNet(五层;Dropout) 6
7、DeepNet(五层;Dropout+relu) 8
8、AutoEncoder_Net(五层;AutoEncoder) 9
9、结论 10
摘要:本次试验的数据集为MNIST digits,使用keras构建了各式各样的网络,完成了手写数字识别,实验结果比较理想。除此之外,我们还比较了不同模型之间的差别,定性或定量的分析了各种超参数(结点个数、激活函数、隐含层个数、训练轮数等)、是否采用dropout策略、是否有预训练(使用AutoEncoder)等细节选择对实验结果的影响,通过这种定性或定量的深入分析,让我们对神经网络有了更清晰的认识,对不同情境下神经网络的选择也有了更深入的理解。
0、BaseNet(三层、sigmoid、784-386-10)
三层结构、激活函数为常见的sigmoid,网络结构784-386-10,代码如下:
#*************build your model
model=Sequential()
model.add( Dense( 386, input_dim=784, init='uniform' ) )
model.add(Activation('sigmoid'))
model.add(Dense(10, activation='softmax')) #'softmax' for multi-calss
#*************compile your model
sgd=SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, class_mode=None, sample_weight_mode=None)
#*************train your model
#Returns a history object.
#Its history attribute is a record of training loss values at successive epochs,
#as well as validation loss values (if applicable).
model.fit(X=Xtrain, y=ytrain,
nb_epoch=10, batch_size=200,
verbose=1, callbacks=[],
validation_split=0.0, validation_data=(XCV, yCV),
shuffle=True, show_accuracy=True,
class_weight=None, sample_weight=None)
#*************evaluate your model
score=model.evaluate(X=Xtest, y=ytest, batch_size=200, show_accuracy=True, verbose=1, sample_weight=None)
print "loss="+str(score[0])+" acc="+str(score[1])
Training和evaluation的结果如下:
Loss=0.128940589167;acc=0.962099999189
这个结果作为baseline,不做分析。
1、Hidden_Net(784-112-10和784-543-10)
结构和上面一样,不过隐藏层节点数改为112。
Training和evaluation的结果如下:
Loss=0.0937348691374;acc=0.970400002003
结构和上面一样,不过隐藏层节点数改为543。
Training和evaluation的结果如下:
Loss=1.6589958334;acc=0.869799996614
通过对比试验0和1,我们发现:隐藏层节点数较少时,效果较好;隐藏层节点数较多时,效果相对较差。
2、reluActivation_Net
结构和上面一样,不过激活函数改为relu。
Training和evaluation的结果如下:
Loss=0.0602644333878;acc=0.980100008249
通过对比试验0和2,我们发现:激活函数改为relu比使用sigmoid效果更好,loss更小,acc更大(提高了0.02,已经非常不错了!);实际上relu(Rectified Linear Units)激活函数已经被证明,在大多数情况下要好于sigmoid函数。
3、DeepNet(四层、五层)
四层,sigmoid激活函数,网络结构784-426-246-10,代码如下:
model=Sequential()
model.add( Dense( 426, input_dim=784, init='uniform' ) )
model.add(Activation('sigmoid'))
model.add(Dense(246, activation='sigmoid'))
model.add(Dense(10, activation='softmax')) #'softmax' for multi-calss
Training和evaluation的结果如下:
Loss=0.132126849946;acc=0.960399998426
五层,sigmoid激活函数,网络结构784-543-386-112-10,代码如下:
model=Sequential()
model.add( Dense( 543, input_dim=784, init='uniform' ) )
model.add(Activation('sigmoid'))
model.add(Dense(386, activation='sigmoid'))
model.add(Dense(112, activation='sigmoid'))
model.add(Dense(10, activation='softmax')) #'softmax' for multi-calss
Training和evaluation的结果如下:
Loss=0.142769166548;acc=0.955300002098
通过对比试验0和3以及实验3本身的两个子实验,我们发现:层数越多反而效果越差;仔细分析发现可能的原因是“层数较多的情况下需要经过较长次数的训练,否则网络不容易达到最优”,这个结论从val_acc一直在增加也可以证明,至少网络当前处于underfitting的状态!
为了验证这个猜想,我们做了如下实验:将nb_epoch=10改为nb_epoch=20。
4、DeepNet(四层、五层;训练轮数增加)
四层,将nb_epoch=10改为nb_epoch=20,Training和evaluation的结果如下:
Loss=0.0860328582302;acc=0.973700002432
五层,将nb_epoch=10改为nb_epoch=20,Training和evaluation的结果如下:
Loss=0.079075542494;acc=0.976300004721
通过对比试验3、4以及实验3本身的两个子实验和实验4本身的两个子实验,我们发现:随着训练轮数的增多,效果越来越好,这说明我们前面的分析是正确的!这也告诉我们,如果网络比较深,应该多训练几轮以使网络得到充分训练。
5、DeepNet(五层;Dropout)
sigmoid激活函数,网络结构784-543-386-112-10,使用随机Dropout,nb_epoch=20,代码如下:
#*************build your model
model=Sequential()
model.add( Dense( 543, input_dim=784, init='uniform' ) )
model.add(Activation('sigmoid'))
model.add(Dropout(0.05))
model.add(Dense(386, activation='sigmoid'))
model.add(Dropout(0.05))
model.add(Dense(112, activation='sigmoid'))
model.add(Dropout(0.05))
model.add(Dense(10, activation='softmax')) #'softmax' for multi-calss
Training和evaluation的结果如下:
Loss=0.098954036464;acc=0.970100002289
通过对比试验4和5,我们发现:当网络的某一层的节点数比较少的时候采取dropout策略反而容易引起网络性能的下降!这可能因为比较少的节点难以捕获数据内在关系有关。为了解决上面的问题,我们猜测需要进一步加大训练轮数才可以,所以进行了下面的试验。
6、DeepNet(五层;Dropout+nb_epoch=30)
sigmoid激活函数,网络结构784-543-386-112-10,使用随机Dropout,nb_epoch=30:
Training和evaluation的结果如下:
Loss=0.0791375797056;acc=0.975700001717
通过对比试验4、5和6,我们发现:在采取dropout策略时适当增大训练轮数也能在一定程度上提高网络性能。
7、DeepNet(五层;Dropout+relu)
relu激活函数,网络结构784-543-386-112-10,使用随机Dropout,nb_epoch=20,代码如下:
#*************build your model
model=Sequential()
model.add( Dense( 543, input_dim=784, init='uniform' ) )
model.add(Activation('relu'))
model.add(Dropout(0.05))
model.add(Dense(386, activation='relu'))
model.add(Dropout(0.05))
model.add(Dense(112, activation='relu'))
model.add(Dropout(0.05))
model.add(Dense(10, activation='softmax')) #'softmax' for multi-calss
Training和evaluation的结果如下:
Loss=0.0797024395682;acc=0.983800008297
通过对比试验4、5、6和7,我们发现:relu激活函数的性能非常好,即便是在采取dropout策略时保持训练轮数不变,也能在一定程度上提高网络性能;这也验证了试验2的结论。
8、AutoEncoder_Net(五层;AutoEncoder)
网络结构784-543-386-112-10,nb_epoch=30,sigmoid激活函数,关键代码如下:
#*************add the softmax layer to create the DEEP(AutoEncoder) neural network
#*************and fine turning the DEEP(AutoEncoder) neural network
model=Sequential()
model.add(autoencoder1.encoder)
model.add(autoencoder2.encoder)
model.add(autoencoder3.encoder)
model.add(Dense(input_dim=112, output_dim=10, activation='softmax'))
sgd=SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, class_mode=None, sample_weight_mode=None)
#model.fit(X=Xtrain, y=ytrain, nb_epoch=10) #note: y=Xtrain
model.fit(X=Xtrain, y=ytrain,
nb_epoch=30, batch_size=200,
verbose=1, callbacks=[],
validation_split=0.0, validation_data=(XCV, yCV),
shuffle=True, show_accuracy=True,
class_weight=None, sample_weight=None)
Training和evaluation的结果如下:
Loss=0.0799347099484;acc=0.976900002956
通过对比试验4和8,我们发现:使用AutoEncoder进行预训练,能在一定程度上提高网络性能。另外,训练的时间也大大缩短(大约缩短1/3的时间)!
9、结论
通过实验0到实验8的对比分析,我们主要得到以下结论:
1)结点个数:最后一个隐藏层结点个数越接近输出层的结点个数,效果相对越好。
2)激活函数:relu比sigmoid等效果普遍较好;该结论也被其他实验证明。
3)隐含层个数:如果保持训练轮数不变,那么隐含层个数越多,效果相对越差;但如果同时增大训练轮数,那么效果就会相对较好。
4)训练轮数:增大训练轮数在一定程度上能够提高网络性能;尤其是在增大隐含层个数的情况下,增加训练轮数非常有必要。
5)Dropout策略:在网络的结点个数相对较少时,采用dropout策略会降低网络性能;在网络的结点个数相对较多时,采用dropout策略则会在一定程度上提升网络性能。
6)预训练:使用AutoEncoder进行预训练,能在一定程度上提高网络性能;另外,训练的时间也大大缩短(大约缩短1/3的时间)!
- Keras(2):使用Keras构建神经网络进行Mnist手写字体分类,并定性分析各种超参数的影响
- 使用Keras构建神经网络进行Mnist手写字体分类
- [深度学习框架] Keras上使用神经网络进行mnist分类
- keras/构建卷积神经网络识别mnist
- Keras入门课2 -- 使用CNN识别mnist手写数字
- [深度学习框架] Keras上使用CNN进行mnist分类
- [深度学习框架] Keras上使用RNN进行mnist分类
- Keras-2 Keras Mnist
- keras:1)初体验-MLP神经网络实现MNIST手写识别
- CNN中使用SVM进行分类(keras的实现)
- 使用Keras进行图像分类
- 2.keras实现MNIST手写数字分类问题初次尝试(Python)
- 使用OpenCV自带的神经网络对MNIST手写字体进行识别
- Keras框架神经网络算法训练MNIST分类准确率(实验)
- keras入门 利用卷积神经网络进行手写数字识别
- 【Iris】【Keras】神经网络分类器和【scikit-learn】逻辑回归分类器的构建
- Keras 浅尝之MNIST手写数字识别
- 利用keras进行分类
- Jmeter Sampler (取样器插件开发) 制定自己的 Sampler
- js获取url的参数和值的N种有效方法
- luajit笔记---编译成静态库以及FFI绑定宿主程序函数
- Android 中this、 getApplicationContext()、getApplication()之间的区别
- VS2010 C++下编译调试MongoDB源码
- Keras(2):使用Keras构建神经网络进行Mnist手写字体分类,并定性分析各种超参数的影响
- MyEclipse下连接SVN资源库URL连接及验证错误解决办法
- CodeForces600B(二分查找)
- iOS Json转换模型库:YYModel
- @weakify, @strongify
- 关于智能指针
- 初级还是高级开发者,到底区别在哪里?
- 这个控件找不到的问题.报错瞎报..
- Linux下C++调用Java简单实例(jni)