再探MNIST

这里就是搭建一个CNN网络来做手写数字的识别。

import tensorflow as tf
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

# 加载数据集
minst = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = minst.load_data()
# 设置数据集使之符合tensorflow的输入
x_train = np.pad(x_train, ((0, 0), (2, 2), (2, 2)), 'constant', constant_values=0)
x_test = np.pad(x_test, ((0, 0), (2, 2), (2, 2)), 'constant', constant_values=0)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train = x_train/255
x_test = x_test/255
x_train = x_train.reshape(x_train.shape[0], 32, 32, 1)
x_test = x_test.reshape(x_test.shape[0], 32, 32, 1)

# 模型建立
model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(filters=6, kernel_size=(5, 5), padding="valid", activation=tf.nn.tanh, input_shape=(32, 32, 1)),
    # 这里的input_shape就对输入的形状大小有限制。激活函数是神经网络的灵魂。
    # 它把线性变换转变成了非线性的。
    # 至于padding是什么?该单词的中文意思是填补。
    # 如果是valid,到了边界部分,不够一个卷积核大小的,就直接丢掉不用了,若是same,则自己填充0使之达到一个卷积核的大小。
    # "SAME"时,卷积之后的输出形状大小是取上整(W/S)  W是输入图片的尺寸大小。S是步长。
    # "VALID"时,卷积之后的输出形状大小是取上整((W-F+1)/S) F是卷积核大小。
    tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding="same"),
    # 平均池化,池化之后的图像的大小会一半。
    tf.keras.layers.Conv2D(filters=16, kernel_size=(5, 5), padding="valid", activation=tf.nn.tanh),
    tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding="same"),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(units=120, activation=tf.nn.tanh),
    tf.keras.layers.Dense(units=84, activation=tf.nn.tanh),
    tf.keras.layers.Dense(units=10, activation=tf.nn.softmax),
    # 关于各个激活函数是个什么鬼样子,可以自己去搜一下。
])

# 模型训练
# 超参设置
num_epochs = 10
batch_size = 64
learning_rate = 0.001
# 优化器
adam_optimizer = tf.keras.optimizers.Adam(learning_rate)
# 这里使用这个优化器。# arxiv.org/abs/1412.6980v8 听说这是说明书,但从来没打开过。。
model.compile(optimizer=adam_optimizer, loss=tf.keras.losses.sparse_categorical_crossentropy, metrics=['accuracy'])
# loss函数使用的是这个,这个函数适合多分类问题,这里就是多分类。与categorical_accuracy相同,这个尤其对稀疏的目标值预测时有用。

import datetime  # 计算时间
start_time = datetime.datetime.now()
model.fit(x=x_train, y=y_train, batch_size=batch_size, epochs=num_epochs)
end_time = datetime.datetime.now()
time_cost = end_time-start_time
print("time_cost = ", time_cost)

# 下面这里是测试了。是读入一个图片,是我手写的一个数字。做处理,满足输入格式后输入。
# 测试
img = cv.imread('0.jpg')   # 载入
print(img.shape)
plt.imshow(img)
plt.show()
# 转为灰度
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
print(img.shape)
plt.imshow(img)
plt.show()
# 转换成白底黑字,因为训练集里面就是这样。而我写出来的转成灰度之后是黑底白字。
img = cv.bitwise_not(img)
print(img.shape)
plt.imshow(img)
plt.show()
# 这里的目的是让黑色更黑,白色更白。0代表黑色 #255代表白色
img[img <= 95] = 0
img[img > 150] = 255
print(img.shape)
plt.imshow(img)
plt.show()
# 接下来是处理格式,使之满足输入的格式。
img = cv.resize(img, (32, 32))
print(img.shape)
cv.imshow('image', img)
img = img.astype('float32')
img /= 255
img = img.reshape(1, 32, 32, 1)
print(img.shape)
pred=model.predict(img)
print(pred)  # 输出判断为每个数字的概率。
print(pred.argmax())  # 输出具体的那个数字。

手写的数字长这样。
手写的数字长这样。

原创文章 77 获赞 4 访问量 9047

猜你喜欢

转载自blog.csdn.net/weixin_40007143/article/details/104706050