TensorFlow 学习笔记(四)手写体数字模型的建立

上一篇

手写体数字数据集的生成

1 进行数据预处理

1.1 导入所需模块
from keras.utils import np_utils
import numpy as np
np.random.seed(10)

在 JupyterNotebook 中显示如图:
在这里插入图片描述

1.2 读取数据

这里的路径必须是自己存放 npz 文件的路径。

train_dic=np.load('E:/practice/data_and_distribution/data_train.npz',allow_pickle=True)
(x_train_image,y_train_label)=train_dic['x'],train_dic['y']
test_dic=np.load('E:/practice/data_and_distribution/data_test.npz',allow_pickle=True)
(x_test_image,y_test_label)=test_dic['x'],test_dic['y']

如果使用 MNIST 数据集。(初次加载可能会比较慢)

(x_train_image, y_train_label), \
(x_test_image, y_test_label) = mnist.load_data()

注:如果 MNIST 数据集加载出现错误,请前往以下网址手动下载。
亚马逊 MNIST 数据集下载链接
下载完成后复制文件到 C:\Users\用户名.keras\datasets,重新运行指令即可。

代码在 JupyterNotebook 中显示如图:
在这里插入图片描述

1.3 将 features (数字图像特征值)使用 reshape 转换。

可以用下列指令查看每一个数字图像的 shape 是 28×28。

print('train data=',len(x_train_image))
print(' test data=',len(x_test_image))

在 JupyterNotebook 中显示如图:
在这里插入图片描述

下面的程序将原本 28×28 的数字图像以 reshape 转换成 784 个 Float 数。
因为单个神经元只能对应单个的点,图像矩阵有 28 行 28 列,28×28=784个。

x_Train=x_train_image.reshape(60000, 784).astype('float32')
x_Test=x_test_image.reshape(10000, 784).astype('float32')

在 JupyterNotebook 中显示如图:
在这里插入图片描述

再次查看发现每一个数字图像变成了长度为 784 的一维张量。
在这里插入图片描述

查看 images 第 0 项的内容。

import matplotlib.pyplot as plt
def plot_image(image):
    fig = plt.gcf()
    fig.set_size_inches(2, 2)
    plt.imshow(image, cmap="binary")
    plt.show()

plot_image(x_train_image[0])

PIL 的图像:
在这里插入图片描述

MNIST 的图像:
在这里插入图片描述

从以上结果可知,数字矩阵的大部分是0,少部分是有效值。
对于 MNIST 数据集,每一个数字都是从 0 到 255 的值,代表图形每一个点灰度的深浅。

1.4 将 features (数字图像特征值)标准化。

将 features (数字图像特征值)标准化可以提高模型预测的准确度,并且更快收敛。
(仅在 MNIST 数据集中有作用)

x_Train_normalize=x_Train/255
x_Test_normalize=x_Test/255

在 JupyterNotebook 中显示如图:
在这里插入图片描述

1.5 label (数字真实的值) 以 One-Hot Encoding 转换。
y_Train_OneHot=np_utils.to_categorical(y_train_label)
y_Test_OneHot=np_utils.to_categorical(y_test_label)

在 JupyterNotebook 中显示如图:
在这里插入图片描述

以下列指令来查看训练数据 label 标签字段的前 5 项训练数据,我们可以看到这是 0-9 的数字。

y_train_label[:5]

在这里插入图片描述

使用 np_utils.to_categorical 将训练数据与测试数据的 label 进行 One-Hot Encoding 转换。

y_TrainOneHot = np_utils.to_categorical(y_train_label)
y_TestOneHot = np_utils.to_categorical(y_test_label)
y_train_label[:5]

进行 One-Hot Encoding 转换后,查看训练数据 label 标签字段的前 5 项训练数据,我们可以看到转换后的结果。
在这里插入图片描述

参考上面的结果,例如第一项数据,原本的真实值是 5 ,进行 One-Hot Encoding 转换后,只有第 5 个数字(由 0 算起)是 1,其余都是 0。
这样就可以用 10 个神经元来表示 0-9 的数字。

2 建立模型

