DNN手写字体识别
1.使用框架
本篇主要使用的是paddlepaddle框架(百度公司提出的深度学习框架),在本次任务中则直接使用该框架,作为最简单的手写字体识别实现。
2.主要任务
将手写字体的灰度像素(28*28)分到0-9十个类别
3.模型组网
模型创建过程:
具体代码实现过程:
1.下载mnist数据集
import numpy as np
import paddle
import matplotlib.pyplot as plt
from paddle.vision.transforms import ToTensor
train_dataset=paddle.version.datasets.MNIST(mode='train',transform=ToTesnor())
print('数据集中的照片:{}'.format(len(train_dataset)))
print('测试集中的照片:{}'.format(len(test_dataset)))
2.查看数据
train_data0,train_label_0=train_dataset[0][0],train_dataset[0][1]
train_data0=train_data0.reshape([28,28])
plt.figure(figsize=(2,2))
print(plt.imshow(train_data0,cmap=plt.cm.binary))
#显示灰度图
print('train_data0的标签:'+str(train_label_0))
3.模型设计
mnist=paddle.nn.Sequential(
paddle.nn.Flatten(),
#Flatten为拉平,最开始为28*28的灰度图片,将其展开为784
paddle.nn.Linear(28*28,100),
#这里使用了线性变换层,隐藏神经元节点数目为100,神经元节点数目设置可以自己设定。
paddle.nn.ReLU(),
#激活函数,Relu(x)=max(0,x)
paddle.nn.Linear(100,10)
#输出层
)
model=paddle.Model(mnist)
#模型封装
model.summary((1,28,28))
#模型可视化
这里主要使用的是Sequential建立,Sequential为paddlepaddle的顺序容器。
4.模型配置、模型训练、模型评价
#模型配置
model.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=mnist.parameters()),
paddle.nn.CrossEntropyLoss(), paddle.metric.Accuracy())
#学习率设置为0.001
#配置优化器,由于为多分类问题,所以选择交叉熵损失函数
#模型训练
model.fit(train_dataset, epochs=1, batch_size=32, verbose=1)
#epochs训练次数,batch_size一次性输入多少图片给网络训练,verbose为是否显示进度条
此处提出关于优化器loss函数选择的问题,为什么loss函数选择交叉熵:
在多分类问题中,通常选择交叉熵作为损失函数的计算的原因主要是:
- 交叉熵对比了模型的预测结果和数据的真实标签
比如期望的概率分布是Q,真实的概率分布为P
假设模型的正确预测标签P为[1,0,0,0,0]
计算交叉熵后
Entropy(P 1,Q1)=-(1log2 0.4+0log2 0.3+0*log2 0.05+0 log2 0.05+0 log2 0.2)
同理可得Entropy( P1,Q2)
发现随着预测数量增多,完全预测正确数量和完全预测错误数量的差,交叉熵逐渐在增大而均方差损失再减小。 - 交叉熵一般与softmax函数作匹配
softmax公式如下:
因为 softmax函数对一组数据的每个数据进行计算后,可以将这组数据中的每一个都映射到 (0,1) 区间上,并且其和为 1,符合概率的定义,而交叉熵恰恰是对概率分布进行计算,因此通常将 softmax 函数的输出结果作为交叉熵函数的输入,将二者构造为复合函数。
5.模型预测
#模型评估
model.evaluate(test_dataset, verbose=1)