栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

【MLP实战】001:基于Minist数据集的手写数字识别

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【MLP实战】001:基于Minist数据集的手写数字识别

本文又是一篇基于Minist数据集的手写数字识别。

首先,mnist数据集:
链接:https://pan.baidu.com/s/1z7R7_jnDKZm9F7M6n8hiIw
提取码:rn8z

首先将二维的28*28的照片一维化成1*784的向量,搭建了一个784->128->10三个全连接层构成的网络,输出了分类结果。Dense层用了0.2的dropout。

首先对文章代码进行分块介绍,然后给出运行过程和运行结果,再对调试过程中遇到的一些问题进行简要说明,最后粘贴全部代码。

目录

一、代码分块介绍

三、调试中遇到的问题

1. 版本不兼容问题

2. history=model.fit()

3. fit和evaluate中的verbose

4. 关于执行问题

5. fit和evaluate的区别

四、代码

总结:


一、代码分块介绍

导入库:

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import os

第一个是深度学习框架的库

第二个是绘图库

第三个是数据分析库

第四个是操作系统功能接口库

获取Minist数据集

data = tf.keras.datasets.mnist
(train_images,train_labels),(test_images,test_labels) = data.load_data()

获取数据集有很多种方法,比如下载下来保存到路径下,或者直接在tensorflow的库里加载。后文总结了获取数据集的方法,需要参考你的tensorflow版本,1.X和2.X不填一样。

#归一化
train_images = train_images/255.0 
test_images = test_images/255.0
#这一部分是为了测试显示样例所用
#为了产生5*5大小的框框,可以修改
plt.figure(figsize=(5,5))
class_name = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
#下面这段也可以不要,为了显示照片
for i in range(25):
    plt.subplot(5,5,i+1) #画图函数,代表将图按照5行5列的方式显示,i+1表示图存放的位置)
    plt.xticks([])#坐标轴
    plt.yticks([])
    plt.grid(True,axis='x')#网格
    plt.imshow(train_images[i],cmap=plt.cm.binary)#下面详细说说
    plt.xlabel(class_name[train_labels[i]])#去对应的标签
plt.show()#显示图片
plt.imshow(train_images[i],cmap=plt.cm.binary)

第一个参数表示第几张照片,第二个参数cmap=colormap。

设置cmap参数有以下几种方式:

plt.imshow(image, cmap=plt.get_cmap('gray_r'))
plt.imshow(image, cmap='gray_r')
plt.imshow(image, cmap=plt.cm.binary)

参数作用

# 训练和保存模型
if os.path.exists('./model.h5'):		#如果该路径下存在该模块,则加载模块,否则训练模型并保存
    model = tf.keras.models.load_model('./model.h5')
else:
    model = tf.keras.models.Sequential([		#搭建网络结构
        tf.keras.layers.Flatten(input_shape=(28,28)),#拉直层可以变换张量的尺寸,把输入特征拉直为一维数组==1*784维向量
        tf.keras.layers.Dense(128,activation='relu'),#第一个参数神经元个数,第二个参数‘激活函数’
        tf.keras.layers.Dropout(0.2), #dropout丢失率设置为0.2
        tf.keras.layers.Dense(10,activation='softmax') # 输出层,10分类,10个神经元,多分类采用softmax分类器
    ])
    model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
    model.fit(train_images,train_labels,epochs=10)
    model.save('model.h5') #保存模型,命名为model.h5,以后运行直接调用模型,不必训练

使用tf.keras.model.Sequential搭建分类模型主要包括七个步骤:(1)导入包模块;(2)加载数据集;(3)切分训练集和验证集;(4)对数据进行归一化处理;(5)搭建分类模型;(6)训练模型;(7)将模型应用于测试集。

前面4个之前已做,上面的代码就是搭建分类模型的代码。首先将输入的28*28照片拉成一维的1*784的向量作为输入,然后经过一个128个神经元的全连接层Dense,其dropout设置为0.2,最后连接到10个神经元的输出层作为分类结果。Dense层的激活函数为relu,输出层多分类,激活函数使用softmax。

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

optimizer:优化器设置为Adam;

loss:损失函数为交叉熵损失;

metrics: 列表,包含评估模型在训练和测试时的性能的指标,典型用法是metrics=[‘accuracy’];

history = model.fit(train_images,train_labels,epochs=10)
loss = history.history['loss']
acc = history.history['accuracy']

model.fit:返回训练时的情况,返回的是一个History对象,可以通过History.history来查看训练过程,loss值等等,作为列表被保存了下来,方便后面画epoch的图用。epoch设为10。

