数据集

数据集下载MNIST

首先读取数据集, 并打印相关信息

包括

  • 图像的数量, 形状
  • 像素的最大, 最小值
  • 以及看一下第一张图片
path = 'MNIST/mnist.npz'
with np.load(path, allow_pickle=True) as f:
x_train, y_train = f['x_train'], f['y_train']
x_test, y_test = f['x_test'], f['y_test'] print(f'dataset info: shape: {x_train.shape}, {y_train.shape}')
print(f'dataset info: max: {x_train.max()}')
print(f'dataset info: min: {x_train.min()}') print("A sample:")
print("y_train: ", y_train[0])
# print("x_train: \n", x_train[0])
show_pic = x_train[0].copy()
show_pic = cv2.resize(show_pic, (28 * 10, 28 * 10))
cv2.imshow("A image sample", show_pic)
key = cv2.waitKey(0)
# 按 q 退出
if key == ord('q'):
cv2.destroyAllWindows()
print("show demo over")

转换为tf 数据集的格式, 并进行归一化

# convert to tf tensor
x_train = tf.convert_to_tensor(x_train, dtype=tf.float32) // 255.
x_test = tf.convert_to_tensor(x_test, dtype=tf.float32) // 255.
dataset_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
dataset_train = dataset_train.batch(batch_size).repeat(class_num)

定义网络

在这里定义一个简单的全连接网络

def build_simple_net():
net = Sequential([
layers.Dense(256, activation='relu'),
layers.Dense(256, activation='relu'),
layers.Dense(256, activation='relu'),
layers.Dense(class_num)
])
net.build(input_shape=(None, 28 * 28))
# net.summary()
return net

训练

使用 SGD 优化器进行训练

def train(print_info_step=250):
net = build_simple_net()
# 优化器
optimizer = optimizers.SGD(lr=0.01)
# 计算准确率
acc = metrics.Accuracy() for step, (x, y) in enumerate(dataset_train):
with tf.GradientTape() as tape:
# [b, 28, 28] => [b, 784]
x = tf.reshape(x, (-1, 28 * 28))
# [b, 784] => [b, 10]
out = net(x)
# [b] => [b, 10]
y_onehot = tf.one_hot(y, depth=class_num)
# [b, 10]
loss = tf.square(out - y_onehot)
# [b]
loss = tf.reduce_sum(loss) / batch_size # 反向传播
acc.update_state(tf.argmax(out, axis=1), y)
grads = tape.gradient(loss, net.trainable_variables)
optimizer.apply_gradients(zip(grads, net.trainable_variables)) if acc.result() >= 0.90:
net.save_weights(save_path)
print(f'final acc: {acc.result()}, total step: {step}')
break if step % print_info_step == 0:
print(f'step: {step}, loss: {loss}, acc: {acc.result().numpy()}')
acc.reset_states() if step % 500 == 0 and step != 0:
print('save model')
net.save_weights(save_path)

验证

验证在测试集的模型效果, 这里仅取出第一张进行验证

def test_dataset():
net = build_simple_net()
# 加载模型
net.load_weights(save_path)
# 拿到测试集第一张图片
pred_image = x_test[0]
pred_image = tf.reshape(pred_image, (-1, 28 * 28))
pred = net.predict(pred_image)
# print(pred)
print(f'pred: {tf.argmax(pred, axis=1).numpy()}, label: {y_test[0]}')

应用

分割手写数字, 并进行逐一识别

  • 先将图像二值化
  • 找到轮廓
  • 得到数字的坐标
  • 转为模型的需要的输入格式, 并进行识别
  • 显示
def split_number(img):
result = []
net = build_simple_net()
# 加载模型
net.load_weights(save_path) image = cv2.cvtColor(img.copy(), cv2.COLOR_RGB2GRAY)
ret, thresh = cv2.threshold(image, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, 1, 2)
for cnt in contours[:-1]:
x, y, w, h = cv2.boundingRect(cnt) image = img[y:y+h, x:x+w]
image = cv2.resize(image, (28, 28)) pred_image = tf.convert_to_tensor(image, dtype=tf.float32) / 255.
pred_image = tf.reshape(pred_image, (-1, 28 * 28))
pred = net.predict(pred_image)
out = tf.argmax(pred, axis=1).numpy()
result = [out[0]] + result
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow("demo", img)
print(result)
k = cv2.waitKey(0)
# 按 q 退出
if k == ord('q'):
pass
cv2.destroyAllWindows()

效果

单数字



多数字



附录

所有代码, 文件 tf2_mnist.py

