Keras: ImageDataGenerator
\(\def\vector#1{\boldsymbol{#1}}\)概要
Keras 2.2 に付属するデータ拡張と正規化のための多機能前処理ユーティリティ ImageDataGenerator
のパラメータごとの効果を整理する。明文化されていない部分については Github のソースを参照する必要がある。
ImageDataGenerator は拡大縮小や回転、明るさなどを変更することで画像の特徴のバリエーションを水増しし、少ない訓練データでモデルの精度を上げる目的で使用される。
画像変換のパラメータ
アフィン変換と明るさの変換を行うことができる。
channel_shift_range
画像の明るさをランダムに変化させる。
このパラメータは画像のカラーチャネル値 (RGB の場合はピクセルごとに 3 次元) それぞれに指定された範囲の値を加算する。float
値 \(t\) を指定した場合、カラーチャネルに加算される intensity 値は \(\pm t\) 範囲のランダムな値である。ただし、画像のカラーチャンネル階調の最小値 \(x_{\rm min}\)、最大値 \(x_{\rm max}\) を超えることはない。つまり: \[ \begin{array}{l} -t \leq {\rm intensity} \lt t \\ x' = \left\{ \begin{array}{ll} x_{\rm min} & \ \ {\rm if} \ x + {\rm intensity} \lt x_{\rm min} \\ x_{\rm max} & \ \ {\rm if} \ x + {\rm intensity} \gt x_{\rm max} \\ x + {\rm intensity} & \ \ {\rm otherwise} \end{array} \right. \end{array} \]
カラーチャネルに加減される intensity 値は画像に対して同一であるため、色調を変更せず明るくまたは暗くする効果を持つ。
例えば RGB カラーモデルの配列では各カラーチャネルは 256 階調を持つため 0-255 の範囲で指定する (rescale=1./255
の正規化は画像変換後に適用される)。
width_shift_range, height_shift_range
上下または左右にランダムにスライドさせる。
設定値 \(d\) は移動距離となる乱数の範囲を示す。値によって以下のように解釈される。
float
で \(d \lt 1\) の場合、画像の横幅/縦幅に対する割合を示す。float
で \(d \geq 1\) の場合、\(-d \leq x \lt d\) 範囲のピクセル数を示す。例えば3.0
を指定した場合、1次元配列で[-3, -2, -1, 0, 1, 2]
とした場合と等価である。int
の場合、\(-d \lt x \lt d\) 範囲のピクセル数を示す。例えば3
を指定した場合、1次元配列で[-2, -1, 0, 1, 2]
とした場合と等価である。- 1次元配列の場合、それらの中からランダムに選ばれた値のピクセル数が適用される。
移動により発生した空白領域を埋める方法は fill_mode
で指定することができる。デフォルトは "nearest"
が適用される。
horizontal_flip, vertical_flip
縦反転、横反転をランダムに行う。
横方向または縦方向の反転を行うかを True
/False
で指定する。
rotation_range
ランダムな角度で画像を回転させる。
例えば rotation_range=45
を指定した場合 \(\pm 45^\circ\) の範囲でランダムに回転する。
shear_range
ランダムな角度で画像を傾かせる。
縦方向と横方向への傾き (シアー) の範囲を度数で指定する。
zoom_range
画像を縦横ランダムに拡張/縮小する。
パラメータの値に対する解釈は以下の通り。
float
値 \(t\) を指定した場合、拡大率の取りうる範囲は \(1\pm t\) となる。つまり[1-t, 1+t]
を指定した場合と等価。- 2 要素の配列
[min, max]
で指定した場合、それらはランダムに取りうる拡大率の範囲とみなされる。min == max
の場合、固定倍率の拡縮が行われる。
fill_mode
縮小や回転などによって発生した余白を埋める方法。
constant
, nearest
, reflect
, wrap
のいずれかを指定することができる。constant
を指定した場合、cval
で余白部分のカラーチャネルに設定する階調を指定することができる。
画像変換テスト用スクリプト
このページ用に作成したスクリプト。
# -*- encoding: utf-8 -*-
#
from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array, array_to_img
from PIL import Image, ImageDraw
import numpy as np, math
GENERATORS = [
{
"div": 1,
"generators": {
"fill_mode-constant": ImageDataGenerator(zoom_range=[1.75, 1.75], fill_mode="constant", cval=0xCC),
"fill_mode-nearest" : ImageDataGenerator(zoom_range=[1.75, 1.75], fill_mode="nearest"),
"fill_mode-reflect" : ImageDataGenerator(zoom_range=[1.75, 1.75], fill_mode="reflect"),
"fill_mode-wrap" : ImageDataGenerator(zoom_range=[1.75, 1.75], fill_mode="wrap")
}
}, {
"div": 4,
"generators": {
"rotation_range": ImageDataGenerator(rotation_range=60),
"width_shift_range": ImageDataGenerator(width_shift_range=0.2),
"height_shift_range": ImageDataGenerator(height_shift_range=0.2),
"shear_range": ImageDataGenerator(shear_range=60),
"zoom_range": ImageDataGenerator(zoom_range=0.4),
"horizontal_flip": ImageDataGenerator(horizontal_flip=True),
"vertical_flip": ImageDataGenerator(vertical_flip=True),
"channel_shift_range": ImageDataGenerator(channel_shift_range=100)
}
}
]
def create_samples(file):
original = load_img(file)
X = np.expand_dims(img_to_array(original), axis=0)
margin = 1
max_screen_size = 480
rate = min(1.0, min(float(max_screen_size) / original.width, float(max_screen_size) / original.height))
screen_size = (int(original.width * rate), int(original.height * rate))
for gs in GENERATORS:
div = gs["div"]
thumb_size = (int(original.width * rate / div), int(original.height * rate / div))
for id in gs["generators"]:
g = gs["generators"][id]
g.fit(X, seed=1234)
generator = g.flow(X)
screen = Image.new("RGB", screen_size)
x = y = 0
while y < screen.height:
while x < screen.width:
thumb_array = next(generator)
thumb = array_to_img(thumb_array[0])
thumb = thumb.resize(thumb_size, resample=Image.BICUBIC)
screen.paste(thumb, (x, y))
x += thumb_size[0] + margin
x = 0
y += thumb_size[1] + margin
screen.save("%s.png" % id)
if __name__ == "__main__":
import sys
create_samples(sys.argv[1])
正規化のパラメータ
正規化はアフィン変換や明るさ変換が行われたあとに適用される。ジェネレータが生成するテンソルを入力とするニューラルネットワークに向けた処理である。
rescale
テンソルの正規化係数を指定する。
このパラメータは画像変換を行なったあとにすべてのテンソル値 (つまりすべてのピクセルのカラーチャネル) に乗算する係数を指定する。例えば RGB 各チャネルに 256 階調を持つ一般的なフルカラー画像であれば、rescale=1./255
と指定することで、このジェネレータによって生成されるテンソルを 0 から 1 の範囲に正規化することができる。
array_to_img()
や save_image()
はテンソル中の最大値/最小値を 0-255 に変換しているだけであるため、正規化した画像を正確には復元することができない。rescale
によって 0~1 範囲に正規化された画像を元に戻すにはテンソルに 255 を乗算したテンソルをそれらに scale=False
で適用することで元の 256 階調に戻すことができる (いずれもデフォルト True
であるため注意)。
上記は 4x4 RGB 画像の適用例である。rescale
値を \(f=1/255\) とすると \(\vector{T}_2 = f \times \vector{T}_1\) となっていることが分かる。
samplewise_center, featurewise_center
値の平均が 0.0 となるように調整する。
このパラメータはゼロを中心にプラスとマイナス方向に分布する入力データを生成するための正規化処理を行う (このパラメータは rescale
の後に適用される)。具体的には以下のようにテンソルのそれぞれの値から平均値を減算する。\[ \vector{T}' = \vector{T} - \bar{t} \]
samplewise_center
での \(\bar{t}\) はサンプルに対する平均であり、featurewise_center
はデータセット全体に対する平均である。
rescale
で正規化された \(\vector{T}_2\) の平均 \(\bar{t}=0.409150\) より、\(\vector{T}_3 = \vector{T}_2 - \bar{t}\) であることが分かる。
samplewise_std_normalization, featurewise_std_normalization
値を標準偏差で正規化する。
テンソル \(\vector{T}\) に含まれる値の分布の広がりを正規化するために使用する (対応する xxxwise_center
と共に使用する必要がある)。\(\vector{T}\) の平均値を \(\bar{t}\)、標準偏差を \(\sigma\) としたとき、このパラメータを True
にすることで以下の変換が行われる。\[ \vector{T}' = \frac{\vector{T} - \bar{t}}{\sigma} \]
samplewise_std_normalization
での \(\sigma\) はサンプルに対する標準偏差であり、featurewise_std_normalization
ではデータセット全体に対する標準偏差である。
これらのパラメータを True
にする場合は、それぞれ対応する samplewise_center
や featurewise_center
が暗黙的に True
に設定される (False
のままでは警告が出るため明示的に指定するとよい)。
\(\vector{T}_3\) の分散は \(\sigma = 0.329183\) である。\(\vector{T}_4 = \vector{T}_3 / \sigma\) であることがわかる。
zca_whitening, zca_epsilon
ZCA 白色化を行う。
白色化 (wwhitening) とは共分散行列 \(\Sigma\) が単位行列となるような変換のこと。つまり白色化は特徴を非相関化するための前処理である。featurewise_center=True
とともに使用する。
参照
- ImageDataGenerator
- Francois Chollet (2018)PythonとKerasによるディープラーニング, マイナビ出版
- 太田満久, 須藤広大, 黒澤匠雅, 小田大輔 (2018) TensorFlow開発入門 Kerasによる深層学習モデル構築手法, 翔泳社
- サンプル画像: Biandintz eta zaldiak