当前位置: 代码迷 >> 综合 >> 03-用神经网络实现MNIST分类-Dropout-正则化-优化器
  详细解决方案

03-用神经网络实现MNIST分类-Dropout-正则化-优化器

热度:19   发布时间:2023-12-14 09:47:13.0

一、单层感知机实现MNIST分类

import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import SGD#1、载入数据
(x_train,y_train),(x_test,y_test) = mnist.load_data()
#2、数据预处理
x_train.shape,y_train.shape  #((60000, 28, 28), (60000,))
#将x (60000, 28, 28) => (60000,784)
x_train = x_train.reshape(x_train.shape[0],-1) / 255.0  #x_train.shape[0]=60000
x_test = x_test.reshape(x_test.shape[0],-1) / 255.0
#将y 0-9 => one-hot 
# to_categorical:转换label格式的函数 num_classes:label的种类
y_train = np_utils.to_categorical(y_train,num_classes=10)
y_test = np_utils.to_categorical(y_test,num_classes=10)
#3、创建模型 输入784个神经元 输出10个神经元 
model = Sequential()
#bias_initializer:偏置值 默认0 softmax:将输出转为概率
model.add(Dense(input_dim=784,units=10,activation='softmax',bias_initializer='one'))
#自定义优化器
sgd = SGD(learning_rate=0.2)
#使用定义优化器(optimizer),loss,同时计算准确率 
#categorical_crossentropy(交叉熵):在做分类问题时,使用交叉熵收敛的速度会更快,收敛的效果也会更好
model.compile(optimizer=sgd,loss='categorical_crossentropy',metrics=['accuracy'])
#4、训练模型 这里采用fit函数训练模型
#batch_size:训练批次,每一训练32张图片 epochs:迭代周期 
#60000张图片 每次训练32张,训练完60000张为一个周期,总共训练10个周期
model.fit(x_train,y_train,batch_size=32,epochs=10)
#5、评估模型
loss,accuracy = model.evaluate(x_test,y_test)
print(loss,accuracy)  
#评估结果如下图

在这里插入图片描述

二、多层感知机+Dropout+正则化

Dropout
1、随机删除网络中的一些隐藏神经元,保持输入输出神经元不变;
2、将输入通过修改后的网络进行前向传播,然后将误差通过修改后的网络进行反向传播;
3、对于另外一批的训练样本,重复上述操作1.
正则化
l1 / l2

import numpy as np
from keras.datasets import mnist
from keras.layers import Dense,Dropout #Dropout防止过拟合
from keras.models import Sequential
from keras.optimizers import SGD
from keras.utils import np_utils
from keras.regularizers import l2 #导入l2正则化
(x_train,y_train),(x_test,y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0],-1) / 255.0
x_test = x_test.reshape(x_test.shape[0],-1) / 255.0
y_train = np_utils.to_categorical(y_train,num_classes=10)
y_test = np_utils.to_categorical(y_test,num_classes=10)
model = Sequential()
#正则化
#权值w加正则化:kernel_regularizer 偏置值b加正则化:bias_regularizer
#wx+b整体加正则化activity_regularizer 一般用w比较多 l2(正则化系数):0.0003
# model.add(Dense(input_dim=784,units=200,activation='tanh'))
model.add(Dense(input_dim=784,units=200,activation='tanh',kernel_regularizer=l2(0.0003)))
#Dropout
#随机地删除隐藏层的部分单元 参数(0.5):该层随机隐藏的神经元个数比率 一般是0.5/0.3
#model.add(Dropout(0.5))
# model.add(Dense(units=100,activation='tanh'))
model.add(Dense(units=100,activation='tanh',kernel_regularizer=l2(0.0003)))
#model.add(Dropout(0.5))
# model.add(Dense(units=10,activation='softmax'))
model.add(Dense(units=10,activation='softmax',kernel_regularizer=l2(0.0003)))
sgd = SGD(learning_rate=0.2)
model.compile(optimizer=sgd,loss='categorical_crossentropy',metrics=['accuracy'])
model.fit(x_train,y_train,batch_size=32,epochs=10)
loss,accuracy = model.evaluate(x_test,y_test)
print('test',loss,accuracy)
loss,accuracy = model.evaluate(x_train,y_train)
print('train',loss,accuracy) 
#执行效果如下图

