Kaggleのチュートリアルを頑張っています。今回は画像認識に関して最終の回です。
https://www.kaggle.com/code/ryanholbrook/data-augmentation
ほぼコピペですが、頑張ります。
データ拡張
追加のトレーニングデータを作成することでパフォーマンスを向上させます。
導入
畳み込み分類器の基礎を学び終えたので、より高度なトピックに進む準備ができました。このレッスンでは、画像分類器の性能を向上させるテクニック、データ拡張という手法について学びます。
偽のデータの有用性
機械学習モデルの性能を向上させる最良の方法は、それをより多くのデータで訓練することです。モデルが学習のために持っている例が多ければ多いほど、画像のどの違いが重要でどれがそうでないかをよりよく認識することができます。多くのデータはモデルがより良く一般化するのに役立ちます。
より多くのデータを手に入れる簡単な方法の1つは、既に持っているデータを使用することです。データセットの画像をクラスを保持したままの方法で変換できれば、分類器にその種の変換を無視する方法を教えることができます。たとえば、写真の中で車が左を向いているか右を向いているかは、それがトラックではなく車であるという事実を変えません。したがって、訓練データを反転した画像で拡張すれば、分類器は「左または右」という違いを無視すべきだと学ぶでしょう。
そして、それがデータ拡張の背後にあるアイデアの全体です:実際のデータのように見える追加の偽のデータを追加すると、分類器の性能が向上します。
データ拡張の使用
通常、データセットを拡張するときにはさまざまな種類の変換が使用されます。これには、画像を回転させる、色やコントラストを調整する、画像をワープさせるなど、通常は組み合わせて適用される多くの操作が含まれるかもしれません。以下は、単一の画像がどのように変換されるかの異なる方法の一例です。
引用:https://www.kaggle.com/code/ryanholbrook/data-augmentation
データ拡張は通常オンラインで行われます。つまり、画像がトレーニングのためにネットワークに供給されるときに行われます。トレーニングは通常、データのミニバッチで行われることを思い出してください。データ拡張が使用される場合、16枚の画像のバッチがどのように見えるかがこれです。
引用:https://www.kaggle.com/code/ryanholbrook/data-augmentation
トレーニング中に画像が使用されるたびに、新しいランダムな変換が適用されます。このようにして、モデルは以前に見たものとは少し異なるものを常に見ることになります。このトレーニングデータの追加の変動が、モデルが新しいデータでの性能を向上させるのを助けています。
ただし、与えられた問題に対してすべての変換が有用であるわけではないことを覚えておくことが重要です。最も重要なのは、使用する変換がクラスを混同しないようにすることです。例えば、数字の認識器をトレーニングしている場合、画像を回転させると'9'と'6'が混ざってしまいます。
例 - データ拡張を使用したトレーニング
Kerasは2つの方法でデータを拡張できます。1つ目の方法は、ImageDataGeneratorのような関数でデータパイプラインにそれを含めることです。2つ目の方法は、Kerasの前処理レイヤーを使用してモデル定義にそれを含めることです。これが私たちが取るアプローチです。私たちにとっての主な利点は、画像変換がCPUではなくGPUで計算されるため、トレーニングが速くなる可能性があることです。
# Imports
import os, warnings
import matplotlib.pyplot as plt
from matplotlib import gridspec
import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing import image_dataset_from_directory
Reproducability
def set_seed(seed=31415):
np.random.seed(seed)
tf.random.set_seed(seed)
os.environ['PYTHONHASHSEED'] = str(seed)
#os.environ['TF_DETERMINISTIC_OPS'] = '1'
set_seed()
Set Matplotlib defaults
plt.rc('figure', autolayout=True)
plt.rc('axes', labelweight='bold', labelsize='large',
titleweight='bold', titlesize=18, titlepad=10)
plt.rc('image', cmap='magma')
warnings.filterwarnings("ignore") # to clean up output cells
Load training and validation sets
ds_train_ = image_dataset_from_directory(
'../input/car-or-truck/train',
labels='inferred',
label_mode='binary',
image_size=[128, 128],
interpolation='nearest',
batch_size=64,
shuffle=True,
)
ds_valid_ = image_dataset_from_directory(
'../input/car-or-truck/valid',
labels='inferred',
label_mode='binary',
image_size=[128, 128],
interpolation='nearest',
batch_size=64,
shuffle=False,
)
Data Pipeline
def convert_to_float(image, label):
image = tf.image.convert_image_dtype(image, dtype=tf.float32)
return image, label
AUTOTUNE = tf.data.experimental.AUTOTUNE
ds_train = (
ds_train_
.map(convert_to_float)
.cache()
.prefetch(buffer_size=AUTOTUNE)
)
ds_valid = (
ds_valid_
.map(convert_to_float)
.cache()
.prefetch(buffer_size=AUTOTUNE)
)
Found 5117 files belonging to 2 classes.
Found 5051 files belonging to 2 classes.
ステップ2 - モデルの定義
拡張の効果を示すために、チュートリアル1のモデルにいくつかのシンプルな変換を追加します。
from tensorflow import keras
from tensorflow.keras import layers
these are a new feature in TF 2.2
from tensorflow.keras.layers.experimental import preprocessing
pretrained_base = tf.keras.models.load_model(
'../input/cv-course-models/cv-course-models/vgg16-pretrained-base',
)
pretrained_base.trainable = False
model = keras.Sequential([
# Preprocessing
preprocessing.RandomFlip('horizontal'), # flip left-to-right
preprocessing.RandomContrast(0.5), # contrast change by up to 50%
# Base
pretrained_base,
# Head
layers.Flatten(),
layers.Dense(6, activation='relu'),
layers.Dense(1, activation='sigmoid'),
])
で、訓練します。
model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['binary_accuracy'],
)
history = model.fit(
ds_train,
validation_data=ds_valid,
epochs=30,
verbose=0,
)
In [4]:
import pandas as pd
history_frame = pd.DataFrame(history.history)
history_frame.loc[:, ['loss', 'val_loss']].plot()
history_frame.loc[:, ['binary_accuracy', 'val_binary_accuracy']].plot();
チュートリアル1のモデルのトレーニングと検証の曲線はかなり早く乖離しました。これは、正則化が必要であることを示唆しています。このモデルの学習曲線はより近くに留まることができ、検証の損失と精度にわずかな改善が見られました。これは、データセットが実際に拡張から利益を得たことを示唆しています。