我们将建立下列多层感知器模型,输入层(x)共有 784 个神经元,隐藏层 (h)共有 256 个神经元,如图 7-4 所示。我们将使用下面的程序代码建立多层感知机模型。
在这里插入图片描述

2.1 导入所需模块
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
2.2 建立 Sequential 模型

建立一个线性堆叠模型,后续只需要使用 model.add() 方法将各个神经网络层加入模型即可。

model = Sequential()
2.3 建立“输入层”与“隐藏层”

以下程序代码将“输入层”与“隐藏层”加入模型,使用 model.add() 方法加入 Dense 神经网络层。Dense 神经网络层的特色是:所有的上一层与下一层的神经元都完全连接。

model.add(Dense(units=256,input_dim=784,kernel_initializer="normal",activation='relu'))
参数参数说明
units=256定义“隐藏层”神经元个数为 256
input_dim=784设置“输入层”神经元个数为 784
kernel_initializer=‘normal’使用 normal distribution 正态分布的随机数来初始化 weight 和 bias
activation定义激活函数为 relu

关于激活函数 一篇关于激活函数比较详细的博客

2.4 加入 DropOut 功能,以解决过度拟合的问题

过拟合:为了得到一致假设而使假设变得过度严格称为过拟合。
也就是说参数矩阵训练过度,一个假设在训练数据上能够获得比其他假设更好的拟合, 但是在训练数据外的数据集上却不能很好地拟合数据。这时候应该主动舍弃一部分参数,我们通过如下代码舍弃了 50 % 的数据。

model.add(Dropout(0.5))
2.5 建立输出层

输出层共有 10 个神经元,对应 0~9 十个数字。并且使用 softmax 激活函数进行转换,softmax 可以将神经元的输出转换为预测每一个数字的概率。

model.add(Dense(units=10,kernel_initializer='normal',activation='softmax'))

以上建立 Dense 神经网络不需要设置 input_dim,因为 Keras 会自动按照上一层的 units 是 256 个神经元,设置这一层的 inpuy_dim 为 256。

2.6 查看模型的摘要
print(model.summary())

在这里插入图片描述

建立输入层和隐藏层的公式如下: h1 = relu(X*W1 + b1)

建立隐藏层和输出层的公式如下: y = softmax(h1*h2 + b2)

在这里插入图片描述

通常 Trainable Param 数值越大,代表此模型越复杂,需要越多的时间进行训练。
第 2 节在 JupyterNotebook 中显示如图:
在这里插入图片描述

3 进行训练

在我们建立好深度学习模型之后,就可以使用反向传播算法进行训练了。
这个网页提供了不同的梯度下降函数的可视化。
梯度下降法可视化网址

3.1 定义训练方式

在训练模型之前,我们必须使用 compile 方法对训练模型进行设置,指令如下:

model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])

compail 方法需输入下列参数。

  • loss: 设置损失函数,这里使用交叉熵训练的效果比较好。
  • optimizer 使用 adam 优化器使得训练更快收敛,并提高准确率。
  • metrics: 设置评估模型的方式是准确率。
3.2 开始训练

进行 10 次训练,每次使用 48000 项数据训练,分为 240 个批次,每个批次
200 项。再用 12000 项数据进行验证,计算这个训练周期的准确度与误差,并在 train_history 中新增一项记录。

train_history = model.fit(x=x_Train_normalize,
                         y=y_Train_OneHot,validation_split=0.2,
                         epochs=10,batch_size=200, verbose=2)

训练结果会存贮在 train_history 变量中。

参数说明
x=x_Train_normalizefeatures 数字图像的特征值
y=y_Train_OneHotlabel 数字图像真实的值
validation_split=0.280%作为训练数据,20%作为验证数据
epochs=10执行 10 个训练周期
batch_size=200每一批次 200 项训练数据
verbose=2训练过程可视

在这里插入图片描述

从以上执行结果可知,误差越来越小,准确度越来越高。

3.3 显示训练过程

读取 train_history 里的数据,以图表显示训练过程。

