Day 4 tensorflow 模型的存取与 mnist 分类

混了两天范例,该认真点了XD

今天要训练模型,储存模型,读取模型,拿模型分类图片,

以下程序码是昨天的范例,但在最後加上 save ,来储存模型。
为了自己测试方便,我把档案副档名改成了 Jupyter Notebook 的格式(ipynb)。

# a02_tf_mnist.ipynb
import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

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'])

# 训练
model.fit(x_train, y_train, epochs=5)

# 用测试资料评估
model.evaluate(x_test,  y_test, verbose=2)

# 将模型存在 mnist 资料夹
model.save("mnist")

资料夹格式如下,我目前的版本是tensorflow 2.6.0,
其他版本格式可能不同。

接下来再开一个新档案,a03_tf_category.py

# a03_tf_category.ipynb

import tensorflow as tf
saved_model_path = "mnist"
# 读取模型
model = tf.keras.models.load_model(saved_model_path)
# 显示模型资讯
model.summary()

# 显示模型的输入输出格式
print(model.input)
# KerasTensor(type_spec=TensorSpec(shape=(None, 28, 28), dtype=tf.float32, name='flatten_input'), name='flatten_input', description="created by layer 'flatten_input'")

print(model.output)
# KerasTensor(type_spec=TensorSpec(shape=(None, 10), dtype=tf.float32, name=None), name='dense_1/Softmax:0', description="created by layer 'dense_1'")

可以从以下资讯中得知,输入是一个三维浮点数阵列
第一个维度没有限制长度,而二三维长度限制是 28。
shape=(None, 28, 28), dtype=tf.float32

接下来看看最初怎麽训练的。
mnist 是手写数字集。
mnist.load_data() 会回传 shape == (60000, 28, 28),且数值介於 0~255 的浮点数。
也就是 60000 张 28 x 28 的手写数字。
https://www.tensorflow.org/api_docs/python/tf/keras/datasets/mnist/load_data
而在训练前,范例将数值除以 255,变成介於 0~1 的浮点数。

x_train, x_test = x_train / 255.0, x_test / 255.0

那麽如果我们要用这个模型来分类,要做的预处理就是把图片处理成 28x28,介於 0~1 的浮点数阵列。
安装 opencv

conda install -c anaconda opencv

之後来处理图片,这里我画了3张图

使用 opencv ,读取读片,转灰阶,缩小为 28x28。

import cv2

# 读取图片 1
img = cv2.imread('1.png')
print(img.shape) # (100, 100, 3)

# 预设图片读进来是彩色,有RGB的维度,於是我在这里把图片转灰阶
imggray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print(imggray.shape) # (100, 100)

# 缩小为 28x28
resized = cv2.resize(imggray, (28, 28))
print(resized.shape) # (28, 28)

# mnist 的图集黑色是255,白色是 0,而图片读进来是 黑色是0,白色是 255
# 所以在这里除255後,也顺便把黑白翻转过来。
resized = 1 - resized / 255.0

# 原本的格式是将 N 张图片丢进去训练,,所以预测时也不能直接丢,而是在外面包一层阵列。
# 最後将阵列化 resized 转成 tensor 进行预测。
model(tf.constant([resized]))
# <tf.Tensor: shape=(1, 10), dtype=float32, numpy=
# array([[1.1365917e-04, 9.4607556e-01, 3.3843194e-03, 9.3289698e-03,
#         3.3142285e-03, 3.7603064e-03, 1.8111777e-03, 7.1768690e-04,
#         3.1470988e-02, 2.3163184e-05]], dtype=float32)>

# 科学记号不方便看,所以在这里改为小数点後两位。
# mnist 的顺序是从 0 开始,所以 1.png 这张题片摆在第2位。
# 输出是一组机率阵列。
[[round(float(j), 2) for j in i] for i in model(tf.constant([resized]))]
# [[0.0, 0.95, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.03, 0.0]]

接下来一次分类三张图吧

def readimg(imgpath):
    img = cv2.imread(imgpath)
    imggray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    resized = cv2.resize(imggray, (28, 28))
    return 1 - resized / 255.0

imgfiles = ["1.png", "2.png", "3.png"]
imgs = [readimg(i) for i in imgfiles]

[[round(float(j), 2) for j in i] for i in model(tf.constant(imgs))]
# [[0.0, 0.95, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.03, 0.0],
#  [0.0, 0.0, 0.99, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
#  [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]

<<:  [从0到1] C#小乳牛 练成基础程序逻辑 Day 4 - I/O 宣告变数 赋予值

>>:  Day7 Collectionview小实作1

Day 25 - 介绍 OSPF

今天我们来配 OSPF。 OSPF 是一种 IGP (Interior Gateway Protoc...

Day 28 - 建立自己的K线资料库 (下)

本篇重点 建立Index,加快SQLite存取速率 产生日K线资料 产生周K线资料 产生月K线资料 ...

为了转生而点技能-javascript,day2(杂记-记忆体的回收机制-Not Defined VS undefined

Not Defined VS undefined undefined: 在创造阶段只有变数在记忆体里...

从容面对不如预期,把不爽留给命运

早起运动Day6 - 生日快乐我的国家​ ​ 三点多有起来记录了一下梦话,接着再睡了回去,我想那是在...

Day 15 : 案例分享(5.1) CRM与ERP整合 - 线索与商机

案例说明及适用场景 Odoo CRM 简单区分的话 商机 自动建立 商机 阶段管理 商机 转为订单 ...