import os
import cv2
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, Sequential, optimizers, metrics # 屏蔽通知信息和警告信息
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 每批几张图片
batch_size = 2
# 类别数
class_num = 10
# 保存模型的路径
save_path = "./models/mnist.ckpt"
# 展示样例
show_demo = False
# 验证测试集
evaluate_dataset = False
# 是否训练
run_train = False
# 图片路径, 仅用于 detect_image(), 当为False时不识别
image_path = 'images/36.png' path = 'MNIST/mnist.npz'
with np.load(path, allow_pickle=True) as f:
x_train, y_train = f['x_train'], f['y_train']
x_test, y_test = f['x_test'], f['y_test'] if show_demo:
print(f'dataset info: shape: {x_train.shape}, {y_train.shape}')
print(f'dataset info: max: {x_train.max()}')
print(f'dataset info: min: {x_train.min()}') print("A sample:")
print("y_train: ", y_train[0])
# print("x_train: \n", x_train[0])
show_pic = x_train[0].copy()
show_pic = cv2.resize(show_pic, (28 * 10, 28 * 10))
cv2.imshow("A image sample", show_pic)
key = cv2.waitKey(0)
if key == ord('q'):
cv2.destroyAllWindows()
print("show demo over") # convert to tf tensor
x_train = tf.convert_to_tensor(x_train, dtype=tf.float32) // 255.
x_test = tf.convert_to_tensor(x_test, dtype=tf.float32) // 255.
dataset_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
dataset_train = dataset_train.batch(batch_size).repeat(class_num) def build_simple_net():
net = Sequential([
layers.Dense(256, activation='relu'),
layers.Dense(256, activation='relu'),
layers.Dense(256, activation='relu'),
layers.Dense(class_num)
])
net.build(input_shape=(None, 28 * 28))
# net.summary()
return net def train(print_info_step=250):
net = build_simple_net()
# 优化器
optimizer = optimizers.SGD(lr=0.01)
# 计算准确率
acc = metrics.Accuracy() for step, (x, y) in enumerate(dataset_train):
with tf.GradientTape() as tape:
# [b, 28, 28] => [b, 784]
x = tf.reshape(x, (-1, 28 * 28))
# [b, 784] => [b, 10]
out = net(x)
# [b] => [b, 10]
y_onehot = tf.one_hot(y, depth=class_num)
# [b, 10]
loss = tf.square(out - y_onehot)
# [b]
loss = tf.reduce_sum(loss) / batch_size # 反向传播
acc.update_state(tf.argmax(out, axis=1), y)
grads = tape.gradient(loss, net.trainable_variables)
optimizer.apply_gradients(zip(grads, net.trainable_variables)) if acc.result() >= 0.90:
net.save_weights(save_path)
print(f'final acc: {acc.result()}, total step: {step}')
break if step % print_info_step == 0:
print(f'step: {step}, loss: {loss}, acc: {acc.result().numpy()}')
acc.reset_states() if step % 500 == 0 and step != 0:
print('save model')
net.save_weights(save_path) def test_dataset():
net = build_simple_net()
# 加载模型
net.load_weights(save_path)
# 拿到测试集第一张图片
pred_image = x_test[0]
pred_image = tf.reshape(pred_image, (-1, 28 * 28))
pred = net.predict(pred_image)
# print(pred)
print(f'pred: {tf.argmax(pred, axis=1).numpy()}, label: {y_test[0]}') def split_number(img):
result = []
net = build_simple_net()
# 加载模型
net.load_weights(save_path) image = cv2.cvtColor(img.copy(), cv2.COLOR_RGB2GRAY)
ret, thresh = cv2.threshold(image, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, 1, 2)
for cnt in contours[:-1]:
x, y, w, h = cv2.boundingRect(cnt) image = img[y:y+h, x:x+w]
image = cv2.resize(image, (28, 28)) pred_image = tf.convert_to_tensor(image, dtype=tf.float32) / 255.
pred_image = tf.reshape(pred_image, (-1, 28 * 28))
pred = net.predict(pred_image)
out = tf.argmax(pred, axis=1).numpy()
result = [out[0]] + result
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow("demo", img)
print(result)
k = cv2.waitKey(0)
if k == ord('q'):
pass
cv2.destroyAllWindows() if __name__ == '__main__':
if run_train:
train()
elif evaluate_dataset:
test_dataset()
elif image_path:
image = cv2.imread(image_path)
# detect_image(image)
split_number(image)

