深度学习编程入门(一):利用keras实现手写数字识别

903 阅读4分钟

part 1 写在前面

    这篇文章涉及到MLP还有softmax、RMSprop等等一些基础。

1、RMSprop的原理在这里:blog.csdn.net/bvl10101111…

2、多层感知器大概长这样:zhidao.baidu.com/question/16…

3、softmax的原理在这里:www.zhihu.com/question/23…


   本文中使用mnist数据集进行训练和测试,mnist是一个很出名的手写数字数据集,包含了60000个训练数据和10000个测试数据,该数据集下载地址和说明在这里:yann.lecun.com/exdb/mnist/

part2 确定目标&网络建立

前辈们说,如果要用神经网络解决问题,最好先尝试最简单的神经网络模型。

如果最简单的神经网络解决不了问题,再尝试使用更复杂的神经网络。

根据上述经验,我们先使用最简单的单层神经网络进行训练和预测:


1、引入数据集

path = './mnist.npz'
f = np.load(path)
x_train, y_train = f['x_train'], f['y_train']
x_test, y_test = f['x_test'], f['y_test']
f.close()


2、数据预处理

  将原来(n,28,28)的数据变成(n,784)的形式。

(28,28)是图片的长宽,n为训练or测试集的数据量

x_train = x_train.reshape(60000, 784).astype('float32')
x_test = x_test.reshape(10000, 784).astype('float32')
#将28X28的二维数据转成 一维数据
x_train /= 255
x_test /= 255


3、确定我们使用的模型

    根据"先简单后复杂"的尝试原则,我们先使用单隐藏层的神经网络进行训练,模型大概这样:


输入层→单隐藏层(relu)→softmax层


model = Sequential()
model.add(Dense(64, activation='relu', input_dim=784))
model.add(Dense(10, activation='softmax'))

    

    4、确定损失函数,优化方法


#确定学习率等等参数,在此我只调整了学习率,其他参数是copy API的
rms = keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=1e-06)
#确定损失函数,优化器
model.compile(loss='categorical_crossentropy',
              optimizer=rms,
              metrics=['accuracy'])
#载入训练数据,设置mini-batch的值,训练波数
model.fit(x_train, y_train,
          epochs=10,
          batch_size=128)

5、查看准确率


score = model.evaluate(x_test, y_test, batch_size=128) #查看测试值准确度
print(score)


6、运行,该模型准确率为97%左右



part2 调整超参数


    我们知道人在辨认手写数字时是很难出错的,所以97%的准确率显然不尽如人意,因此开始调参。

model.add(Dense(300, activation='relu', input_dim=784))


将单隐藏层的神经元数目增加到300个之后,正确率达到了98%,由于po主要去洗澡了,所以就不继续往下调参数了。

神经元增加之后,正确率上升,个人感觉是之前的神经网络神经元太少,欠拟合了,但事实上,当隐藏层神经元达到300的时候,虽然正确率上升了,但这个网络是处于过拟合状态的(因为训练数据的识别正确率为99.9%,但测试数据的识别正确率只有98%),再增加神经元个数已经失去了意义。


鉴于之前的模型过拟合了,参考了相关论文,我将隐藏层的300个神经元减为150个神经元,并增加了一层100个神经元的隐藏层:


model.add(Dense(150, activation='relu', input_dim=784))
model.add(Dense(100, activation='relu'))
model.add(Dense(10, activation='softmax'))

经过以上修改后,过拟合现象基本消失了,但是识别率依然不尽如人意,在感到调整其他参数作用不大的情况下,我选择改变损失函数的类型,将损失函数换为log损失函数。


log损失函数的参考资料在这里:

https://www.zhihu.com/question/27126057


更换了损失函数之后,识别率上升至99.57%

更换了损失函数后为何识别率大幅上升呢?个人认为是因为之前的损失函数即使收敛到最小值,也只是一个“相对”的最优解,更换损失函数后,得到的值是一个近似的最优解了。



part3 总结


 神经网络真好玩但是好难学,学了好久也才勉强入门,要多多写代码研究多多学习才能进步呀,如果本文有错欢迎指正,毕竟写这文章的人也是个菜鸡╮(╯▽╰)╭

还有就是调参如同炼丹一般,非常玄学