MNIST画像情報を読み込む
MNIST画像情報をPerlで読み込むサンプルプログラムです。MNISTは、ディープラーニングで利用できる画像のサンプルです。
THE MNIST DATABASE of handwritten digitsを読み込むサンプルです。
use strict;
use warnings;
use FindBin;
# MNIST画像情報を読み込む
my $mnist_image_file = "$FindBin::Bin/data/train-images-idx3-ubyte";
open my $mnist_image_fh, '<', $mnist_image_file
or die "Can't open file $mnist_image_file: $!";
# マジックナンバー
my $image_buffer;
read($mnist_image_fh, $image_buffer, 4);
my $magic_number = unpack('N1', $image_buffer);
if ($magic_number != 0x00000803) {
die "Invalid magic number expected " . 0x00000803 . "actual $magic_number";
}
# 画像数
read($mnist_image_fh, $image_buffer, 4);
my $items_count = unpack('N1', $image_buffer);
# 画像の行ピクセル数
read($mnist_image_fh, $image_buffer, 4);
my $rows_count = unpack('N1', $image_buffer);
# 画像の列ピクセル数
read($mnist_image_fh, $image_buffer, 4);
my $columns_count = unpack('N1', $image_buffer);
# 画像の読み込み
my $image_data;
my $all_images_length = $items_count * $rows_count * $columns_count;
my $read_length = read $mnist_image_fh, $image_data, $all_images_length;
unless ($read_length == $all_images_length) {
die "Can't read all images";
}
# 画像情報
my $image_info = {};
$image_info->{items_count} = $items_count;
$image_info->{rows_count} = $rows_count;
$image_info->{columns_count} = $columns_count;
$image_info->{data} = $image_data;
MNIST画像情報を読み込むプログラムの簡易解説
「data」以下に「train-images-idx3-ubyte」を配置します。
ファイルをオープンしてread関数で読み込んでいきます。
マジックナンバーのチェックを行います。ビッグエンディアンの32bit整数なので、unpackに「N1」を指定します。
画像数を取得します。ビッグエンディアンの32bit整数なので、unpackに「N1」を指定します。
画像の行ピクセル数を取得します。ビッグエンディアンの32bit整数なので、unpackに「N1」を指定します。
画像の列ピクセル数を取得します。ビッグエンディアンの32bit整数なので、unpackに「N1」を指定します。
MNIST画像情報では、すべての画像データで、行ピクセル数と列ピクセル数は共通です。
すべての画像を読み込みます。
訓練用の画像情報である「train-images-idx3-ubyte」を読み込んでいますが、検証用の画像情報「t10k-images-idx3-ubyte」も同様の方法で読み込めます。
MNIST画像情報を出力する方法
メモリ上にMNIST画像情報を読み込みましたが、これを確認する方法を解説します。ビットマップ画像として出力すれば、内容を確認できます。
Imagerというモジュールを使います。CPANモジュールですので、cpanmあるいはcpanでインストールしてください。
以下は、最初の5つの画像をビットマップ画像として出力するサンプルです。
use strict;
use warnings;
use FindBin;
use Imager;
# MNIST画像情報を読み込む
my $mnist_image_file = "$FindBin::Bin/data/train-images-idx3-ubyte";
open my $mnist_image_fh, '<', $mnist_image_file
or die "Can't open file $mnist_image_file: $!";
# マジックナンバー
my $image_buffer;
read($mnist_image_fh, $image_buffer, 4);
my $magic_number = unpack('N1', $image_buffer);
if ($magic_number != 0x00000803) {
die "Invalid magic number expected " . 0x00000803 . "actual $magic_number";
}
# 画像数
read($mnist_image_fh, $image_buffer, 4);
my $items_count = unpack('N1', $image_buffer);
# 画像の行ピクセル数
read($mnist_image_fh, $image_buffer, 4);
my $rows_count = unpack('N1', $image_buffer);
# 画像の列ピクセル数
read($mnist_image_fh, $image_buffer, 4);
my $columns_count = unpack('N1', $image_buffer);
# 画像の読み込み
my $image_data;
my $all_images_length = $items_count * $rows_count * $columns_count;
my $read_length = read $mnist_image_fh, $image_data, $all_images_length;
unless ($read_length == $all_images_length) {
die "Can't read all images";
}
# 画像情報
my $image_info = {};
$image_info->{items_count} = $items_count;
$image_info->{rows_count} = $rows_count;
$image_info->{columns_count} = $columns_count;
$image_info->{data} = $image_data;
# 画像情報の出力
for (my $i = 0; $i < 5; $i++) {
# 画像オフセット
my $offset = $i * $rows_count * $columns_count;
# キャンバス(モノクロ)
my $img = Imager->new(xsize => $rows_count, ysize => $columns_count, channels => 1);
# 画像情報を順番に出力
for (my $row = 0; $row < $rows_count; $row++) {
for (my $column = 0; $column < $columns_count; $column++) {
# 色(白黒がRGBと逆なので反転)
my $pos = $offset + ($column * $rows_count) + $row;
my $color_bin = substr($image_data, $pos, 1);
my $color_value = unpack('C1', $color_bin);
my $color_value_neg = $color_value ^ 0xFF;
my $color = Imager::Color->new($color_value_neg, $color_value_neg, $color_value_neg);
# ピクセル描画
$img->setpixel(x => $row, y => $column, color => $color);
}
}
# Web表示できるようにPNGとして保存
my $bitmap_file = "$FindBin::Bin/tmp_images/number$i.png";
$img->write(file => $bitmap_file);
}
出力した画像です。
MNIST画像情報を出力するプログラムの簡易解説
Imagerオブジェクトを幅と高さとチャンネル数を指定して作成します。モノクロなので1を指定しています。
画像情報を読み込んでいきます。行列の順で色の濃さが並んでいるので、取得します。データは、符号なし8bit整数で格納されているのでunpackに「C1」を指定しています。
MNISTの色の濃さはRGBと逆なので、反転させています。
Imager::Colorオブジェクトを作成しています。
ピクセルに描画します。
最後に、Webで表示できるようにpngで保存しています。拡張子から自動判定されます。
C言語のlibpngライブラリがOSのインストールされていることと、Imager::File::PNGが必要かもしれません。
Perl AI深層学習入門