使用javascript/node.js读取MNIST数据集
Reading MNIST dataset with javascript/node.js
我正在尝试从这个来源解码数据集: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 ... ],
等对于数据集中的所有图像条目。我试图找出二进制文件的结构,但失败了。
我意识到在我的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);
}
像素值的结构现在是这样的:
[
{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循环,渲染左上角的第一个像素,然后向右工作。
只是一个小小的改进:
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训练的神经网络来验证真实的手写数字,你会得到不好的结果,因为真实的图像没有翻转。
@Lilleman的代码非常有帮助。这是一个经过清理的版本,更新到ES6,并作为函数实现。如前所述,原始代码以错误的顺序将字节放在一起,因此图像逆时针旋转90度。这段代码修复了这个问题,并且循环直到读取所有数据,而不是硬编码最大图像计数。
const os = require('os');
const fs = require('fs');
function load(labelsFilePath, imagesFilePath) {
const labelsFileBuffer = fs.readFileSync(labelsFilePath);
const dataFileBuffer = fs.readFileSync(imagesFilePath);
const pixelValues = [];
let image = 0;
while(true) {
const imageData = {};
const label = labelsFileBuffer[image + 8];
const pixels = [];
if(typeof label == 'undefined') {
break;
}
for(let x=0; x<=27; x++) {
for(let y=0; y<=27; y++) {
pixels.push(dataFileBuffer[(image * 28 * 28) + (x * 28 + y) + 15]);
}
}
imageData[label] = pixels;
pixelValues.push(imageData);
image += 1;
}
return pixelValues;
}
// sample usage:
const mnist = load(
`${os.homedir()}/Downloads/train-labels.idx1-ubyte`,
`${os.homedir()}/Downloads/train-images.idx3-ubyte`
);
console.log(mnist);
希望这能帮助到一些人,我添加了将图像保存为png格式的功能。请注意,您需要有一个图像目录
var fs = require('fs');
const {createCanvas} = require('canvas');
function readMNIST(start, end)
{
var dataFileBuffer = fs.readFileSync(__dirname + '''test_images_10k.idx3-ubyte');
var labelFileBuffer = fs.readFileSync(__dirname + '''test_labels_10k.idx1-ubyte');
var pixelValues = [];
for (var image = start; image < end; 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["index"] = image;
imageData["label"] = labelFileBuffer[image + 8];
imageData["pixels"] = pixels;
pixelValues.push(imageData);
}
return pixelValues;
}
function saveMNIST(start, end)
{
const canvas = createCanvas(28, 28);
const ctx = canvas.getContext('2d');
var pixelValues = readMNIST(start, end);
pixelValues.forEach(function(image)
{
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var y = 0; y <= 27; y++)
{
for (var x = 0; x <= 27; x++)
{
var pixel = image.pixels[x + (y * 28)];
var colour = 255 - pixel;
ctx.fillStyle = `rgb(${colour}, ${colour}, ${colour})`;
ctx.fillRect(x, y, 1, 1);
}
}
const buffer = canvas.toBuffer('image/png')
fs.writeFileSync(__dirname + `''images''image${image.index}-${image.label}.png`, buffer)
})
}
saveMNIST(0, 5);
- 从桌面读取python文件时高亮显示代码
- Javascript-如何读取json文件中的列并将其保存在Javascript数组中
- 使用Dnamics CRM 2011中的JavaScript读取子网格的所有记录,而不考虑活动页面
- 节点Js:How to catch a“;没有这样的文件或目录“;读取线模块出错
- TypeError:无法读取属性'推'未定义的JavaScript
- 同样,同样的错误'ahorcado.js:26未捕获类型错误:无法读取属性'beginPath'
- 未捕获的TypeError无法读取未定义的属性socialsharing
- 如何在读取XLS/XLSX本地文件时,使用IE的javascript代码启用未标记为安全的ActiveX控件
- 字符串在将其传递给另一个活动Android JavaScript时读取Null
- NodeJS-readline暂停和恢复事件发射器(逐行读取)
- 未捕获的类型错误:无法读取属性'删除'的未定义
- AngularJS指令出错-无法读取属性'编译'的未定义
- 未捕获的类型错误:无法读取属性'name'即使它存在,也无法定义
- 如何在Javascript中读取unsigned int
- 如何读取表单中的输入数据
- 通过传递图像的URL通过javascript读取/处理图像-类似于PHP中的file_get_contents
- 看到“;未捕获的类型错误:无法读取属性'weight'未定义的“;尽管按照字面上的指示
- angularjs无法读取未定义的属性then
- 正在读取JSON,数据未显示
- 使用javascript/node.js读取MNIST数据集