MNISTのデータファイルをC言語で読み込む

動機

私は現在「ゼロから作るDeep Learning」を読み進めています。しかし、この本ではPythonが使用されています。自分の理解のために、C言語、もしくはC++でこのディープラーニングを実装していきたいというのが動機です。

MNISTとは

機械学習の分野でよく用いられている数字の画像のデータセットです。
以下のページで公開されています。
MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges

MNISTのデータ書式

上記ページの "FILE FORMATS FOR THE MNIST DATABASE" で説明されています。
それによると、以下のような書式です。(3次元データの場合)

  • 最初の2バイト:マジックナンバー 0x0000
  • 次の1バイト:1要素のバイト数の情報。0x8なら1要素=1バイト
  • 次の1バイト:次元数。3なら3次元。
  • 次の4バイト:次元0のサイズ
  • 次の4バイト:次元1のサイズ
  • 次の4バイト:次元2のサイズ
  • 残り:データ(次元0×次元1×次元2のバイト数)

Stirlingなどのバイナリエディタで見ると、確かにそのような書式になっています。
f:id:kenjiwn:20170709200226p:plain

また、"Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black)." と記載されています。
これは通常の画像形式とは逆なのでこれに従うのであれば反転が必要です。

これらを踏まえて、MNISTの画像をPGM形式に変換するプログラムをC言語で記述してみました。

github.com

出力されたPGMファイルをIrfanViewなどのビュアーで見ると、確かに数字っぽい画像が出現してきます。
f:id:kenjiwn:20170709201139p:plain

ついでに、ラベルデータをテキストで出すプログラムも作りました。

github.com

実行すると以下のような出力がされており、画像とラベルデータが一致していることが目視で確認できます。

50419213143536172869
40911243273869056076
18793985933074980941
44604561001716302117
90267839046746807831
57171163029311049200
20271864163459133854
77428586734619960372
82944649709295159123
23591762822507497832
11836103100172730465
26471899307102035465
86375809103122336475
06279859211445641253
93905965741340480436
87609757211689415229
03967203543658954742
73489192879187413110
23949216847744925724
42197287692238165110