[numpy]利用softmaxANN训练mnist数据集
mnist数据集
下载数据集
直接点yann的homepage就可以下载,还有详细的介绍。
-
一共有四个文档,分别是:
-
训练集图片
训练集标签
测试集图片
测试集标签
注意:不要让浏览器自行解压了下载的文件(对比一下下载的文件与网页内所示文件大小是否一致)。下载的时候去掉 “.gz” 扩展名可以解决。
导出数据集
- 解压文件到某个目录
- 写一个简单的代码把文件内容提取出来
所以看一下网页上对文件格式的描述,根据格式提取文件。
先看一下训练集标签的格式。
-
TRAINING SET LABEL FILE (train-labels-idx1-ubyte):
- [offset] [type] [value] [description]
- 0000 32 bit integer 0x00000801(2049) magic number (MSB first)
- 0004 32 bit integer 60000 number of items
- 0008 unsigned byte ?? label
- 0009 unsigned byte ?? label
- …
- xxxx unsigned byte ?? label
The labels values are 0 to 9.
offset指byte数。0位是magicNumber, 4位是60000(个数),8位开始后面全部是标签(0 - 9), 一共60000个。
- 本文使用 struct.unpack_from() 函数提取文件数据。
此处需要 import struct 包。
def load_train_labels(path):
'''
Argument:
path -- path of file
Returns:
num_images -- number of items
train_Y_orig -- original dataset extracted from file
'''
# 'rb'模式打开文件
with open(path, 'rb') as file_handle:
# 读取文件
buf = file_handle.read()
# index 用来记录目前读取到了第几位
index = 0
# 使用 struct 包的 unpack_from 函数提取文件内容
# '>' 表示大数记法,'I' 表示 32bit unsigned integer
# 根据格式中记录 magic_number 和 number_of_items 都是 32bit
# unsighed interger 类型, 所以unpack_from接收的第一个位置参数
# 是 '>II'
magic, num_images= struct.unpack_from('>II', buf, index)
# index 增加相应的字节数
index += struct.calcsize('>II')
# 'B' 表示 byte 类型, str(num_images) 表示共有60000 byte
fmt = '>' + str(num_images) + 'B'
train_Y_orig = struct.unpack_from(fmt, buf, index)
return num_images, train_Y_orig
关于 struct.unpack_from 相关内容点这里。
对于训练集图片,根据文件格式代码如下:
def load_train_images(path):
with open(path, 'rb') as file_handle:
buf = file_handle.read()
index = 0
magic, num_images, num_X, num_Y = struct.unpack_from('>IIII', buf, index)
index += struct.calcsize('>IIII')
fmt = '>' + str(num_images * num_X * num_Y) + 'B'
train_X_orig = struct.unpack_from(fmt, buf, index)
return num_images, num_X, num_Y, train_X_orig
以上两个函数也可以用在测试集文件上,由于命名原因只写了train。
- 把以上两个函数整合为一个函数,并处理为 numpy array。
此处需要 import numpy 包。
import numpy as np
def extract_file():
# 设置文件路径
train_images_path = 'data/train-images-idx3-ubyte'
train_labels_path = 'data/train-labels-idx1-ubyte'
# 调用上面定义的函数
num_images, num_X, num_Y, train_X_orig = load_train_images(train_images_path)
num_images, train_Y_orig = load_train_labels(train_labels_path)
# 先转化为numpy array,再reshape为vector
# 对于图片集,每一列是一张图片,一共60000列
# 对于标签集,每一列是一个标签,一共60000列
X = np.array(train_X_orig).reshape(num_images, -1).T
Y = np.array(train_Y_orig).reshape(-1, num_images)
return X, Y
此处可以用 plt.imshow() 检测图片是否能正确显示。因为reshape的时候有可能会将原有的像素顺序打乱。
处理数据集(preprocessing)
- 因为所有像素都是 (0 - 255) ,所以本文直接令所有像素点除以 255 得到一个小于 1 的值。
- 神经网络最后的输出层的节点为 10 个,各节点有一个输出,为 (10,1) 的numpy array, 所以要把标签集 Y 处理为同样形式的 numpy array。
把标签集数字对应的索引位置的值设为1, 其他全为0。以下为两个例子:
此处需要 import numpy 包。
def initialize_dataset(train_X_orig, train_Y_orig):
'''
set a (10, 60000) array to represent value of number in train_Y by (10, 1) array,
with which the posistion of the value refering to will be attributed to 1, others all 0
'''
X = train_X_orig / 255
Y_10 = np.zeros((10, train_Y_orig.shape[1