在这里插入图片描述

可以看到,在增加模型复杂度(单层感知机->多层感知机)后,模型的泛化能力明显提升,但是训练集的正确率高达99.9%,明显存在过拟合现象,可以使用Dropout或者添加正则项来解决过拟合问题。
加Dropout后:
在这里插入图片描述
可以看出在添加了Dropout后,模型的泛化能力下降了,但是对于训练的过拟合现象是有抑制的,但这里还是不适合使用Dropout.
加正则化项后:
在这里插入图片描述
可以看出在添加了Dropout后,模型的泛化能力下降了,但是对于训练的过拟合现象是有抑制的,但这里还是不适合使用正则化项.

总结:具体要不要加Dropout/正则化项,要具体项目具体分析。遵循一个原则:如果训练集过拟合,且加了Dropout/正则化项后,测试集的正确率增加/不变,那就可以放心的添加Dropout/正则化项。

三、优化器

import numpy as np
from keras.datasets import mnist
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import SGD,Adam
from keras.utils import np_utils
(x_train,y_train),(x_test,y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0],-1) / 255.0
x_test = x_test.reshape(x_test.shape[0],-1) / 255.0
y_train = np_utils.to_categorical(y_train,num_classes=10)
y_test = np_utils.to_categorical(y_test,num_classes=10)
model = Sequential()
model.add(Dense(input_dim=784,units=10,activation='softmax'))
# sgd = SGD(learning_rate=0.2)
adma = Adam(learning_rate=0.01) #使用Adam优化器,学习率用默认的0.01比较多
model.compile(optimizer=adma,loss='categorical_crossentropy',metrics=['accuracy'])
model.fit(x_train,y_train,batch_size=32,epochs=10)
loss,accuracy = model.evaluate(x_test,y_test)
print(loss,accuracy)

优化器总结.
1、Batch Gradient Descent(BGD):全部样本梯度下降一次,训练样本很大时,单次迭代需要时间太长。
2、Stochastic Gradient Descent(SGD用的比较多)单个样本梯度下降一次,没有了向量化加速,效率比Batch Gradient Descent低,到达loss最低区域后还可能会跳出来,当然这也可以使它从局部最小值区域跳出来,可以使用学习率衰减来缓解这个问题。无法解决鞍点问题。准确率很高,但是训练速度慢。
3、Mini-batch Gradient Descent(MBGD):部分样本梯度下降一次,上两个方法的折中,它可能不会收敛也可能不会在很小的范围内波动(同样可以用学习率衰减的方法来缓解这个问题)。
4、Momentum(动量梯度下降法):基本的想法就是计算梯度的指数加权平均数,并利用它更新权重。相当于给普通的梯度下降加了个“惯性”,比如这次迭代算出来你需要向a方向优化,但你并不能直接将你的方向改成a,需要综合考虑之前的方向。
5、NAG: 计算的不是当前的梯度,而是下一步的梯度。
6、AdaGrad(自适应梯度算法):不需要人为的调节学习率,它可以自动的调节学习率。缺点:随着迭代次数的增多,学习率也会越来越小,最终趋近于0。
6、RMSprop:是AdaGrad算法的一种改进。不会出现学习率越来越低的问题,并且可以自动调整学习率,可以得到一个比较好的结果。
7、Adadelta: 也是AdaGrad算法的一种改进。不需要使用学习率,也可以得到一个比较好的结果。
8、Adam(用的比较多): 速度快,效果也好
总结:Adam和SGD用的最多。

  相关解决方案