本文章介绍使用TensorFlow2.0+ 上手mnist数据集学习的一个示例,以便快速的使用Tensorflow
Tensorflow 中相关概念理解
# 计算图 是 Tensorflow 的基本计算模型
# 张量 tensor - Tensorflow管理数据的形式
Tensor("add:0",shape=(2,1),dtype=float32)
张量的三个属性:名字,维度、类型
## 名字 name 计算节点"add"输出的第一个结果
## 维度 shape 一个长度为2的1维数组
## 类似 dtype 参与运行的张量类型必须一样
Tensorflow2.0 后一个训练示例的基本步骤
# 导入数据
(train_images, train_labels), (test_images, test_labels) = keras.datasets.mnist.load_data()
# 数据处理,维度要一致
train_images = train_images.reshape((-1, 28, 28, 1)).astype('float32')
test_images = test_images.reshape((-1, 28, 28, 1)).astype('float32') # -1代表那个地方由其余几个值算来的
train_images = train_images / 255
test_images = test_images / 255
# 定义模型方法,这里可以定义更深层的网络模型、
## 卷积神经网络:激活、池化层、全连接层、分类层等等
keras.Sequential()
# 训练模型配置,优化器、损失函数、回归问题用均方差
model.compile
# 训练模型
model.fit(train_images, train_labels, batch_size=64, epochs=10, validation_split=0.1)
# 测试模型
model.evaluate(test_images, test_labels)
# 保存模型
model.save('保存目录')
# 验证自己的数据,查看返回值
model.predict(x_pre)
完整示例介绍
Mac运行基本的tensorflow函数,需要在代码前添加
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
使用Keras导入MNIST数据集
# 默认的直接以下使用方法加载数据集,会从https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz国外网站下载,所以会失败
(train_images, train_labels), (test_images, test_labels) = keras.datasets.mnist.load_data()
正确的操作是将其下载下来下载地址四个压缩文件夹,放到~/.keras/datasets/目录下,这样keras就会使用本地包,执行代码不再报错
完整的源代码与其中步骤解说
"""
mnist 数据集的训练、测试、保存模型、用验证模型
"""
# 相关库的导入
from tensorflow import keras
import tensorflow.keras.layers as layers
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
# 导入数据
(train_images, train_labels), (test_images, test_labels) = keras.datasets.mnist.load_data()
# 观察数据
print(train_images.shape)
plt.imshow(train_images[10000])
print(train_labels[10000])
# 数据处理,维度要一致
train_images = train_images.reshape((-1, 28, 28, 1)).astype('float32')
test_images = test_images.reshape((-1, 28, 28, 1)).astype('float32') # -1代表那个地方由其余几个值算来的
train_images = train_images / 255
test_images = test_images / 255
print(train_images.shape)
# 定义模型方法一-add()
# 这里我的模型比较简单,但准确率也有98%多,感兴趣的可以扩大深度或者引入其他方法优化下
model = keras.Sequential()
model.add(layers.Conv2D(input_shape=(28, 28, 1),
filters=32, kernel_size=(3, 3), strides=(1, 1), padding='valid',
activation='relu')) # 卷积层加激活
model.add(layers.MaxPool2D(pool_size=(2, 2))) # 池化层
model.add(layers.Flatten()) # 全连接层
model.add(layers.Dense(32, activation='relu'))
# 分类层
model.add(layers.Dense(10, activation='softmax'))
# 训练模型配置
model.compile(optimizer=keras.optimizers.Adam(),
# loss=keras.losses.CategoricalCrossentropy(),
# 损失函数多分类使用交叉熵(这里还要看标签是否为one-hot编码)
# 回归问题用均方差
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=['accuracy'])
model.summary()
# 进行模型训练
history = model.fit(train_images, train_labels, batch_size=64, epochs=10, validation_split=0.1) #epochs,训练迭代次数
# 保存下模型(这个方法比较常用,也可以考虑适合部署的SavedModel 方式)
model.save('saved_model/my_model') # 保存模型,名字可以任取,但要由.h5后缀
# 测试模型
model.evaluate(test_images, test_labels)
# 构建神经网络层结构
# 这个网络的第一层,tf.keras.layers.Flatten,将图像的格式从一个二维数组(28×28像素)转换为一个一维数组(28 * 28 = 784像素)。把这层想象成把图像中的像素行分解并排列起来。这一层没有需要学习的参数;它只会重新格式化数据。
# 在像素被平展之后,网络由两个tf.keras.layers.Dense组成。致密层。这些是紧密相连的,或完全相连的神经层。第一个致密层有128个节点(或神经元)。第二层(也是最后一层)返回长度为10的logits数组。每个节点包含一个分数,表示当前图像属于10个类中的一个。
# 在模型准备好进行培训之前,它需要更多的设置。这些是在模型的编译步骤中添加的:
#
# 损失函数——测量模型在训练过程中的准确性。您希望最小化这个函数,以将模型“引导”到正确的方向。
# 优化器——这是根据模型所看到的数据及其损失函数更新模型的方法。
# 度量标准——用于监视培训和测试步骤。下面的例子使用了准确率,即被正确分类的图像的比例。
# 定义一个简单的序列模型
# 训练神经网络模型需要以下步骤:
#
# 将训练数据提供给模型。在本例中,训练数据位于train_images和train_labels数组中。
# 模型学会将图像和标签联系起来。
# 您要求模型对测试集做出预测—在这个例子中,test_images数组。
# 验证预测是否与test_labels数组中的标签匹配。
# 开始训练模型
"""
使用保存的模型验证准确性
"""
new_model = tf.keras.models.load_model('saved_model/my_model')
# 检查其架构
new_model.summary()
# 评估还原的模型
loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))
print(new_model.predict(test_images).shape)
def output(y_pre, y):
temp = np.argmax(y_pre)
print('预测结果为' + str(temp))
print('实际结果为' + str(y))
if str(temp) == str(y):
print('预测结果正确')
else:
print('预测结果错误')
def readnum(path): # 读取自己的数字数据进行预测
img = cv2.imread(path, 0) # 灰度图读入
# 查看数据
img = cv2.resize(img, (28, 28))
# cv2.imshow('img', img)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
img = np.array(img)
img = img.reshape((-1, 28, 28, 1)).astype('float32')
img = 1 - img / 255.0 # 因为我的数字是相反颜色的所以有个反转
return img
# 预测并输出结果
path = '/tmp/666.png' # 验证的数据图片
x_pre = readnum(path)
y_pre = new_model.predict(x_pre)
output(y_pre, 6)