MNISTのWebサイトで配布されている手書き数字のデータは、バイナリ形式です。これを、JSONデータに変換する方法をメモしました。
DBをダウンロードして、解凍します。
mnistdb2json.js
// MNIST手書きデータをJSONに変換する for Node.js
const CONV_LIMIT = 5000 // 小さなJSONを作成する場合
// サンプルファイルの保存先を指定
var DIR_IMAGE = __dirname + "/image";
// モジュールの取り込み
var fs = require('fs');
// 変換処理
convertToJSON("train");
convertToJSON("t10k");
function convertToJSON(basename) {
console.log("convert: " + basename);
// 各種ファイル名を決定
var file_images = basename + "-images-idx3-ubyte";
var file_labels = basename + "-labels-idx1-ubyte";
var file_csv = basename + ".json";
// ファイルを開く
var f_img = fs.openSync(file_images, "r");
var f_lbl = fs.openSync(file_labels, "r");
// var f_out = fs.openSync(file_csv, "w+");
if (!fs.existsSync(DIR_IMAGE)) {
fs.mkdirSync(DIR_IMAGE);
}
// ヘッダを読む
var buf_i = new Buffer(16);
fs.readSync(f_img, buf_i, 0, buf_i.length);
var buf_l = new Buffer(8);
fs.readSync(f_lbl, buf_l, 0, buf_l.length);
// ヘッダをチェック
var magic = buf_i.readUInt32BE(0);
var num_images = buf_i.readUInt32BE(4);
var num_rows = buf_i.readUInt32BE(8);
var num_cols = buf_i.readUInt32BE(12);
var num_size = num_rows * num_cols;
if (magic != 0x803) {
console.error("[ERROR] Broken file=", magic.toString(16));
process.exit();
}
console.log("num_of_images=" + num_images);
console.log("num_of_rows=" + num_rows);
console.log("num_of_cols=" + num_cols);
console.log("num_of_pixel_size=" + num_size);
// 画像を取り出す
var buf_img = new Buffer(num_size);
var buf_lbl = new Buffer(1);
var mini_csv = "";
var labels = [];
var datas = [];
for (var i = 0; i < num_images; i++) {
// 経過を表示
if (i % 1000 == 0) console.log( i + "/" + num_images );
if (i > CONV_LIMIT) break;
// 画像を読む
var pos_i = i * num_size + 16;
fs.readSync(f_img, buf_img, 0, num_size, pos_i);
// ラベルを読む
var pos_l = i * 1 + 8;
fs.readSync(f_lbl, buf_lbl, 0, 1, pos_l);
var no = buf_lbl[0];
// PGM形式として保存 (テスト用)
if (i < 30) {
var s = "P2 28 28 255\n";
for (var j = 0; j < 28 * 28; j++) {
s += buf_img[j] + " ";
s += (j % 28 == 27) ? "\n" : "";
}
var img_file =
DIR_IMAGE + "/" + basename +
"-" + i + "-" + no + ".pgm";
fs.writeFileSync(img_file, s, "utf-8");
}
// CSVとして保存
var cells = [];
for (var j = 0; j < 28 * 28; j++) {
const v = Math.floor(buf_img[j] / 255 * 100) / 100
cells.push(v);
}
labels.push(no)
datas.push(cells)
}
var obj = {"label":labels, "data":datas}
fs.writeFileSync(file_csv, JSON.stringify(obj), "utf-8")
console.log("ok:" + basename);
}