mnist数据集及其读写格式
1. mnist 数据集
mnist数据是手写的数字0-9的数据集,共包含训练集60000个样本和测试集10000个样本。mnist是NIST的子集,同时mnist将全部图片统一了尺寸大小,同时将所有图片放置了在图片中心。
mnist有四个包:
train-images-idx3-ubyte.gz:
training set images (9912422 bytes)train-labels-idx1-ubyte.gz:
training set labels (28881 bytes)t10k-images-idx3-ubyte.gz:
test set images (1648877 bytes)t10k-labels-idx1-ubyte.gz:
test set labels (4542 bytes)
将来自NIST的原始黑白(双水平)图像尺寸标准化为适合20x20像素的框,同时保留其长宽比。作为归一化算法使用的抗锯齿技术的结果,所得图像包含灰度级。通过计算像素的质心并平移图像以将该点定位在28x28场的中心,从而将图像定位在28x28图像的中心。
使用某些分类方法(尤其是基于模板的方法,例如SVM和K最近邻),当数字以边界框而不是质心为中心时,错误率会提高。如果进行这种预处理,则应在出版物中进行报告。
MNIST数据库由NIST的特殊数据库3和特殊数据库1构成,其中包含手写数字的二进制图像。 NIST最初将SD-3指定为训练集,将SD-1指定为测试集。但是,SD-3比SD-1更干净,更容易识别。可以从SD-3是在人口普查局员工中收集而SD-1是在高中学生中收集的事实中找到其原因。从学习实验中得出明智的结论,要求结果独立于完整样本集中训练集和测试的选择。因此,有必要通过混合NIST的数据集来构建新的数据库。
MNIST训练集由SD-3的30,000个模式和SD-1的30,000个模式组成。我们的测试集由SD-3的5,000个模式和SD-1的5,000个模式组成。 60,000种模式训练集包含来自大约250位作者的示例。我们确保训练集和测试集的作者集不相交。
SD-1包含由500位不同作者编写的58,527位数字图像。与SD-3不同,在SD-3中,来自每个写入器的数据块按顺序出现,而SD-1中的数据则被加密。 SD-1的写入者身份可用,我们使用此信息来对写入者进行解读。然后,我们将SD-1分为两部分:由前250位作者编写的字符进入了我们的新培训集。其余的250名作者被放置在我们的测试集中。因此,我们有两组,每组有近30,000个示例。新的训练集已完成,其中包含来自SD-3的足够示例(从模式0开始),从而形成了60,000套完整的训练模式。同样,新的测试集以SD-3示例(模式编号为35,000)完成,从而构成了具有60,000个测试模式的全套设备。此站点上仅提供10,000个测试图像的子集(SD-1提供了5,000个,SD-3提供了5,000个)。完整的60,000个样本训练集可用。
此训练集和测试集已经测试了许多方法。这里有一些例子。有关方法的详细信息将在即将发表的论文中给出。这些实验中的一些实验使用了一个数据库版本,其中输入图像进行了歪斜校正(通过计算最接近垂直方向的形状的主轴,并移动直线使其垂直)。在其他一些实验中,训练集增加了原始训练样本的人为扭曲版本。失真是移位,缩放,倾斜和压缩的随机组合。
注: 以上部分摘自谷歌翻译
2. idx 数据格式
IDX数据的格式如下,此处以大端格式为例
注: 大小端区分如下图,假设有一个4字节的数字0x12345678,则其大小端存放方式如下:
方式 | 0000 | 0001 | 0002 | 0003 |
---|---|---|---|---|
大端 | 0x12 | 0x34 | 0x56 | 0x78 |
小端 | 0x78 | 0x56 | 0x34 | 0x12 |
IDX文件格式:
[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 |
idx文件分为三部分
- magic num:占4个字节,规定了数据是大端存放还是小端存放,参数的个数,以及数据格式及所占字节数
- 参数:说明了数据的维度,以及每一维的大小
- 数据:存储数据的部分
再以大端模式存储时,magic的前两个字节一般为0,
第三个字节表示数据类型,第四个字节表示参数个数
- 0x08: unsigned byte
- 0x09: signed byte
- 0x0B: short (2 bytes)
- 0x0C: int (4 bytes)
- 0x0D: float (4 bytes)
- 0x0E: double (8 bytes)
根据以上信息得到的idx文件python解析源码为
#!/usr/bin/env python3
import struct as st
# change data mode
# f : the obj of binary file
# size: the length of reading
# mode : st.unpack fmt
def getData(f,size,mode):
tmp = f.read(size)
tmp = st.unpack(mode,tmp)
tmp = tmp[0]
return tmp
# get the data types of the data
def getDataTpe(dataTypeCode):
if dataTypeCode == 0x08:
dataTypeSize = 1
dataType = 'B'
elif dataTypeCode == 0x09:
dataTypeSize = 1
dataType = 'b'
elif dataTypeCode == 0x0B:
dataTypeSize = 2
dataType = 'h'
elif dataTypeCode == 0x0C:
dataTypeSize = 4
dataType = 'i'
elif dataTypeCode == 0x0D:
dataTypeSize = 4
dataType = 'f'
elif dataTypeCode == 0x0E:
dataTypeSize = 8
dataType = 'd'
return dataTypeSize,dataType
# processor the type of the data
def getIdxDataFromFile(fileName):
with open(fileName,mode='rb') as f:
isHighCode = getData(f, 2, '>H')
isHigh = ">"
if isHighCode == 0:
isHigh = ">"
dataTypeCode = getData(f,1,isHigh+'B' ) # idx type of the data
dataDim = getData(f,1,isHigh+'B')
else:
isHigh = "<"
dataDim = getData(f,1,isHigh+'B')
dataTypeCode = getData(f,1,isHigh+'B' ) # idx type of the data
s = 1
for i in range(dataDim): # get the num of every dim
tmp = getData(f,4,isHigh+'i')
s = s*tmp
dataDimNum.append(tmp)
# get the type and size of the data
dataTypeSize,dataType = getDataTpe(dataTypeCode)
for i in range(s):# get the data
tmp = getData(f,dataTypeSize,isHigh+dataType)
data.append(tmp)
return dataDimNum,data,dataType
参考文献
[1] http://yann.lecun.com/exdb/mnist/
[2] 谷歌翻译