plt.subplot(1, 2, 1)
plt.plot(acc, label='Training Accuracy')
plt.title('Training Accuracy')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.title('Training Loss')
plt.legend()
plt.show()

画出loss和accuracy随着epoch变化的图。

print('在测试集上评估')
test_loss,test_acc = model.evaluate(test_images,test_labels,verbose=1)
print('看看测试及测试结果')
predictions = model.predict(test_images)
for i in range(10):
    print('预测值 = %i;正确值 = %i' % (np.argmax(predictions[i]),test_labels[i]))

model.evaluate():返回的是损失值和你指定的指标值。本例中你的目标是准确率accuracy,即model.compile(metric["accuracy"])。此处返回测试集的Loss和acc。只返回一个值。

model.predict将测试集照片进行预测,输出的是一个列表,保存对每个对应的test_images的预测。每个预测结果predict[i]都是一个长度为10的一维数组(十分类问题),哪个值最大就属于哪个分类结果。所以predeicts是一个test_size*10的二维数组。

ef preprocess_image(image):
    image = tf.image.decode_jpeg(image,channels=1)
    image = tf.image.resize(image,[28,28])
    image = image/255.0
    image = tf.reshape(image,[28,28])
    return image

将输入的照片剪裁成合适尺寸,并归一化,最后改变形状。

def load_and_preprocess_image(path):
    image = tf.io.read_file(path)
    return preprocess_image(image)

读一个路径下的图片。

filepath = './3.jpg'
test_my_image = load_and_preprocess_image(filepath)
test_my_image = (np.expand_dims(test_my_image,0))
my_result = model.predict(test_my_image)
print('自己的图片预测值 = %i ; 文件名 = ', (np.argmax(my_result[0]), filepath))

测试:加载本文件同路径下的照片,reshape后进行预测。

二、运行过程和结果

整篇代码没有什么错误,下载所需的库就可以直接运行。

运行结果:

(1)显示的图片库中的一些图片:

 (2)model.fit模型训练时,画的loss和acc随epoch变化图:

 (3)model.fit模型训练时的日志信息,包括loss和acc:

训练模型:
2021-10-05 15:33:45.436902: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN)to use the following CPU instructions in performance-critical operations:  AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
Epoch 1/10
1875/1875 [==============================] - 1s 792us/step - loss: 0.2952 - accuracy: 0.9153
Epoch 2/10
1875/1875 [==============================] - 2s 874us/step - loss: 0.1424 - accuracy: 0.9578
Epoch 3/10
1875/1875 [==============================] - 2s 858us/step - loss: 0.1068 - accuracy: 0.9672
Epoch 4/10
1875/1875 [==============================] - 2s 824us/step - loss: 0.0890 - accuracy: 0.9728
Epoch 5/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.0750 - accuracy: 0.9772
Epoch 6/10
1875/1875 [==============================] - 2s 831us/step - loss: 0.0656 - accuracy: 0.9792
Epoch 7/10
1875/1875 [==============================] - 2s 816us/step - loss: 0.0587 - accuracy: 0.9811
Epoch 8/10
1875/1875 [==============================] - 2s 835us/step - loss: 0.0547 - accuracy: 0.9821
Epoch 9/10
1875/1875 [==============================] - 2s 929us/step - loss: 0.0468 - accuracy: 0.9845
Epoch 10/10
1875/1875 [==============================] - 2s 833us/step - loss: 0.0454 - accuracy: 0.9847

 (4)model.evaluate评估训练完的模型的结果(用测试集):

在测试集上评估
313/313 [==============================] - 0s 775us/step - loss: 0.0717 - accuracy: 0.9790

(5)该路径下图片的预测结果:

开始预测:
自己的图片预测值 = %i ; 文件名 =  (5, './3.jpg')

三、调试中遇到的问题

1. 版本不兼容问题

tensorflow1.X和2.X版本不兼容,找到的代码里边有些是1.X的语法,在导入库时用以下代码:

把
import tensorflow as tf
改成:
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

例如,在使用sess=tf.Session时,不能使用,就需要如下方式改:

import tensorflow as tf
tf.compat.v1.disable_eager_execution()

matrix1 = tf.constant([[3,3]])
matrix2 = tf.constant([[2],[2]])
product = tf.matmul(matrix1,matrix2)
print(matrix1)
print(matrix2)
print(product)

# method 1
sess = tf.compat.v1.Session()
result = sess.run(product)
print(result)
sess.close()
# method 2
# with tf.compat.v1.Session() as sess:
# result2 = sess.run(product)
# print(result2)

