我尝试解码此来源的数据集: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 ... ],
等用于数据集中的所有图像条目。我试图找出二进制文件的结构,但失败了。
答案 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数据集转换回真实和单独的图像文件。所以我在你的代码中发现了更多的错误。
肯定是+16,因为你必须跳过16字节的标题数据。这个小错误反映在你的答案中,第一个数字的第一个像素值(带有5)是'28'。这实际上是指示图像有多少列的值 - 而不是图像的第一个像素。
您的嵌套for循环必须从里到外翻转才能获得正确的像素顺序 - 假设您将从左上角到右下角“重建”您的图像。使用您的代码,图像将沿着从左上角到右下角的轴进行翻转。
所以你的代码应该是:
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训练的神经网络并尝试用现实生活中的手写数字来验证它,你会得到不好的结果,因为真实的图像没有被翻转。