1,538 views
1) CIFAR-10データセットを入手する。
画像のダウンロード元はこちら(↓) Python用に pickleで作成されたデータファイルをダウンロードする。
https://www.cs.utoronto.ca/~kriz/cifar.html
ダウンロードしたファイルを解凍する。
$ tar -xzvf cifar-10-python.tar.gz
画像表示用に Python仮想環境に Matplotlibを入れておく。
$ sudo apt install python3-matplotlib
以下、ダウンロードデータを解凍したディレクトリで作業する。
$ ls -l
total 181884
drwxr-xr-x 2 hoge hoge 4096 Jun 5 2009 ./
drwxrwxr-x 3 hoge hoge 4096 Apr 23 04:31 ../
-rw-r--r-- 1 hoge hoge 158 Mar 31 2009 batches.meta
-rw-r--r-- 1 hoge hoge 31035704 Mar 31 2009 data_batch_1
-rw-r--r-- 1 hoge hoge 31035320 Mar 31 2009 data_batch_2
-rw-r--r-- 1 hoge hoge 31035999 Mar 31 2009 data_batch_3
-rw-r--r-- 1 hoge hoge 31035696 Mar 31 2009 data_batch_4
-rw-r--r-- 1 hoge hoge 31035623 Mar 31 2009 data_batch_5
-rw-r--r-- 1 hoge hoge 88 Jun 5 2009 readme.html
-rw-r--r-- 1 hoge hoge 31035526 Mar 31 2009 test_batch
2) データセットの構造を確認する。
(1) batches.meta
まずはファイルをロードする。
>>> import pickle >>> with open(‘batches.meta’, ‘rb’) as f: ... meta = pickle.load(f, encoding=’bytes’)
データタイプを確認してみると dictionary型なので、keyの値を表示する。
>>> type(meta) <class 'dict'> >>> >>> meta.keys() dict_keys([b’num_cases_per_batch’, b’label_names’, b’num_vis’])
以下の三種類のデータが格納されていることがわかった。
meta[ b’num_cases_per_batch’ ]
meta[ b’label_names’ ]
meta[ b’num_vis’ ]
それぞれのデータタイプと中身を見てみる。
num_cases_per_batch には、一つのデータファイルに格納されている画像の個数が入っている。
>>> type(meta[b’num_cases_per_batch’]) <class 'int'> >>> meta[b’num_cases_per_batch’] 10000
label_names には、画像のラベル名(airplane, automobile, bird, deer, etc.)が入っている。
b’airplane’ と書かれているので、Unicodeではなく 1バイトのアスキーコードで入っている。
>>> type(meta[b’label_names’]) <class 'list'> >>> len(meta[b’label_names’]) 10 >>> >>> type(meta[b’label_names’][0]) <class 'bytes'> >>> >>> meta[b’label_names’] [b’airplane’, b’automobile’, b’bird’, b’cat’, b’deer’, b’dog’, b’frog’, b’horse’, b’ship’, b’truck’]
num_visには、一つの画像データのバイトサイズが入っている。
(縦, 横, チャネル) = (32, 32, 3) = 3072バイトの画像データが入っているということ。
>>> type(meta[b’num_vis’]) <class 'int'> >>> meta[b’num_vis’] 3072
(2) data_batch_n, test_batch
まずはファイルをロードする。
>>> with open(‘data_batch_1’, ‘rb’) as f: ... batch = pickle.load(f, encoding=’bytes’)
データタイプを確認してみると dictionary型なので、keyの値を表示する。
>>> type(batch) <class 'dict'> >>> >>> batch.keys() dict_keys([b’batch_label’, b’labels’, b’data’, b’filenames’])
以下の三種類のデータが格納されていることがわかった。
batch[ b’batch_label’ ]
batch[ b’labels’ ]
batch[ b’filenames’ ]
それぞれのデータタイプと中身を見てみる。
batch_label には、今回開いたファイルの説明が書かれている。
data_batch_1 〜 data_batch_5 の中の一番目のファイルを開いたので、training batch 1 of 5 と書かれている。
>>> type(batch[b’batch_label’]) <class 'bytes'> >>> batch[b’batch_label’] b’training batch 1 of 5′
labels には、このファイルに格納されている各画像のラベル番号(0:airplane, 1:automobile, 2:bird, etc.)が入っている。
>>> type(batch[b’labels’]) <class 'list'> >>> len(batch[b’labels’]) 10000 >>> batch[b’labels’][0] 6 >>> batch[b’labels’][1] 9
data には、このファイルに格納されている各画像データが入っている。
各画像データは、要素数 3072個の配列データとして格納されている。 上記の num_vis に書かれていた通りだ。
>>> type(batch[b’data’]) <class 'numpy.ndarray'> >>> len(batch[b’data’]) 10000 >>> batch[b’data’][0].shape (3072,) >>> batch[b’data’][1].shape (3072,)
3) 学習用画像を表示してみる。
(1) 指定indexの画像 1枚を表示する。
このブログ執筆作業は Ubuntu24.04 Desktop 上で行っている。
画面上に画像を表示したいので、使用中の Python仮想環境にも matplotlibをインストールする。
$ pip install matplotlib
Python shellを起動し、以下のプログラムを実行する。
この後、show_image( index ) を実行すれば、任意のインデックスの画像を表示できる。
import pickle
import numpy as np
import matplotlib.pyplot as plt
# CIFAR-10 データのファイルパス
file_path = "./cifar-10-batches-py/data_batch_1"
# Python 3 用にエンコード指定して読み込み
with open('data_batch_1', 'rb') as f:
batch = pickle.load(f, encoding='bytes')
# データとラベルを取り出す(キーはバイト文字列)
images = batch[b'data'] # shape: (10000, 3072)
labels = batch[b'labels'] # shape: (10000,)
def show_image(index):
# 画像データ[3072]を [32][32][3] に並び替える
img = images[index].reshape(3, 32, 32) # [3074] → [C:3][V:32][H:32]
img = np.transpose(img, (1, 2, 0)) # → [V:32][H:32][C:3]
# 画像を表示
plt.imshow(img)
plt.title(f"Label: {labels[index]}")
plt.show()
まずは、先頭画像(index=0)を表示する。
>>> show_image(0)
前回と同じ、frog が表示された。
(2) 複数枚の画像をまとめてタイル表示する。
もっと表示してみる。
最後の36画像のタイル表示は、以下のプログラムで実行した。
import pickle
import numpy as np
import matplotlib.pyplot as plt
# CIFAR-10 バッチ読み込み
with open('data_batch_1', 'rb') as f:
batch = pickle.load(f, encoding='bytes')
images = batch[b'data']
labels = batch[b'labels']
# 画像データ[3072]を [32][32][3] に並び替える関数
def convert_image(raw):
img = raw.reshape(3, 32, 32) # [3074] → [C:3][V:32][H:32]
img = np.transpose(img, (1, 2, 0)) # → [V:32][H:32][C:3]
return img
# 6x6個の画像プロットエリアを作る。
fig, axes = plt.subplots(6, 6, figsize=(8, 8))
# 最初の36枚の画像をループして描画する。
for i in range(36):
row = i // 6 # 行インデックス(0〜5)
col = i % 6 # 列インデックス(0〜5)
ax = axes[row, col] # 該当のsubplotを取得
img = convert_image(images[i]) # 画像を整形
ax.imshow(img) # 表示
ax.set_title(f"Label: {labels[i]}", fontsize=8) # タイトルにラベル表示
ax.axis('off') # 枠線・軸目盛りを非表示
plt.tight_layout() # タイル間の間隔を自動調整
plt.show()
(3) 複数枚の画像をまとめてタイル表示する。改良版
ラベル番号よりもラベル名で表示したほうが親切かな。
batches.metaを読み込み、ラベル名を表示するように改善した。
import pickle
import numpy as np
import matplotlib.pyplot as plt
# CIFAR-10 メタ読み込み
with open('./cifar-10-batches-py/batches.meta', 'rb') as f:
meta = pickle.load(f, encoding='bytes')
label_names = [b.decode('utf-8') for b in meta[b'label_names']]
# CIFAR-10 バッチ読み込み
with open('./cifar-10-batches-py/data_batch_1', 'rb') as f:
batch = pickle.load(f, encoding='bytes')
images = batch[b'data']
labels = batch[b'labels']
# 画像データ[3072]を [32][32][3] に並び替える関数
def convert_image(raw):
img = raw.reshape(3, 32, 32) # [3074] → [C:3][V:32][H:32]
img = np.transpose(img, (1, 2, 0)) # → [V:32][H:32][C:3]
return img
# 6x6個の画像プロットエリアを作る。
fig, axes = plt.subplots(6, 6, figsize=(8, 8))
# 最初の36枚の画像をループして描画する。
for i in range(36):
row = i // 6 # 行インデックス(0〜5)
col = i % 6 # 列インデックス(0〜5)
ax = axes[row, col] # 該当のsubplotを取得
img = convert_image(images[i]) # 画像を整形
ax.imshow(img) # 表示
ax.set_title(f"{label_names[labels[i]]}", fontsize=8) # タイトルにラベル表示
ax.axis('off') # 枠線・軸目盛りを非表示
plt.tight_layout() # タイル間の間隔を自動調整
plt.show()