You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MNIST数据集IDX转像素矩阵时数值全部右移的问题求助

MNIST IDX格式转像素矩阵出现右移问题排查

在探索神经网络与机器学习时,使用MNIST手写数字数据集,将IDX格式文件转换为神经网络可输入的像素矩阵时,所有数值出现右移现象(附效果截图)。以下是转换代码及问题分析:

原转换代码

const fs = require("fs");
const { hex_to_decimal } = require("../utils/hex_to_decimal");

function read_idx_file(path) {
  return new Promise(function (resolve, reject) {
    fs.readFile(path, (err, data) => {
      if (err) {
        console.log(err.message);
        reject(err.message);
      }
      resolve(data);
    });
  });
}

function input_into_json(data, path) {
  return new Promise(function (resolve, reject) {
    fs.writeFile(path, data, {}, (err) => {
      if (err) reject(err.message);
      else resolve();
    });
  });
}

// inputting training-images into json file
read_idx_file("../samples/unzipped/train-images.idx3-ubyte")
  .then((data) => {
    const output = [];
    let temp_row_arr = [];
    let temp_col_arr = [];
    let temp_index = 8;
    while (data[temp_index] !== undefined) {
      for (let i = temp_index; i - temp_index < 28; i++) {
        temp_row_arr.push(hex_to_decimal(data[i]));
      }
      temp_index += 28;
      temp_col_arr.push(temp_row_arr);
      temp_row_arr = [];
      if (temp_col_arr.length === 28) {
        output.push(temp_col_arr);
        temp_col_arr = [];
      }
    }
    input_into_json(
      JSON.stringify(output),
      "../samples/json/training-images.json"
    );
  })
  .then(() => console.log("done"))
  .catch((err) => console.log(err));

IDX格式说明(中文翻译)

IDX文件格式用于存储向量与多维矩阵,结构如下:

  1. 文件头由多个32位大端(big-endian)整数组成:
    • 前两个字节为填充值0
    • 第三个字节表示数据类型:
      • 0x08:无符号字节(对应MNIST像素的0-255灰度值)
      • 0x09:有符号字节
      • 0x0B:16位短整数
      • 0x0C:32位整数
      • 0x0D:32位单精度浮点数
      • 0x0E:64位双精度浮点数
    • 第四个字节表示数据维度数(如向量为1维,图像矩阵为2维)
  2. 后续每个32位大端整数对应各维度的大小
  3. 文件头之后是实际数据,按维度顺序排列,数据元素的大小与类型由文件头指定

针对MNIST的train-images.idx3-ubyte,文件头包含4个32位整数(共16字节):

  • 第0-3字节:魔术数(固定为0x00000803,标识无符号字节类型的3维数据)
  • 第4-7字节:图像总数量
  • 第8-11字节:单图像行数(固定为28)
  • 第12-15字节:单图像列数(固定为28)
  • 第16字节及之后:每个图像的28×28字节像素数据

问题原因分析

  1. 文件头跳过长度错误:原代码从索引8开始读取数据,错误地将文件头中第8-15字节(行数、列数字段,共8字节)当成了第一个图像的前8个像素,导致所有图像数据整体偏移,显示时出现右移现象。
  2. 多余的数值转换:Buffer对象通过索引访问时,返回的已经是0-255的十进制灰度值,调用hex_to_decimal函数属于画蛇添足——若该函数将数字当作十六进制字符串处理,会导致数值错误(比如十进制10被转成十六进制10对应的十进制16),进一步加剧显示异常。

修正后的代码

const fs = require("fs");

function read_idx_file(path) {
  return new Promise(function (resolve, reject) {
    fs.readFile(path, (err, data) => {
      if (err) {
        console.log(err.message);
        reject(err.message);
      }
      resolve(data);
    });
  });
}

function input_into_json(data, path) {
  return new Promise(function (resolve, reject) {
    fs.writeFile(path, data, {}, (err) => {
      if (err) reject(err.message);
      else resolve();
    });
  });
}

// 处理训练图像转JSON
read_idx_file("../samples/unzipped/train-images.idx3-ubyte")
  .then((data) => {
    const output = [];
    // MNIST图像文件头共16字节,从索引16开始读取像素数据
    let temp_index = 16;
    // 从文件头读取总图像数(大端字节序)
    const totalImages = data.readUInt32BE(4);
    const imageWidth = 28;
    const imageHeight = 28;

    for (let i = 0; i < totalImages; i++) {
      const image = [];
      for (let row = 0; row < imageHeight; row++) {
        const pixels = [];
        for (let col = 0; col < imageWidth; col++) {
          // 直接取Buffer中的十进制灰度值
          pixels.push(data[temp_index]);
          temp_index++;
        }
        image.push(pixels);
      }
      output.push(image);
    }

    return input_into_json(
      JSON.stringify(output),
      "../samples/json/training-images.json"
    );
  })
  .then(() => console.log("done"))
  .catch((err) => console.log(err));

内容的提问来源于stack exchange,提问作者maxovic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:27:27