Ruby で MNIST 手書き文字データを扱う


PRML Hackathon #1 参加中。
はやくもプチ煮詰まり中(ぉぃ)。


Ruby で書いている人は他にいなさそうだが、気晴らしに RubyMNIST データを扱うためのコード片を さらしてみる。

require 'zlib'

n_rows = n_cols = nil
images = []
labels = []
Zlib::GzipReader.open('train-images-idx3-ubyte.gz') do |f|
  magic, n_images = f.read(8).unpack('N2')
  raise 'This is not MNIST image file' if magic != 2051
  n_rows, n_cols = f.read(8).unpack('N2')
  n_images.times do
    images << f.read(n_rows * n_cols)
  end
end

Zlib::GzipReader.open('train-labels-idx1-ubyte.gz') do |f|
  magic, n_labels = f.read(8).unpack('N2')
  raise 'This is not MNIST label file' if magic != 2049
  labels = f.read(n_labels).unpack('C*')
end

補足。

  • データは http://yann.lecun.com/exdb/mnist/ からダウンロードして、gz のままカレントに転がしておけばOK
  • n_rows, n_cols に画像の縦横の大きさが入る
  • images[idx] にイメージデータが、labels[idx] にその正解(0〜9) が入る。
  • イメージデータはでかいので(45MB)、バイナリのまま保持。実際に使うときに unpack で配列に展開。
  image = images[idx].unpack('C*')  # 要素数 784 の配列に変換(=28x28)
  • 展開した配列には 0(白)〜255(黒) のグレイスケールがピクセルごとに格納
  • テストデータも同じ形式なので、同コードで読み込み可能。