使用javascript / node.js读取MNIST数据集

时间:2014-07-29 20:16:23

标签: javascript node.js neural-network mnist

我尝试解码此来源的数据集:http://yann.lecun.com/exdb/mnist/

有一个非常简单的描述" IDX文件类型在底部,但我无法弄明白。

我想要达到的目标是:

var imagesFileBuffer = fs.readFileSync(__dirname + '/train-images-idx3-ubyte');
var labelFileBuffer  = fs.readFileSync(__dirname + '/train-labels-idx1-ubyte');
var pixelValues      = {};

魔术

pixelValues现在就像:

// {
//   "0": [0,0,200,190,79,0... for all 784 pixels ... ],
//   "4": [0,0,200,190,79,0... for all 784 pixels ... ],

等用于数据集中的所有图像条目。我试图找出二进制文件的结构,但失败了。

2 个答案:

答案 0 :(得分:9)

我意识到在pixelValues对象的结构中会有重复的键,所以我创建了一个对象数组。以下代码将创建我之后的结构:

var dataFileBuffer  = fs.readFileSync(__dirname + '/train-images-idx3-ubyte');
var labelFileBuffer = fs.readFileSync(__dirname + '/train-labels-idx1-ubyte');
var pixelValues     = [];

// It would be nice with a checker instead of a hard coded 60000 limit here
for (var image = 0; image <= 59999; image++) { 
    var pixels = [];

    for (var x = 0; x <= 27; x++) {
        for (var y = 0; y <= 27; y++) {
            pixels.push(dataFileBuffer[(image * 28 * 28) + (x + (y * 28)) + 15]);
        }
    }

    var imageData  = {};
    imageData[JSON.stringify(labelFileBuffer[image + 8])] = pixels;

    pixelValues.push(imageData);
}

pixelValues的结构现在是这样的:

[
    {5: [28,0,0,0,0,0,0,0,0,0...]},
    {0: [0,0,0,0,0,0,0,0,0,0...]},
    ...
]

有28x28 = 784个像素值,均在0到255之间变化。

要渲染像素,请像上面一样使用我的for循环,渲染左上角的第一个像素,然后向右移动。

答案 1 :(得分:1)

只是一个小小的改进:

for (var image = 0; image <= 59999; image++) {

60000在pixelValues的最后有一个带“null”的“条目”。

修改

我对细节有点痴迷,因为我想将MNIST数据集转换回真实和单独的图像文件。所以我在你的代码中发现了更多的错误。

  1. 肯定是+16,因为你必须跳过16字节的标题数据。这个小错误反映在你的答案中,第一个数字的第一个像素值(带有5)是'28'。这实际上是指示图像有多少列的值 - 而不是图像的第一个像素。

  2. 您的嵌套for循环必须从里到外翻转才能获得正确的像素顺序 - 假设您将从左上角到右下角“重建”您的图像。使用您的代码,图像将沿着从左上角到右下角的轴进行翻转。

  3. 所以你的代码应该是:

    var dataFileBuffer  = fs.readFileSync(__dirname + '/train-images-idx3-ubyte');
    var labelFileBuffer = fs.readFileSync(__dirname + '/train-labels-idx1-ubyte');
    var pixelValues     = [];
    
    // It would be nice with a checker instead of a hard coded 60000 limit here
    for (var image = 0; image <= 59999; image++) { 
        var pixels = [];
    
        for (var y = 0; y <= 27; y++) {
            for (var x = 0; x <= 27; x++) {
                pixels.push(dataFileBuffer[(image * 28 * 28) + (x + (y * 28)) + 16]);
            }
        }
    
        var imageData  = {};
        imageData[JSON.stringify(labelFileBuffer[image + 8])] = pixels;
    
        pixelValues.push(imageData);
    }
    

    如果您保持一致并使用这些提取的数据来训练神经网络,那些小细节就不会成为问题,因为您将对测试数据集做同样的事情。但是如果你想接受MNIST训练的神经网络并尝试用现实生活中的手写数字来验证它,你会得到不好的结果,因为真实的图像没有被翻转。