SIGMA-SE Math & Tech Library

SIGMA-SE Math & Tech Library


数学と情報技術をテーマに、書籍や教材だけではつかみにくい考え方を具体例とともに簡潔にわかりやすく伝える解説サイトです。
技術の歴史や背景、関連知識の整理、学習のための覚書や要約記事も掲載しています。

Python - ニューラルネットワーク:5/14 MNISTデータセットの取得と確認

概要

手書き数字画像データセットであるMNISTを取得し、ニューラルネットワークのサンプルで扱える形にする手順を整理する。

MNISTは、画像分類の入門でよく使われるデータセットで、入力データ、ラベル、訓練データ、テストデータの関係を確認するのに向いている。

ここでは、データの仕様、ダウンロード処理、画像としての表示確認までを扱う。

この記事の構成

概念の説明と実装サンプル

MNISTとは

  • データセットの構成

    MNIST(Modified National Institute of Standards and Technology database)とは、0~9の手書き数字で構成され、訓練画像60,000枚とテスト画像10,000枚が用意された画像データセットである。

    また、手書き数字の訓練画像が60,000枚、テスト画像が10,000枚の「1枚」に対して画像データその画像の正解となるラベルデータがペアとなっており、下記の4つのファイルで構成されている。

    • train-images-idx3-ubyte : 学習用 画像データセット(60,000枚)
    • train-labels-idx1-ubyte : 学習用 ラベルデータセット(60,000個)
    • t10k-images-idx3-ubyte : テスト用 画像データセット(10,000枚)
    • t10k-labels-idx1-ubyte : テスト用 ラベルデータセット(10,000個)

MNISTのデータ仕様

  • 画像・ラベルデータの形式

    機械学習では画像を数値として扱う必要があるため、バイナリデータとなっており、画像とラベルデータが紐付いている。

    ※ 以下の画像・ラベルの形式は、MNISTで使われるIDXファイルのヘッダーとデータ配置を整理したもの。

    以下、画像とラベルのフォーマット仕様。

    • 画像データのフォーマット(train-images-idx3-ubyte、t10k-images-idx3-ubyte)

      offset type value description
      0000 32 bit integer 0x00000803(2051) 識別子(定数)
      0004 32 bit integer 60000 画像データの数
      0008 32 bit integer 28 1画像あたりのデータ行数
      0012 32 bit integer 28 1画像あたりのデータ列数
      0016 unsigned byte 0 ~ 255 1つめの画像の1ピクセル目の値
      0017 unsigned byte 0 ~ 255 1つめの画像の2ピクセル目の値
      ... ... ... ...
      xxxx unsigned byte 0 ~ 255 最後の画像の784ピクセル目の値
    • ラベルデータのフォーマット(train-labels-idx1-ubyte、t10k-labels-idx1-ubyte)

      offset type value description
      0000 32 bit integer 0x00000801(2049) 識別子(定数)
      0004 32 bit integer 60000 or 10000 ラベルデータの数
      0008 unsigned byte 0 ~ 9 1つ目のデータのラベル
      0009 unsigned byte 0 ~ 9 2つ目のデータのラベル
      ... ... ... ...
      xxxx unsigned byte 0 ~ 9 最後のデータのラベル

