弾性歪み(だんせいひずみ、)や弾性変形(だんせいへんけい、)とは、機械学習の画像に対するデータ拡張の手法。2003年にマイクロソフトの研究者等がMNIST手書き数字データセットに対する手法として発表した。
この手法は「手書き文字は多少線の位置が変わっても線のつながり方が変わらなければ文字の種類が変わらない」という事前知識をモデルの学習に導入する。
計算方法 二次元グレースケール画像に対する弾性歪みの計算手法は以下の通り。 は畳み込みの演算子。 連続一様分布からランダムノイズを生成する: ガウスぼかしを適用してα倍する: 補間して新画像を作成する:
論文のMNISTデータセットに対する推奨値はα=34, σ=4である。この数字は何ピクセル平行移動させるかという数字であり、MNISTの画像サイズの28x28ピクセルに依存していることに注意。
アフィン変換との比較 1998年にヤン・ルカン等がMNISTデータセットを発表した際はデータ拡張としてアフィン変換を使用していた。以下は、MNISTに対する、データ拡張なし、アフィン変換、弾性歪み、弾性歪み+アフィン変換の誤判定率の比較表である。
モデル データ拡張なし アフィン変換 弾性歪み 弾性歪み+アフィン変換 2層パーセプトロン 1.6% 1.1% 0.7% 3層パーセプトロン 0.49% 6層パーセプトロン 0.35% 畳み込みニューラルネットワーク 0.6% 0.4%
実装例 PythonとSciPyを使用して弾性歪みを実装する。
import numpy as np from scipy.ndimage import gaussian_filter, map_coordinates
def elastic_distortion(image, alpha=34, sigma=4): """ image: 2D numpy array (H, W), 0〜1のfloat想定 alpha: 変形の強さ(大きいほど強く変形) sigma: 変形フィールドにかけるガウスぼかしの標準偏差 """ shape = image.shape
# ランダムな変形フィールドを作成 dx = gaussian_filter(np.random.uniform(-1, 1, shape), sigma) * alpha dy = gaussian_filter(np.random.uniform(-1, 1, shape), sigma) * alpha
# 元の座標 x, y = np.meshgrid(np.arange(shape), np.arange(shape))
# 変形後の座標 indices = (y + dy).reshape(-1), (x + dx).reshape(-1)
# map_coordinates で補間付きでサンプリング return map_coordinates(image, indices, order=1).reshape(shape)
参照