4 手写数字识别
手写数字识别通常使用MNIST数字图像集合,MNIST是机器学习领域最有名的数据集之一,同时针对MNIST的识别算法相当于AI算法领域的Hello World!
4.1 关于MNIST数据
MINST的图像数据是28x28像素的灰度图像(1个通道),每个像素的取值在0到255之间。同时,每个图像都有对应数字的标签。
整个数据集包含6万个训练数据和1万个测试数据,具体数据集可在http://yann.lecun.com/exdb/mnist/ 下载。
其中包含4个压缩文件,分别解压后会得到如下4个文件:
train-images.idx3-ubyte , 训练数据的图像集合
train-labels.idx1-ubyte , 训练数据的标签集合
t10k-images.idx3-ubyte , 测试数据的图像集合
t10k-labels.idx1-ubyte , 测试数据的标签集合
数据文件的具体内容可参考上述网站,以train-images.idx3-ubyte为例:
[offset] [type] [value] [description]
0000 32 bit integer 0x00000803(2051) magic number
0004 32 bit integer 60000 number of images
0008 32 bit integer 28 number of rows
0012 32 bit integer 28 number of columns
0016 unsigned byte ?? pixel
0017 unsigned byte ?? pixel
........
xxxx unsigned byte ?? pixel
前面的四个32位整型数分别为Magic Number,图片数量,图片的高度和宽度;
从第16个byte开始,就是图片的数据,每784(28x28)个byte为一个图片,连续存放。
标签文件的存储内容与之类似,但是不存储图片,只存储图片的标签,即图片对应的真实数字,因此文件小了很多。
以下Python代码展示了从图片训练数据中随机读取一个图片并显示出来的方法:
import os
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
dataset_dir = os.path.dirname(os.path.abspath(__file__))
train_img_file = dataset_dir + "\\train-images.idx3-ubyte"
train_lable_file = dataset_dir + "\\train-labels.idx1-ubyte"
print(train_img_file, train_lable_file)
def reset_to_int32(num):
return num[0]<<24 | num[1]<<16 | num[2]<<8 | num[3]
def img_file_info(img_file):
with open(img_file, "rb") as f:
magic_num = np.frombuffer(f.read(4), dtype=np.uint8)
img_count = np.frombuffer(f.read(4), dtype=np.uint8)
row_count = np.frombuffer(f.read(4), dtype=np.uint8)
col_count = np.frombuffer(f.read(4), dtype=np.uint8)
img_data = np.frombuffer(f.read(), dtype=np.uint8)
magic_num = reset_to_int32(magic_num)
img_count = reset_to_int32(img_count)
row_count = reset_to_int32(row_count)
col_count = reset_to_int32(col_count)
print(magic_num, img_count, row_count, col_count, img_data)
print(img_data.shape)
return magic_num, img_count, row_count, col_count, img_data
def lable_file_info(lable_file):
with open(lable_file, "rb") as f:
magic_num = np.frombuffer(f.read(4), dtype=np.uint8)
lable_count = np.frombuffer(f.read(4), dtype=np.uint8)
lable_data = np.frombuffer(f.read(), dtype=np.uint8)
magic_num = reset_to_int32(magic_num)
lable_count = reset_to_int32(lable_count)
print(lable_data.shape)
return magic_num, lable_count, lable_data
_, img_count, row_count, col_count, img_data = img_file_info(train_img_file)
_, lable_count, lable_data = lable_file_info(train_lable_file)
if(img_count != lable_count):
print("There must be something wrong!!!")
exit()
img_data = img_data.reshape(img_count, row_count*row_count)
idx = np.random.randint(img_count)
print(idx)
rand_img = img_data[idx].reshape(row_count, col_count)
plt.imshow(rand_img)
plt.title("Index "+str(idx)+" : "+str(lable_data[idx]))
plt.show()
4.2 前向传播
以MNIST数据中的图片信息作为输入,通过W、B矩阵以及激活函数的运算判断出的输入图片是什么数字。这里需要用到几层神经网络,图片信息上每一个像素点的信息都将通过每一层神经网络的运算,最终对结果产生影响,这个过程就是神经网络的前向传播算法。
4.3 神经网络的学习
神经网络的学习是指从训练数据中自动获取最优权重参数的过程