2. history=model.fit()
history = model.fit(train_images,train_labels,epochs=10)
loss = history.history['loss']
acc = history.history['accuracy']

model.fit()保存了模型训练时训练集loss、验证集loss、训练集准确率数据,作为字典保存了下来。但不同方法种调用loss和acc的数据不一样。本例中key的名字分别为loss和accuracy。

其他的方法可能不一样,如:

acc = history.history['sparse_categorical_accuracy']
val_acc = history.history['val_sparse_categorical_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

3. fit和evaluate中的verbose

其作用为记录训练日志。

verbose = 0 为不在标准输出流输出日志信息,verbose = 1 为输出进度条记录,verbose = 2 为每个epoch输出一行记录。

4. 关于执行问题

有的同学可能注意到,别的网络代码都有session作为模型调用的开始执行,但本例里面没用,难道它是直接执行的吗?

是的。因为别的代码用了session都是将模型写成了一个函数,封装在里面,函数是不会执行的,函数只有被调用了才可以执行。所以需要建立session对象来执行。

但是本例的模型执行直接在if-else里面,构建了model后,执行到model.fit时就开始执行了。

5. fit和evaluate的区别

fit():用于使用给定输入训练模型;

predict():用于实际预测,它为输入样本生成输出预测;

evaluate():用于评估已经训练过的模型,返回损失值&模型的度量值。

同时,模型的BatchNormalization,Dropout,LayerNormalization等优化手段只在fit时,对训练集有用;在进行evaluate()的时候,这些优化都会失效,因此,再次进行evaluate(x_train,y_train),就算添加了batchsize,也不能达到相同的评估计算结果。

四、代码
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import os

data = tf.keras.datasets.mnist
(train_images,train_labels),(test_images,test_labels) = data.load_data()
train_images = train_images/255.0 #归一化
test_images = test_images/255.0

plt.figure(figsize=(5,5))
class_name = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(True,axis='x')
    plt.imshow(train_images[i],cmap=plt.cm.binary)
    plt.xlabel(class_name[train_labels[i]])
    # plt.ylabel(class_name[train_labels[i]])
plt.show()
#训练和保存模型
if os.path.exists('./model.h5'):
    print('直接加载模型:')
    model = tf.keras.models.load_model('./model.h5')
else:
    print('训练模型:')
    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape=(28,28)),
        tf.keras.layers.Dense(128,activation='relu'),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(10,activation='softmax')
    ])
    model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
    history = model.fit(train_images,train_labels,epochs=10)
    loss = history.history['loss']
    acc = history.history['accuracy']

    plt.subplot(1, 2, 1)
    plt.plot(acc, label='Training Accuracy')
    plt.title('Training Accuracy')
    plt.legend()

    plt.subplot(1, 2, 2)
    plt.plot(loss, label='Training Loss')
    plt.title('Training Loss')
    plt.legend()
    plt.show()

    model.save('model.h5')

print('在测试集上评估')
test_loss,test_acc = model.evaluate(test_images,test_labels,verbose=1)
print('看看测试及测试结果')
predictions = model.predict(test_images)
print('预测值 = %i;正确值 = %i' % (np.argmax(predictions[0]),test_labels[0]))

# 图片进行预处理,reshape后进行归一化
def preprocess_image(image):
    image = tf.image.decode_jpeg(image,channels=1)
    image = tf.image.resize(image,[28,28])
    image = image/255.0
    image = tf.reshape(image,[28,28])
    return image

# 加载图片路径,将图片进行预处理后输出
def load_and_preprocess_image(path):
    image = tf.io.read_file(path)
    return preprocess_image(image)

print('开始预测:')
filepath = './3.jpg'
test_my_image = load_and_preprocess_image(filepath)
test_my_image = (np.expand_dims(test_my_image,0))
my_result = model.predict(test_my_image)
print('自己的图片预测值 = %i ; 文件名 = ',(np.argmax(my_result[0]), filepath))

总结:

(1)显然,这份代码有点憨批,照片识别没有用CNN。直接将二维的照片一维化成784的向量,搭建了一个784->128->10三个全连接层构成的网络,输出了分类结果。

(2)同时,本文在fit时没有用batchsize,所以训练时有点慢,且准确率达到98.10%。加上batchsize后,如设置为1000,每1000个才进行一次更新,快了很多,但准确率下降到96%。

有了batchsize=1000:

没有batchsize:

不过作为新手还是推荐学习的,学习一下整个神经网络的训练和学习过程。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/294344.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号