Kodax

Data Augmentation — التعلم العميق

زيادة البيانات (Data Augmentation)

بيانات أكثر هي أفضل علاج للحفظ، لكن جمعها مكلف. الحيلة: توليد نسخ معدّلة واقعياً من الصور الموجودة. قطة مقلوبة أفقياً أو مزاحة قليلاً ما زالت قطة، والشبكة تتعلم أن هذه التغييرات لا تغيّر الفئة.

التحويلات الشائعة

| التحويل | طبقة Keras | ملاحظة |

|---|---|---|

| قلب أفقي | RandomFlip("horizontal") | ❌ للنصوص والأرقام (2 مقلوبة ليست 2) |

| دوران | RandomRotation(0.1) | 0.1 = ±10% من دورة كاملة (±36°) |

| تكبير | RandomZoom(0.1) | |

| إزاحة | RandomTranslation(0.1, 0.1) | |

| تباين وسطوع | RandomContrast(0.2)، RandomBrightness(0.2) | ظروف إضاءة مختلفة |

اختر حسب المجال

- صور طبيعية: قلب أفقي، دوران بسيط، تكبير.

- أرقام وحروف مكتوبة: لا قلب؛ دوران وإزاحة بسيطان فقط.

- صور طبية: بحذر شديد — قلب صورة صدر يجعل القلب في الجهة الخطأ!

- القاعدة: هل يستطيع إنسان تصنيف الصورة المعدّلة بنفس الإجابة بلا تردد؟

داخل النموذج

from tensorflow import keras
from tensorflow.keras import layers

augment = keras.Sequential([
    layers.RandomFlip("horizontal"),
    layers.RandomRotation(0.05),
    layers.RandomZoom(0.1),
])
model = keras.Sequential([
    keras.Input(shape=(32, 32, 3)),
    augment,                          # تعمل أثناء التدريب فقط
    layers.Rescaling(1 / 255),
    layers.Conv2D(32, 3, activation="relu"),
    layers.GlobalAveragePooling2D(),
    layers.Dense(10, activation="softmax"),
])

- كل epoch يرى نسخاً مختلفة عشوائياً من كل صورة.

- طبقات Random* تتعطل تلقائياً في evaluate و predict: الاختبار يجب أن يكون على صور حقيقية غير معدّلة.

- ImageDataGenerator القديمة مُهملة في Keras 3 — استخدم هذه الطبقات.

الفكرة بـ NumPy

import numpy as np

rng = np.random.default_rng(0)
img = np.arange(16).reshape(4, 4)
flipped = img[:, ::-1]                               # قلب أفقي
shifted = np.roll(img, shift=1, axis=1)              # إزاحة بكسل واحد
noisy = img + rng.normal(0, 0.5, img.shape)          # ضوضاء خفيفة
print(img, flipped, shifted, noisy.round(1), sep="\n\n")

توقعات واقعية

- يبطئ انخفاض خسارة التدريب (المهمة أصعب)، لكن الفجوة بين التدريب والتحقق تصغر.

- يحتاج غالباً epochs أكثر.

- لا يعوّض بيانات منحازة: إذا كانت كل صور القطط داخلية، لن يعلّم القلبُ النموذجَ القطط في الحدائق.

تمرين

في المثال الكامل درّب نفس الشبكة مرتين (مع الزيادة وبدونها) لـ 10 epochs، وقارن الفجوة بين دقة التدريب والتحقق.

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# ===== Data Augmentation Layer =====
data_augmentation = keras.Sequential([
    layers.RandomFlip("horizontal"),
    layers.RandomRotation(0.1),
    layers.RandomZoom(0.1),
    layers.RandomTranslation(0.1, 0.1),
])

# ===== دمج مع النموذج =====
model = keras.Sequential([
    # Augmentation (تدريب فقط)
    data_augmentation,
    
    # CNN
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(10, activation='softmax')
])

# ملاحظة: ImageDataGenerator أسلوب قديم مُهمل في Keras 3؛ طبقات Random* أعلاه هي البديل الحديث
# وتعمل داخل النموذج (على المعالج الرسومي) وتتعطل تلقائياً أثناء التقييم والتنبؤ.

# ===== عرض الـ Augmentation =====
import matplotlib.pyplot as plt

(X_train, y_train), _ = keras.datasets.cifar10.load_data()

plt.figure(figsize=(10, 4))
for i in range(5):
    augmented = data_augmentation(X_train[0:1])
    plt.subplot(1, 5, i+1)
    plt.imshow(augmented[0].numpy().astype('uint8'))
    plt.axis('off')
plt.suptitle('Data Augmentation Examples')
plt.show()
اختبر فهمك