Keras(2):使用Keras构建神经网络进行Mnist手写字体分类,并定性分析各种超参数的影响



实 验 报 告

0BaseNet(三层、sigmoid784-386-10 1

1Hidden_Net784-112-10784-543-10 2

2reluActivation_Net 3

3DeepNet(四层、五层) 4

4DeepNet(四层、五层;训练轮数增加) 5

5DeepNet(五层;Dropout) 6

7DeepNet(五层;Dropout+relu) 8

8AutoEncoder_Net(五层AutoEncoder) 9

9、结论 10

 

 

摘要:本次试验的数据集为MNIST digits,使用keras构建了各式各样的网络,完成了手写数字识别,实验结果比较理想。除此之外,我们还比较了不同模型之间的差别,定性或定量的分析了各种超参数(结点个数、激活函数、隐含层个数、训练轮数等)、是否采用dropout策略、是否有预训练(使用AutoEncoder)等细节选择对实验结果的影响,通过这种定性或定量的深入分析,让我们对神经网络有了更清晰的认识,对不同情境下神经网络的选择也有了更深入的理解。

 

 

0BaseNet(三层、sigmoid784-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])

Trainingevaluation的结果如下:

 

Loss=0.128940589167acc=0.962099999189

 

这个结果作为baseline,不做分析。

1Hidden_Net784-112-10784-543-10

结构和上面一样,不过隐藏层节点数改为112

Trainingevaluation的结果如下:

 

Loss=0.0937348691374acc=0.970400002003

 

结构和上面一样,不过隐藏层节点数改为543

Trainingevaluation的结果如下:

 

Loss=1.6589958334acc=0.869799996614

 

通过对比试验01,我们发现:隐藏层节点数较少时,效果较好;隐藏层节点数较多时,效果相对较差

 

 

2reluActivation_Net

结构和上面一样,不过激活函数改为relu

Trainingevaluation的结果如下:

 

Loss=0.0602644333878acc=0.980100008249

 

通过对比试验02,我们发现:激活函数改为relu比使用sigmoid效果更好,loss更小,acc更大(提高了0.02,已经非常不错了!);实际上reluRectified Linear Units)激活函数已经被证明,在大多数情况下要好于sigmoid函数。

 

3DeepNet(四层、五层)

四层,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

Trainingevaluation的结果如下:

 

Loss=0.132126849946acc=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

Trainingevaluation的结果如下:

 

Loss=0.142769166548acc=0.955300002098

 

通过对比试验03以及实验3本身的两个子实验,我们发现:层数越多反而效果越差;仔细分析发现可能的原因是“层数较多的情况下需要经过较长次数的训练,否则网络不容易达到最优”,这个结论从val_acc一直在增加也可以证明,至少网络当前处于underfitting的状态!

为了验证这个猜想,我们做了如下实验:将nb_epoch=10改为nb_epoch=20

 

4DeepNet(四层、五层;训练轮数增加)

四层,将nb_epoch=10改为nb_epoch=20Trainingevaluation的结果如下:

 

Loss=0.0860328582302acc=0.973700002432

 

五层,将nb_epoch=10改为nb_epoch=20Trainingevaluation的结果如下:

 

Loss=0.079075542494acc=0.976300004721

 

通过对比试验34以及实验3本身的两个子实验和实验4本身的两个子实验,我们发现:随着训练轮数的增多,效果越来越好,这说明我们前面的分析是正确的!这也告诉我们,如果网络比较深,应该多训练几轮以使网络得到充分训练。

 

5DeepNet(五层;Dropout)

sigmoid激活函数,网络结构784-543-386-112-10使用随机Dropoutnb_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

Trainingevaluation的结果如下:

 

Loss=0.098954036464acc=0.970100002289

 

通过对比试验45,我们发现:当网络的某一层的节点数比较少的时候采取dropout策略反而容易引起网络性能的下降!这可能因为比较少的节点难以捕获数据内在关系有关。为了解决上面的问题,我们猜测需要进一步加大训练轮数才可以,所以进行了下面的试验。

 

 

6、DeepNet(五层;Dropout+nb_epoch=30)

 

sigmoid激活函数,网络结构784-543-386-112-10使用随机Dropoutnb_epoch=30

Trainingevaluation的结果如下:

 

Loss=0.0791375797056acc=0.975700001717

 

通过对比试验456,我们发现:在采取dropout策略时适当增大训练轮数也能在一定程度上提高网络性能。

 

7DeepNet(五层;Dropout+relu)

relu激活函数,网络结构784-543-386-112-10使用随机Dropoutnb_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

Trainingevaluation的结果如下:

 

Loss=0.0797024395682acc=0.983800008297

 

通过对比试验4567,我们发现:relu激活函数的性能非常好,即便是在采取dropout策略时保持训练轮数不变,也能在一定程度上提高网络性能;这也验证了试验2的结论。

 

8AutoEncoder_Net(五层AutoEncoder

网络结构784-543-386-112-10nb_epoch=30sigmoid激活函数,关键代码如下:

#*************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)

 

Trainingevaluation的结果如下:

 

Loss=0.0799347099484acc=0.976900002956

 

通过对比试验48,我们发现:使用AutoEncoder进行预训练,能在一定程度上提高网络性能。另外,训练的时间也大大缩短(大约缩短1/3的时间)!

 

9、结论

通过实验0到实验8的对比分析,我们主要得到以下结论:

1)结点个数:最后一个隐藏层结点个数越接近输出层的结点个数,效果相对越好。

2)激活函数:relusigmoid等效果普遍较好;该结论也被其他实验证明。

3)隐含层个数:如果保持训练轮数不变,那么隐含层个数越多,效果相对越差;但如果同时增大训练轮数,那么效果就会相对较好。

4)训练轮数:增大训练轮数在一定程度上能够提高网络性能;尤其是在增大隐含层个数的情况下,增加训练轮数非常有必要。

5)Dropout策略:在网络的结点个数相对较少时,采用dropout策略会降低网络性能;在网络的结点个数相对较多时,采用dropout策略则会在一定程度上提升网络性能。

6)预训练:使用AutoEncoder进行预训练,能在一定程度上提高网络性能;另外,训练的时间也大大缩短(大约缩短1/3的时间)!




你可能感兴趣的:(Theano,AND,Keras)