FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

ニューラルネットワーク C/C++ 実装の検討 (2. MNISTのロード)

MNISTのデータは一般に誰でも手に入れることができる。 TensorFlowやCNTK, 「ゼロから作るディープラーニング」の書籍などでは、インターネットからMNISTのデータを直接ロードしてくる手法が用意されており、初心者でも簡単にMNISTを試すことができるような環境が整えられている。

一方で、C言語フルスクラッチでネットワークを構成する場合、どうやってMNISTを取ってくればよいのだろう。 普通に考えて、ファイルをダウンロードして読み込むのがよいと思われる。MNISTのファイルは以下でダウンロードした。

MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges

ファイルフォーマットは以下のようになっている。つまり、トレーニングデータの場合、最初の8バイトは捨ててしまい、そこから先にデータが存在する。

f:id:msyksphinz:20170623010954p:plain

次に、トレーニングデータのラベル(解答)は最初の2バイトを捨てるのでよかろう。

これを一旦全部メモリにロードしてもよいのだが、マイコン等で走らせるときにメモリ不足になるのはあまり嬉しくないので、とりあえずファイルから処理するたびに1つずつロードするようにした。 print_images()を作ってロードしたファイルを表示してみると、正常にロードできていることが確認できる。

f:id:msyksphinz:20170623010632p:plain

とりあえずMNISTデータをロードしてネットワークを通過させるところまでは完成したのだが、まだ学習をしていないので、認識精度は10%程度だ。まあ、偶然の確率と一致する。 これからBackwardのネットワークを実装して、学習するように構築しなければ。。。

github.com

#define IMAGE_FILE "train-images-idx3-ubyte"
#define LABEL_FILE "train-labels-idx1-ubyte"

int open_image ()
{
  int fd;
  if ((fd = open(IMAGE_FILE,O_RDONLY))==-1){
    printf("couldn't open image file");
    exit(0);
  }

  unsigned char *ptr; 
  static int num[10];
  read(fd, num, 4 * sizeof(int)); 
    
  for (int i = 0; i < 4; i++) { 
    ptr = (unsigned char *)(num + i);
    FlipLong( ptr);
    printf("%d\n", num[i]);
    ptr = ptr + sizeof(int);
  }

  return fd;
}


int open_label ()
{
  int fd;
  if ((fd = open(LABEL_FILE,O_RDONLY))==-1){
    printf("couldn't open image file");
    exit(0);
  }

  unsigned char *ptr; 
  static int num[10];
  read(fd, num, 2 * sizeof(int)); 

  for (int i = 0; i < 2; i++) { 
    ptr = (unsigned char *)(num + i);
    FlipLong( ptr);
    printf("%d\n", num[i]);
    ptr = ptr + sizeof(int);
  }
  
  return fd;
}