import matplotlib.pyplot as plt
def show_train_history(train_history,train,validation):
    plt.plot(train_history.history[train])
    plt.plot(train_history.history[validation])
    plt.title('Train History')
    plt.ylabel(train)
    plt.xlabel('Epoch')
    plt.legend(['train','validation'], loc='upper left')
    plt.show()
程序代码说明
plt.title(‘Train History’)设置标题
plt.ylabel(train)设置 y 轴的标签名称
plt.xlabel(‘Epoch’)设置 x 轴的标签名称
plt.legend([‘train’,‘validation’], loc=‘upper left’)设置图例是 ‘train’ ‘validation’ ,位置在左上角

调用函数画出准确率评估的执行结果

show_train_history(train_history,'accuracy',"val_accuracy")

在这里插入图片描述

因为使用了 DropOut 函数,所以模型得到的结果非常好。随着训练次数的增加,训练和验证的准确度都越来越高,并且彼此靠近。如果没有 DropOut 函数,在训练的后期,’accuracy’ 数值将高于 ‘val_accuracy’ 之后 ’accuracy’ 将继续升高,而 ‘val_accuracy’ 将逼近极限,陷入俗称的过度拟合。
关于过度拟合访问 wiki 需要科学上网!
在这里插入图片描述

画出误差执行结果,可以看到无论是训练还是验证,误差都越来越低。

show_train_history(train_history,'loss',"val_loss")

在这里插入图片描述

3.4 以测试数据评估模型准确率

之前我们已经完成了训练,现在要使用 test 测试数据来评估模型准确率。

scores = model.evaluate(x_Test_normalize, y_Test_OneHot)
print()
print('accuracy=',scores[1])

在这里插入图片描述
准确率约为 0.984

程序代码说明
model.evaluate该函数可以评估模型的准确率,评估的结果会存在变量 scores 中
x=x_Train_normalizefeatures 数字图像的特征值
y=y_Train_OneHotlabel 数字图像真实的值
print(‘accuracy=’,scores[1])显示准确率

4 进行预测

通过之前的步骤,我们建立了模型,并且完成了模型训练,接下来我们将使用此模型进行预测。

4.1 执行预测
prediction=model.predict_classes(x_Test_normalize)

注:源码有误,应该将 prediction=model.predict_classes(x_Test)
的参数改成 x_Test_normalize

利用 model.predict_classes 函数进行预测,并将预测结果存在变量 prediction 中

4.2 预测结果
prediction # 查看预测结果

在这里插入图片描述
可以看到第0项的预测结果是8,第1项的预测结果是3,诸如此类。

4.3 显示 10 项预测结果
def plot_images_labels_prediction(images, labels, prediction, idx, num = 10):
    fig=plt.gcf()
    fig.set_size_inches(12, 14)
    if num>25:num=25
    for i in range(num):
        ax=plt.subplot(5,5,1+i)
        ax.imshow(images[idx],cmap="binary")
        title= "label=" + str(labels[idx])
        if len(prediction)>0:
            title+=",prediction="+str(prediction[idx])
        ax.set_title(title,fontsize=10)
        ax.set_xticks([]);ax.set_yticks([])
        idx+=1
    plt.show()
plot_images_labels_prediction(x_test_image,y_test_label,prediction,idx=340)

在这里插入图片描述

可以看到我们随机选取的这十个数据预测结果和实际标签相符。

4.4 显示混淆矩阵

混淆矩阵用来显示在所建立的模型中,哪些数字准确率最高那些数字最容易混淆。
1.使用pandas crosstab 建立混淆矩阵

import pandas as pd
pd.crosstab(y_test_label,prediction,rownames=['label'],colnames=['predict'])

在这里插入图片描述

从图中可以看出数字 1 的准确率最高,数字 8 的错误率最高。

2.建立真实值与预测 DataFrame
因为我们希望能够找出所有预测错误的结果,所以创建下列 DataFrame 。

df=pd.DataFrame({'label':y_test_label,'predict':prediction})
df[:2]

在这里插入图片描述
3.如图显示所有 label 是 8 而 prediction 是 5 的数据。

df[(df.label==8)&(df.predict==5)]

在这里插入图片描述

附录

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值