linux-基于tensorflow2.x的手写数字识别-基于MNIST数据集的更多相关文章

  1. 基于Numpy的神经网络+手写数字识别

    基于Numpy的神经网络+手写数字识别 本文代码来自Tariq Rashid所著<Python神经网络编程> 代码分为三个部分,框架如下所示: # neural network class ...

  2. 手写数字识别——基于LeNet-5卷积网络模型

    在<手写数字识别——利用Keras高层API快速搭建并优化网络模型>一文中,我们搭建了全连接层网络,准确率达到0.98,但是这种网络的参数量达到了近24万个.本文将搭建LeNet-5网络, ...

  3. 【TensorFlow-windows】(四) CNN(卷积神经网络)进行手写数字识别(mnist)

    主要内容: 1.基于CNN的mnist手写数字识别(详细代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3-4.2.0-Windows-x86_64. ...

  4. 【TensorFlow-windows】(三) 多层感知器进行手写数字识别(mnist)

    主要内容: 1.基于多层感知器的mnist手写数字识别(代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3-4.2.0-Windows-x86_64. ...

  5. TensorFlow.NET机器学习入门【5】采用神经网络实现手写数字识别(MNIST)

    从这篇文章开始,终于要干点正儿八经的工作了,前面都是准备工作.这次我们要解决机器学习的经典问题,MNIST手写数字识别. 首先介绍一下数据集.请首先解压:TF_Net\Asset\mnist_png. ...

  6. 基于卷积神经网络的手写数字识别分类(Tensorflow)

    import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_dat ...

  7. 基于多层感知机的手写数字识别(Tensorflow实现)

    import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_dat ...

  8. 吴裕雄--天生自然python机器学习:基于支持向量机SVM的手写数字识别

    from numpy import * def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i ...

  9. 【TensorFlow-windows】(一)实现Softmax Regression进行手写数字识别(mnist)

    博文主要内容有: 1.softmax regression的TensorFlow实现代码(教科书级的代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3 ...

随机推荐

  1. go语言编译过程概述

    go语言编译过程概述 总结自<go语言设计与实现> 名词解释: 中间代码 中间代码是编译器或者虚拟机使用的语言,它可以来帮助我们分析计算机程序.在编译过程中,编译器会在将源代码转换到机器码 ...

  2. 从小白到侠客的 Windows 快捷键宝典

    "天下 武功,唯快不破."你是否羡慕过那些电脑键盘侠客,他们操作起电脑行云流水,任务完成的又快又准.这到底是怎么做到的呢?我们是否也能向他们一样达到把键盘操作熟记于心呢?那就跟着笔 ...

  3. SMTP协议解读以及如何使用SMTP协议发送电子邮件

    电子邮件协议中POP3协议用于接收邮件,SMTP协议用于发送邮件.SMTP的全称为Simple Mail Transfer Protocol,也就是简单邮件传输协议,字如其名.   相较于POP3而言 ...

  4. C++ 类成员指针

    C++的类成员指针是一种奇葩的指针. 假设现在我们要表示一个三维的点,现在有两种定义方式: struct point1{ int x, y, z; }; struct point2{ int c[3] ...

  5. 软件工程-UML各种图总结-精华

    ​ UML(Unified Modeling Language)是一种统一建模语言,为面向对象开发系统的产品进行说明.可视化.和编制文档的一种标准语言.下面将对UML的九种图+包图的基本概念进行介绍以 ...

  6. [AcWing 68] 0到n-1中缺失的数字

    点击查看代码 class Solution { public: int getMissingNumber(vector<int>& nums) { if (nums.empty() ...

  7. 如何改变函数内部 this 的指向

    一.函数内 this 的指向 1. this 的指向是当调用函数时确定的,调用的方式不同,this 的指向也就不同. 1.1 this 一般是指向调用者. 函数类型 this 的指向 普通函数 Win ...

  8. 优化 Docker 镜像大小常见方法

    平时我们构建的 Docker 镜像通常比较大,占用大量的磁盘空间,随着容器的大规模部署,同样也会浪费宝贵的带宽资源.本文将介绍几种常用的方法来优化 Docker 镜像大小,这里我们使用 Docker ...

  9. resultMap,日志,分页

    问题:属性名和字段名不一致 解决方法 起别名 select id, username, password as pwd from db4.user resultMap结果集映射 id username ...

  10. Java学习笔记-基础语法Ⅴ

    学习一些Java常用的API Math:包含执行基本数字运算的方法 如果没有构造方法,一般类的成员都是静态的,通过类名可以直接调用 Java中有两种random函数,Math.Random()函数能够 ...