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,则其大小端存放方式如下:

方式0000000100020003
大端0x120x340x560x78
小端0x780x560x340x12

IDX文件格式:

[offset][type][value][description]
000032 bit integer0x00000801(2049)magic number (MSB first)
000432 bit integer60000number of items
0008unsigned byte??label
0009unsigned byte??label
xxxxunsigned 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] 谷歌翻译


版权声明:本文为New_Leaf原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。