MMdetection フレームワークを使用してデータ拡張を実装する N 通りの方法
1 なぜデータ拡張が必要なのか
ご存知のとおり、現在、最も高度なニューラル ネットワーク モデルでさえ、ターゲット出力に適合させるために一連の線形関数と非線形関数を使用しています。当然のことながら、フィッティングするのでサンプル数が多ければ多いほど、より正確な結果が得られるため、ニューラル ネットワークの学習に使用されるデータの規模はますます大きくなっています。
ただし、実際の使用では、データが数千、場合によっては数百しかないことがよくあります。ニューラル ネットワークの何百万ものパラメータに直面すると、過学習の罠に陥りやすくなります。ニューラルネットワークの収束には長いトレーニングプロセスが必要であり、このプロセス中にネットワークはトレーニングセット内の同じ数枚の画像に何度も遭遇するため、それらを記憶することで一般化できるものを学習することが困難であるためです。自然に考えられるのは、1 つの画像を使用して一連の画像を生成し、それによってデータ セットを何百倍、何千倍にも拡張できるだろうか、ということです。これがデータ強化の目的の 1 つです。
ニューラル ネットワークの「トリック」 - ニューラル ネットワークには常識がないため、常に最も「便利な」方法でのみ 2 つのカテゴリを区別します。
リンゴとオレンジを区別できるようにニューラル ネットワークをトレーニングしたいとします。しかし、手元にあるデータは赤いリンゴと緑のオレンジだけです。写真を何枚撮っても、ニューラル ネットワークは単に赤いものがリンゴで、シアンのものがリンゴであると判断するだけです。オレンジ。これは実際の使用においてもよく起こることであり、照明や撮影角度などの目立たない点を基にニューラルネットワークが分類します。
次に、現在の分類研究で最も一般的に使用されている一連のデータ強化方法と効果がリストされます。
2 データ拡張に関するよくある誤解
データ強化方法はたくさんあるのに、一度に積み上げれば最大の強化効果が得られるのではないかと思う人もいるだろう。答えは「ノー」で、データ強化の目的は、無闇にデータを蓄積することではなく、元のデータではカバーできないが現実に起こり得る状況を可能な限りカバーすることです。
例: 道路上の車の種類を区別するためにニューラル ネットワークをトレーニングしたいと考えています。そのため、画像の垂直方向の反転は、データ拡張方法としてはあまり適していません。実際には全輪アップです。
3 つの一般的なデータ拡張方法
3.1 ランダムフリップ
ランダム フリッピングは、水平反転と垂直反転を含む、非常に一般的なデータ拡張方法です。このうち水平反転が最もよく使われますが、実際の対象によっては垂直反転も使用できます。
MMClassification では、ほとんどのデータ拡張メソッドは、config のパイプライン構成を変更することで実装できます。ここでは、上に示したデータ拡張効果を示す Python コードを提供します。
import mmcvfrom mmcls.datasets
import PIPELINES
# 数据增强配置,利用 Registry 机制创建数据增强对象
aug_cfg = dict(
type='RandomFlip',
flip_prob=0.5, # 按 50% 的概率随机翻转图像
direction='horizontal', # 翻转方向为水平翻转
)
aug = PIPELINES.build(aug_cfg)
img = mmcv.imread("./kittens.jpg")
# 为了便于信息在预处理函数之间传递,数据增强项的输入和输出都是字典
img_info = {
'img': img}
img_aug = aug(img_info)['img']
mmcv.imshow(img_aug)
3.2 ランダムクロップ(RandomCrop)
画像をランダムな位置で指定したサイズに切り抜きます。このデータ強調方法では、画像の比率を維持したまま、画像内の各領域の位置を移動できます。
MMClassification では、次の構成が利用可能です。
# 此处只提供 cfg 选项,只需替换 RandomFlip 示例中对应部分,即可预览效果
aug_cfg = dict(
type='RandomCrop',
size=(384, 384), # 裁剪大小
padding = None, # 边缘填充宽度(None 为不填充)
pad_if_needed=True, # 如果图片过小,是否自动填充边缘
pad_val=(128, 128, 128), # 边缘填充像素
padding_mode='constant', # 边缘填充模式
)
3.3 ランダムにトリミングして拡大縮小する (RandomResizeCrop)
この方法は現在、分類ネットワークを学習する際の ImageNet などの一般的な画像データ セットのほぼ標準的な拡張方法です。固定サイズの画像を厳密にトリミングする RandomCrop と比較して、RandomResizeCrop は、特定の範囲内のランダムな位置とランダムな比率で画像をトリミングし、均一なサイズに拡大縮小します。
したがって、画像には比例してある程度の歪みが生じます。しかし、これは分類にとって必ずしも悪いことではなく、結局のところ、少し平板な猫を犬として認識することはありませんし、ネットワークはこの機能強化を通じてより本質に近い特徴を学習することもできます。さらに、この強調方法は比例的にトリミングされるため、異なる解像度の入力画像により適しています。
MMClassification では、次の構成が利用可能です。
# 此处只提供 cfg 选项,只需替换 RandomFlip 示例中对应部分,即可预览效果
aug_cfg = dict(
type='RandomResizedCrop',
size=(384, 384), # 目标大小
scale=(0.08, 1.0), # 裁剪图片面积占比限制(不得小于原始面积的 8%)
ratio=(3. / 4., 4. / 3.), # 裁剪图片长宽比例限制,防止过度失真
max_attempts=10, # 当长宽比和面积限制无法同时满足时,最大重试次数
interpolation='bilinear', # 图像缩放算法
backend='cv2', # 缩放后端,有时 'cv2'(OpenCV) 和 'pillow' 有微小差别
)
3.4 カラージッター (ColorJitter)
画像の色のデータを強調するために最も一般的に使用される方法は ColorJitter であり、この方法は画像の明るさ (Brightness)、コントラスト (Contrast)、彩度 (Saturation)、および色相 (Hue) を一定の範囲内で強調します。ランダムな変換により、実際の撮影におけるさまざまな照明環境やその他の条件の変化をシミュレートします。
MMClassification では、次の構成が利用可能です。
# 此处只提供 cfg 选项,只需替换 RandomFlip 示例中对应部分,即可预览效果
aug_cfg = dict(
type='ColorJitter',
brightness=0.5, # 亮度变化范围(0.5 ~ 1.5)
contrast=0.5, # 对比度变化范围(0.5 ~ 1.5)
saturation=0.5, # 饱和度变化范围(0.5 ~ 1.5)
# 色相变换应用较少,目前 MMClassification 暂不支持 Hue 的增强
)
3.5 ランダムグレースケール
一定の確率に従って、画像はグレースケール画像に変換されます。この強調方法は色の影響を排除し、特定のシーンに適用できます。
MMClassification では、次の構成が利用可能です。
# 此处只提供 cfg 选项,只需替换 RandomFlip 示例中对应部分,即可预览效果
aug_cfg = dict(
type='RandomGrayscale',
gray_prob=0.5, # 按 50% 的概率随机灰度化图像
)
3.6 ランダムな照明変換(照明)
この論文は、画像照明のデータ強化方法を提案しています。その出典: https://dl.acm.org/doi/pdf/10.1145/3065386
この方法では、まずトレーニング データセット内のすべての画像のピクセルに対して PCA (主成分分析) が実行され、RGB 空間の固有値と固有ベクトルが取得されます。では、この特徴ベクトルは何を表すのでしょうか? ここで、論文の著者は、これが画像ピクセルに対する光強度の影響を表していると考えています。結局のところ、画像の内容は多様ですが、写真のどこにいても、必然的に照明条件の影響を受けます。
特徴ベクトルは光の強度の影響を表すため、特徴ベクトルの方向に沿って画像のピクセル値にランダムな加算と減算を行うことで、異なる照明の画像をシミュレートできます。
MMClassificationでは以下の設定が可能です。注意が必要なのは固有値と固有ベクトルの設定で、一般的なシーンでの分類であればImageNetの値を直接利用できますが、特殊な照明環境でのタスクであればForを収集する必要があります。異なる照明強度の下で画像を作成する場合は、独自のデータセットに対して PCA を実行して、ここでの設定を置き換えます。
import mmcvfrom mmcls.datasets
import PIPELINES
aug_cfg = dict(
type='Lighting',
eigval=[55.4625, 4.7940, 1.1475], # 在 ImageNet 训练集 PCA 获得的特征值
eigvec=[[-0.5675, 0.7192, 0.4009], # 在 ImageNet 训练集 PCA 获得的特征向量
[-0.5808, -0.0045, -0.8140],
[-0.5836, -0.6948, 0.4203]],
alphastd=2.0, # 随机变换幅度,为了展示效果,这里设置较大,通常设置为 0.1
to_rgb=True, # 是否将图像转换为 RGB,mmcv 读取图像为 BGR 格式,为了与特征向量对应,此处转为 RGB
)
aug = PIPELINES.build(aug_cfg)
img = mmcv.imread("./kittens.jpg")
img_info = {
'img': img}
img_aug = aug(img_info)['img']
# Lighting 变换得到的图像为 float32 类型,且超出 0~255 范围,为了可视化,此处进行限制
img_aug[img_aug < 0] = 0
img_aug[img_aug > 255] = 255
img_aug = img_aug.astype('uint8')[:, :, ::-1] # 转回 BGR 格式
mmcv.imshow(img_aug)
上記で紹介したデータ補正方法は一般的に使用されている方法の一部であり、複数の方法をランダムに組み合わせたり(AutoAugment、RandAugment)、複数の画像を混合して補正したり(MixUp、CutMix)など、さらに多くのデータ補正方法があります。