MNISTのダウンロード

  • データ取得と読み込み

    下記、mnist.pyを使用し、MNISTをダウンロードする。

    Git(deep-learning-from-scratch):https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/dataset/mnist.py

    • リポジトリをクローン

      $ cd gitlocalrep
      $ git clone https://github.com/oreilly-japan/deep-learning-from-scratch.git
      Cloning into 'deep-learning-from-scratch'...
      remote: Enumerating objects: 381, done.
      remote: Total 381 (delta 0), reused 0 (delta 0), pack-reused 381
      Receiving objects: 100% (381/381), 4.93 MiB | 4.16 MiB/s, done.
      Resolving deltas: 100% (197/197), done.
      
    • カレントディレクトに移動
      mnist.pyの利用時は、カレントディレクトを ch01、ch02、ch03 … ch08 のいずれかで実施する必要がある。
      ここでは、ch03から実施。

      $ cd deep-learning-from-scratch/ch03
      
    • ダウンロード
      下記、load_mnistによってMNISTデータセットのダウンロードを行っているが、初回のみオンラインである必要があり数分かかる。
      初回で読み込み時にpickleというローカルファイルが作成され、ダウンロード結果を保持しているので、2回目以降は、オフラインかつ、すぐに処理が終わる。
      ※ Pythonのpickleは、Pythonオブジェクトをファイルへ保存・復元する機能。信頼できないpickleを読み込むと任意のコードが実行される危険があるため、この例では取得元を確認したファイルだけを使用する。

      $ python
       >>> import sys, os
       >>> sys.path.append(os.pardir)    # 親ディレクトリのファイルをインポートするための設定
       >>> from dataset.mnist import load_mnist
       >>>
       >>> (x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)    # MNISTデータセットのダウンロード
       Downloading train-images-idx3-ubyte.gz ...
       Done
       Downloading train-labels-idx1-ubyte.gz ...
       Done
       Downloading t10k-images-idx3-ubyte.gz ...
       Done
       Downloading t10k-labels-idx1-ubyte.gz ...
       Done
       Converting train-images-idx3-ubyte.gz to NumPy Array ...
       Done
       Converting train-labels-idx1-ubyte.gz to NumPy Array ...
       Done
       Converting t10k-images-idx3-ubyte.gz to NumPy Array ...
       Done
       Converting t10k-labels-idx1-ubyte.gz to NumPy Array ...
       Done
       Creating pickle file ...
       Done!
       >>>
       >>> print(x_train.shape)    # データ形状の確認:学習用 画像データセット
       (60000, 784)
       >>> print(t_train.shape)    # データ形状の確認:学習用 ラベルデータセット
       (60000,)
       >>> print(x_test.shape)    # データ形状の確認:テスト用 画像データセット
       (10000, 784)
       >>> print(t_test.shape)    # データ形状の確認:テスト用 ラベルデータセット
       (10000,)
       >>>
      
    • load_mnist関数の概要
      引数 normalize は、入力画像を0.0 ~ 1.0 に正規化するかどうかBool値で設定。
      Falseの場合、入力画像のピクセルは 0 ~ 255 となる。
      引数 flatten は、入力画像を1次元にするかどうかBool 値で設定。
      Falseの場合、入力画像は1 * 28 * 28 の3次元配列として格納され、Trueの場合、1次元配列(要素:784)として格納される。
      引数 one_hot_label は、ラベルを one_hot表現で格納するかBool値で設定。
      one_hot 表現の場合は、正解となるラベルのみ 1 でそれ以外は、0 の配列となる。
      戻り値は、(訓練画像, 訓練ラベル), (テスト画像, テストラベル)の形式でMNISTデータを返す。

画像データ表示確認

  • 手書き数字画像の表示

    ch03/mnist_show.pyに訓練画像1枚目「5」の確認用ソースコードが記載されている。
    下記は、この中のshowにあたる箇所をsaveに置換え、画像ファイルを出力するサンプル。

    $ python
     >>> import sys, os
     >>> sys.path.append(os.pardir)
     >>> import numpy as np
     >>> from dataset.mnist import load_mnist
     >>> from PIL import Image
     >>>
     >>> def img_save(img):
     ...     pil_img = Image.fromarray(np.uint8(img))
     ...     pil_img.save('pid19_1.png')    # *1 mnist_show.py では、pil_img.show()
     ...
     >>> (x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
     >>>
     >>> img = x_train[0]
     >>> label = t_train[0]
     >>> print(label)
     5
     >>> print(img.shape)
     (784,)
     >>> img = img.reshape(28, 28)
     >>> print(img.shape)
     (28, 28)
     >>> img_save(img)    # *1 mnist_show.py では、img_show()
     >>>
    
    • pid19_1.png
      期待通り、数字の手書き画像「5」が出力された。
      pid19_1

まとめ

  • MNISTは手書き数字の画像と正解ラベルから構成され、画像はピクセル値の配列として扱われる。
  • shapeや画像表示を確認すると、配列の形と実際の画像を対応付けやすい。
  • 訓練データは学習、テストデータは評価に使い、両者を混ぜない。
  • 正規化の有無によってピクセル値の範囲が変わるため、後続処理の前提をそろえる。

参考文献

この記事を共有
Xで共有 Facebookで共有 LINEで共有



Copyright SIGMA-SE All Rights Reserved.
s-hama@sigma-se.jp