Logo Zephyrnet

Memahami Overfitting di ConvNets

Tanggal:

Pengantar

Overfitting di ConvNets merupakan tantangan dalam pembelajaran mendalam dan jaringan neural, saat model belajar terlalu banyak dari data pelatihan, sehingga menyebabkan performa buruk pada data baru. Fenomena ini terutama terjadi pada arsitektur saraf kompleks, yang dapat memodelkan hubungan yang rumit. Mengatasi overfitting di convnet sangat penting untuk membangun model jaringan neural yang andal. Artikel ini memberikan panduan untuk memahami dan memitigasi overfitting, memeriksa akar penyebab seperti kompleksitas model, data pelatihan yang terbatas, dan fitur-fitur yang mengganggu. Bagian ini juga membahas teknik untuk mencegah overfitting, seperti strategi augmentasi data dan metode regularisasi.

Saya akan merekomendasikan membaca artikel ini untuk pemahaman dasar terlalu pas, terlalu pas dan tradeoff varians bias.

Pelajari Tujuan

  • Pahami penyebab, konsekuensi, dan skenario overfitting Jaringan Konv.
  • Menafsirkan kurva pembelajaran untuk mendeteksi overfitting dan underfitting dalam model jaringan saraf.
  • Pelajari berbagai teknik untuk mengurangi overfitting, seperti penghentian awal, dropout, normalisasi batch, regularisasi, dan augmentasi data.
  • Terapkan teknik ini menggunakan TensorFlow dan Keras untuk melatih ConvNets pada kumpulan data CIFAR-10.
  • Analisis dampak berbagai teknik pada kinerja model dan generalisasi.

Daftar Isi

Skenario Umum untuk Overfitting di ConvNet

Mari kita lihat beberapa skenario umum overfitting di ConvNet:

Skenario1: Model Sangat Kompleks dengan Data Tidak Memadai

Penggunaan model yang sangat kompleks, seperti jaringan neural dalam, pada kumpulan data kecil dapat menyebabkan overfitting. Model mungkin menghafal contoh pelatihan daripada mempelajari pola umum. Misalnya, melatih jaringan neural dalam yang hanya berisi beberapa ratus gambar untuk tugas kompleks seperti pengenalan gambar dapat menyebabkan overfitting.

Konsekuensi

Model ini mungkin memiliki performa yang sangat baik pada data pelatihan, namun gagal melakukan generalisasi terhadap data baru yang tidak terlihat, sehingga menghasilkan performa yang buruk dalam aplikasi dunia nyata.

Bagaimana cara mengatasi masalah ini?

Dapatkan lebih banyak data pelatihan, Lakukan augmentasi gambar untuk menggeneralisasi kumpulan data kami. Mulailah dengan model yang tidak terlalu rumit dan jika kapasitasnya lebih kecil maka tingkatkan kompleksitasnya. 

Skenario 2: Pelatihan Berlebihan

Melatih model secara terus-menerus dalam jangka waktu yang terlalu lama dapat menyebabkan overfitting. Saat model melihat data pelatihan berulang kali, model mungkin mulai mengingatnya dibandingkan mempelajari pola yang mendasarinya.

Konsekuensi

Performa model mungkin tidak berubah atau bahkan menurun pada data yang tidak terlihat karena model tersebut semakin dikhususkan untuk set pelatihan.

Bagaimana cara mengatasi masalah ini?

Gunakan penghentian awal untuk menghindari model melakukan overfit dan menyimpan model terbaik. 

Skenario3: Mengabaikan regularisasi

Teknik regularisasi, seperti regularisasi L1 atau L2, digunakan untuk mencegah overfitting dengan memberikan penalti pada model yang kompleks. Mengabaikan atau menyetel parameter regularisasi dengan tidak tepat dapat menyebabkan overfitting.

Konsekuensi

Model mungkin menjadi terlalu rumit dan gagal menggeneralisasi data baru dengan baik, sehingga menghasilkan performa yang buruk di luar set pelatihan.

Bagaimana cara mengatasi masalah ini?

Menerapkan regularisasi, Validasi silang, Penyetelan parameter hiper. 

Berapa Kapasitas Model?

Kapasitas model mengacu pada ukuran dan kompleksitas pola yang dapat dipelajari. Untuk jaringan saraf, hal ini sangat ditentukan oleh berapa banyak neuron yang dimilikinya dan bagaimana mereka terhubung satu sama lain. Jika tampaknya jaringan Anda kekurangan data, Anda harus mencoba meningkatkan kapasitasnya.

Anda dapat meningkatkan kapasitas jaringan dengan membuatnya lebih luas (lebih banyak unit pada lapisan yang ada) atau dengan membuatnya lebih dalam (menambahkan lebih banyak lapisan). Jaringan yang lebih luas lebih mudah mempelajari hubungan yang lebih linier, sementara jaringan yang lebih dalam lebih menyukai hubungan yang lebih nonlinier. Mana yang lebih baik tergantung pada kumpulan datanya.

Interpretasi Kurva Pembelajaran

Keras menyediakan kemampuan untuk mendaftarkan panggilan balik saat pelatihan a model pembelajaran mendalam. Salah satu panggilan balik default yang didaftarkan saat melatih semua model pembelajaran mendalam adalah panggilan balik Riwayat. Ini mencatat metrik pelatihan untuk setiap zaman. Hal ini mencakup kerugian dan keakuratan (untuk masalah klasifikasi) serta kerugian dan keakuratan kumpulan data validasi jika ada yang ditetapkan.

Objek histori dikembalikan dari panggilan ke fungsi fit() yang digunakan untuk melatih model. Metrik disimpan dalam kamus di anggota riwayat objek yang dikembalikan.

Misalnya, Anda dapat mencantumkan metrik yang dikumpulkan dalam objek riwayat menggunakan cuplikan kode berikut setelah model dilatih:

# list all data in history
print(history.history.keys())

Keluaran:

['akurasi', 'kerugian', 'val_akurasi', 'val_loss']

Jenis Informasi

Anda mungkin menganggap informasi dalam data pelatihan ada dua jenis:

  • Sinyal: Sinyal adalah bagian yang menggeneralisasi, bagian yang dapat membantu model kita membuat prediksi dari data baru.
  • Kebisingan: Kebisingan adalah bagian yang hanya berlaku untuk data pelatihan; noise adalah semua fluktuasi acak yang berasal dari data di dunia nyata atau semua pola insidental dan non-informatif yang tidak dapat membantu model membuat prediksi. Kebisingan adalah bagian yang mungkin terlihat berguna tetapi sebenarnya tidak.

Saat kami melatih model, kami telah merencanakan kerugian pada set pelatihan dari waktu ke waktu. Untuk ini kami juga akan menambahkan plot data validasi. Plot ini kita sebut kurva pembelajaran. Untuk melatih model pembelajaran mendalam secara efektif, kita harus mampu menafsirkannya.

kurva belajar

Pada gambar di atas kita dapat melihat bahwa kerugian pelatihan menurun seiring bertambahnya epoch, namun kerugian validasi menurun pada awalnya dan meningkat seiring model mulai menangkap noise yang ada dalam kumpulan data. Sekarang kita akan melihat cara menghindari overfitting di ConvNets melalui berbagai teknik. 

Metode untuk Menghindari Overfitting

Sekarang kita telah melihat beberapa skenario dan cara menafsirkan kurva pembelajaran untuk mendeteksi overfitting. mari kita periksa beberapa metode untuk menghindari overfitting di jaringan saraf:

Metode 1: Gunakan lebih banyak data

Meningkatkan ukuran kumpulan data Anda dapat membantu model melakukan generalisasi dengan lebih baik karena model tersebut memiliki lebih banyak contoh yang beragam untuk dipelajari. Model akan menemukan pola-pola penting yang ada dalam kumpulan data dan mengabaikan noise saat model menyadari bahwa pola spesifik (noise) tersebut tidak ada di semua kumpulan data.

Metode 2: Berhenti Dini

Penghentian awal adalah teknik yang digunakan untuk mencegah overfitting dengan memantau performa model pada set validasi selama pelatihan. Pelatihan dihentikan ketika performa pada set validasi mulai menurun, yang menunjukkan bahwa model mulai mengalami overfit. Biasanya, set validasi terpisah digunakan untuk memantau performa, dan pelatihan dihentikan ketika performa belum meningkat selama jumlah periode tertentu.

Underfitting dan overfitting

Metode 3: Putus sekolah

Kita tahu bahwa overfitting disebabkan oleh jaringan yang mempelajari pola palsu (noise) dalam data pelatihan. Untuk mengenali pola palsu ini, jaringan sering kali mengandalkan kombinasi bobot yang sangat spesifik, semacam “konspirasi” bobot. Karena sangat spesifik, mereka cenderung rapuh: jika salah satunya dihilangkan maka konspirasi akan berantakan.

Inilah ide di balik putus sekolah. Untuk mematahkan konspirasi ini, kami secara acak mengeluarkan sebagian kecil dari unit masukan lapisan setiap langkah pelatihan, sehingga mempersulit jaringan untuk mempelajari pola palsu tersebut dalam data pelatihan. Sebaliknya, ia harus mencari pola yang luas dan umum, yang pola bobotnya cenderung lebih kuat. 

Anda juga dapat menganggap putus sekolah sebagai semacam kumpulan jaringan. Prediksi tidak lagi dibuat oleh satu jaringan besar, melainkan oleh komite jaringan yang lebih kecil. Individu-individu dalam komite cenderung melakukan berbagai jenis kesalahan, namun pada saat yang sama juga benar, menjadikan komite secara keseluruhan lebih baik daripada individu mana pun. (Jika Anda familiar dengan hutan acak sebagai kumpulan pohon keputusan, idenya sama.)

Overfitting di ConvNets

Metode4: Normalisasi Batch

Metode khusus berikutnya yang akan kita lihat melakukan “normalisasi batch” (atau “norma batch”), yang dapat membantu memperbaiki pelatihan yang lambat atau tidak stabil.

Dengan jaringan saraf, biasanya merupakan ide bagus untuk menempatkan semua data Anda pada skala yang sama, mungkin dengan sesuatu seperti StandardScaler atau MinMaxScaler dari scikit-learn. Alasannya adalah SGD akan menggeser bobot jaringan sebanding dengan seberapa besar aktivasi yang dihasilkan data. Fitur yang cenderung menghasilkan aktivasi dengan ukuran yang sangat berbeda dapat menyebabkan perilaku pelatihan menjadi tidak stabil.

Nah, kalau normalisasi data sebelum masuk ke jaringan itu baik, mungkin normalisasi di dalam jaringan juga akan lebih baik! Faktanya, kami memiliki jenis lapisan khusus yang dapat melakukan hal ini, lapisan normalisasi batch. Lapisan normalisasi batch melihat setiap batch yang masuk, pertama-tama menormalkan batch dengan rata-rata dan deviasi standarnya sendiri, lalu juga menempatkan data pada skala baru dengan dua parameter penskalaan ulang yang dapat dilatih. Batchnorm, pada dasarnya, melakukan semacam penskalaan ulang inputnya yang terkoordinasi.

Paling sering, batchnorm ditambahkan sebagai bantuan pada proses optimasi (meskipun terkadang juga dapat membantu kinerja prediksi). Model dengan batchnorm cenderung memerlukan waktu yang lebih sedikit untuk menyelesaikan pelatihan. Selain itu, batchnorm juga dapat memperbaiki berbagai masalah yang dapat menyebabkan pelatihan “macet”. Pertimbangkan untuk menambahkan normalisasi batch ke model Anda, terutama jika Anda mengalami masalah selama pelatihan.

Metode5: Regularisasi L1 dan L2

Regularisasi L1 dan L2 adalah teknik yang digunakan untuk mencegah overfitting dengan memberikan penalti pada bobot yang besar di jaringan saraf. Regularisasi L1 menambahkan istilah penalti pada fungsi kerugian yang sebanding dengan nilai absolut bobot. Hal ini mendorong ketersebaran dalam bobot dan dapat mengarah pada pemilihan fitur. Regularisasi L2, juga dikenal sebagai peluruhan bobot, menambahkan suku penalti yang sebanding dengan kuadrat bobot ke fungsi kerugian. Hal ini mencegah beban menjadi terlalu besar dan mendorong distribusi beban agar tersebar lebih merata.

Pilihan antara regularisasi L1 dan L2 sering kali bergantung pada masalah spesifik dan properti model yang diinginkan.

Memiliki nilai regularisasi L1/L2 yang besar akan menyebabkan model tidak belajar dengan cepat dan mencapai titik tertinggi dalam pembelajaran yang menyebabkan model menjadi underfit. 

Metode 6: Augmentasi Data

Cara terbaik untuk meningkatkan performa model pembelajaran mesin adalah dengan melatihnya pada lebih banyak data. Semakin banyak contoh yang harus dipelajari oleh model, semakin baik model tersebut mengenali perbedaan gambar mana yang penting dan mana yang tidak. Lebih banyak data membantu model untuk menggeneralisasi dengan lebih baik.

Salah satu cara mudah untuk mendapatkan lebih banyak data adalah dengan menggunakan data yang sudah Anda miliki. Jika kita dapat mengubah gambar dalam kumpulan data kita dengan cara yang mempertahankan kelasnya (contoh: klasifikasi Digit MNIST jika kita mencoba augment 6 maka akan sulit membedakan antara 6 dan 9), kita dapat mengajarkan pengklasifikasi kita untuk mengabaikan transformasi semacam itu. Misalnya, apakah sebuah mobil menghadap ke kiri atau ke kanan dalam sebuah foto tidak mengubah fakta bahwa itu adalah Mobil dan bukan Truk. Jadi, jika kita menambah data pelatihan dengan gambar yang dibalik, pengklasifikasi kita akan mengetahui bahwa “kiri atau kanan” adalah perbedaan yang harus diabaikan.

Dan itulah ide di balik augmentasi data: tambahkan beberapa data palsu tambahan yang terlihat cukup mirip dengan data asli dan pengklasifikasi Anda akan meningkat. 

Ingat, kunci untuk menghindari overfitting adalah memastikan model Anda dapat digeneralisasi dengan baik. Selalu periksa performa model Anda pada set validasi, bukan hanya set pelatihan.

Implementasi Metode Di Atas dengan Data

Mari kita jelajahi langkah-langkah penerapan metode di atas:

Langkah1: Memuat Perpustakaan yang Diperlukan

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ModelCheckpoint
import keras
from keras.preprocessing import image
from keras import models, layers, regularizers
from tqdm import tqdm
import warnings
warnings.filterwarnings(action='ignore')

Langkah2: Memuat Kumpulan Data dan Pemrosesan Awal

#Here all the images are in the form of a numpy array
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0

Langkah3: Mempelajari Kumpulan Data

x_train.shape, y_train.shape, x_test.shape, y_test.shape 

Keluaran:

Keluaran
np.unique(y_train)

Keluaran:

Keluaran
#These labels are in the order and taken from the documentaion
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

Langkah4: Memvisualisasikan gambar Dari Kumpulan Data

def show_image(IMG_INDEX):
    plt.imshow(x_train[20] ,cmap=plt.cm.binary)
    plt.xlabel(class_names[y_train[IMG_INDEX][0]])
    plt.show()
show_image(20)
Overfitting di ConvNets
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
model.summary()

Sekarang mari kita menginisialisasi parameter hiper dan mengkompilasi model dengan pengoptimal, fungsi kerugian, dan metrik evaluasi.


train_hyperparameters_config={'optim':keras.optimizers.Adam(learning_rate=0.001),
                             'epochs':20,
                              'batch_size':16
                             }
model.compile(optimizer=train_hyperparameters_config['optim'],
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])

Langkah6: Model Pelatihan

history = model.fit(x_train, y_train, 
                        epochs=train_hyperparameters_config['epochs'], 
                        batch_size=train_hyperparameters_config['batch_size'], 
                        verbose=1,
                        validation_data=(x_test, y_test))

Langkah7: Evaluasi Model

Ini akan memberi tahu kita informasi yang terkandung dalam objek sejarah dan kita menggunakannya untuk membuat kurva informasi.

print(history.history.keys()) 
def learning_curves(history):
# Plotting Accuracy
    plt.figure(figsize=(14, 5))  # Adjust the figure size as needed
    plt.subplot(1, 2, 1)  # Subplot with 1 row, 2 columns, and index 1
    plt.plot(history.history['accuracy'], label='train_accuracy', marker='s', markersize=4)
    plt.plot(history.history['val_accuracy'], label='val_accuracy', marker='*', markersize=4)
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend(loc='lower right')

    # Plotting Loss
    plt.subplot(1, 2, 2)  # Subplot with 1 row, 2 columns, and index 2
    plt.plot(history.history['loss'], label='train_loss', marker='s', markersize=4)
    plt.plot(history.history['val_loss'], label='val_loss', marker='*', markersize=4)
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend(loc='lower right')

    plt.show()
learning_curves(history)
Overfitting di ConvNets

Dari kurva kita dapat melihat bahwa akurasi validasi mencapai titik tertinggi setelah epoch ke-4 dan model mulai menangkap noise. Oleh karena itu kami akan menerapkan penghentian awal untuk menghindari model overfitting dan mengembalikan bobot terbaik berdasarkan val_loss. Kami akan menggunakan val_loss untuk memantau penghentian awal saat jaringan saraf kami mencoba mengurangi kerugian menggunakan pengoptimal. Akurasi dan Akurasi validasi bergantung pada ambang batas (Probabilitas untuk memisahkan kelas – biasanya 0.5 untuk klasifikasi biner), jadi jika kumpulan data kita tidak seimbang, maka akan terjadi kerugian yang harus kita khawatirkan dalam sebagian besar kasus. 

Langkah 8: Menerapkan Penghentian Dini

Karena kami tidak khawatir model kami akan overfit karena penghentian lebih awal akan mencegah model kami terjadi. Merupakan pilihan yang baik untuk memilih jumlah zaman yang lebih tinggi dan kesabaran yang sesuai. Sekarang kita akan menggunakan arsitektur model yang sama dan berlatih dengan callback penghentian awal. 

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
model.summary()

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)

def model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config):
    model.compile(optimizer=train_hyperparameters_config['optim'],
                      loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                      metrics=['accuracy'])
    ht = model.fit(x_train, y_train, 
                            epochs=train_hyperparameters_config['epochs'], 
                            batch_size=train_hyperparameters_config['batch_size'],
                            callbacks=[callback],
                            verbose=1,
                            validation_data=(x_test, y_test))
    return ht

ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Overfitting di ConvNets

Untuk mengetahui bobot terbaik yang telah diambil model tersebut. 

print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Langkah9: Meningkatkan Kompleksitas Model

Karena model kami tidak berperforma baik dan tidak sesuai karena tidak mampu menangkap cukup data. Kita harus meningkatkan kompleksitas model dan mengevaluasinya. 

model = models.Sequential()

model.add(layers.Conv2D(128, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
model.summary()
Keluaran

Terlihat ada peningkatan pada total parameter. Ini akan membantu menemukan hubungan yang lebih kompleks dalam model kita. Catatan: Kumpulan data kami terdiri dari gambar 32X32; ini adalah gambar yang relatif kecil. Oleh karena itu, menggunakan model yang lebih kompleks di awal pasti akan membuat model tersebut overfit sehingga kita cenderung meningkatkan kompleksitas model secara perlahan.

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)

learning_curves(ht)
Overfitting di ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Dari grafik di atas kita dapat dengan jelas mengatakan bahwa model tersebut overfitting, oleh karena itu kita akan menggunakan metode lain yang disebut normalisasi Drop out dan normalisasi Batch.

Langkah 10: Menggunakan Lapisan Dropout dan Lapisan Normalisasi Batch

model = models.Sequential()

model.add(layers.Conv2D(128, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.3))

model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.3))

model.add(layers.Dense(10, activation='softmax'))
model.summary()
Keluaran
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Overfitting di ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Dari grafik pembelajaran kita dapat melihat bahwa model mengalami overfitting bahkan dengan normalisasi batch dan lapisan dropout. Oleh karena itu, alih-alih menambah kompleksitas tetapi menambah jumlah filter. Kami akan menambahkan lebih banyak lapisan konvolusi untuk mengekstrak lebih banyak fitur.

Langkah11: Meningkatkan Lapisan Konvolusi

Kurangi parameter yang dapat dilatih tetapi tingkatkan lapisan konvolusi untuk mengekstrak lebih banyak fitur.

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))

model.add(layers.Dense(10, activation='softmax'))

model.summary()
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
keluaran
learning_curves(ht)
Overfitting di ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Dari keluaran dan kurva pembelajaran di atas kita dapat menyimpulkan bahwa model telah berkinerja sangat baik dan menghindari overfitting. Akurasi pelatihan dan akurasi validasi sangat dekat. Dalam skenario ini kita tidak memerlukan lebih banyak metode untuk mengurangi overfitting. Namun kami akan mengeksplorasi regularisasi L1/L2. 

Langkah 12: Menggunakan Regularisasi L1/L2

from tensorflow.keras import regularizers

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l2(0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu', kernel_regularizer=regularizers.l1_l2(0.0005, 0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(10, activation='softmax'))

model.summary()
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 7,
    'epochs': 70,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Overfitting di ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Sekarang kita dapat melihat bahwa regularisasi L1/L2 bahkan setelah menggunakan skor penalti rendah sebesar 0.0001, membuat model kita kurang sesuai sebesar 4%. Oleh karena itu disarankan untuk menggunakan semua metode secara bersamaan dengan hati-hati. Karena Normalisasi dan Regularisasi Batch memengaruhi model dengan cara yang sama, kita tidak memerlukan regularisasi L1/L2. 

Langkah13: Augmentasi Data

Kami akan menggunakan ImageDataGenerator dari tensorflow keras.

# creates a data generator object that transforms images
datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')

# pick an image to transform
test_img = x_train[20]
img = image.img_to_array(test_img)  # convert image to numpy arry
img = img.reshape((1,) + img.shape)  # reshape image

i = 0

for batch in datagen.flow(img, save_prefix='test', save_format='jpeg'):  # this loops runs forever until we break, saving images to current directory with specified prefix
    plt.figure(i)
    plot = plt.imshow(image.img_to_array(batch[0]))
    i += 1
    if i > 4:  # show 4 images
        break

plt.show()
Overfitting di ConvNets

Ini adalah empat gambar yang diperbesar dan satu gambar asli.

# Create an instance of the ImageDataGenerator
datagen = ImageDataGenerator(
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode='nearest'
)

# Create an iterator for the data generator
data_generator = datagen.flow(x_train, y_train, batch_size=32)

# Create empty lists to store the augmented images and labels
augmented_images = []
augmented_labels = []

# Loop over the data generator and append the augmented data to the lists
num_batches = len(x_train) // 32
progress_bar = tqdm(total=num_batches, desc="Augmenting data", unit="batch")

for i in range(num_batches):
    batch_images, batch_labels = next(data_generator)
    augmented_images.append(batch_images)
    augmented_labels.append(batch_labels)
    progress_bar.update(1)

progress_bar.close()

# Convert the lists to NumPy arrays
augmented_images = np.concatenate(augmented_images, axis=0)
augmented_labels = np.concatenate(augmented_labels, axis=0)

# Combine the original and augmented data
x_train_augmented = np.concatenate((x_train, augmented_images), axis=0)
y_train_augmented = np.concatenate((y_train, augmented_labels), axis=0)
keluaran

Kami telah menggunakan perpustakaan tqdm untuk mengetahui kemajuan augmentasi kami.

x_train_augmented.shape, y_train_augmented.shape
Keluaran

Ini adalah kumpulan data kami setelah augmentasi. Sekarang mari gunakan kumpulan data ini dan latih model kita.

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))

model.add(layers.Dense(10, activation='softmax'))

model.summary()

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 10,
    'epochs': 70,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)

ht=model_train(model, x_train_augmented, y_train_augmented, x_test, y_test, train_hyperparameters_config)


learning_curves(ht)
Overfitting di ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Kita dapat melihat modelnya lebih umum dan terjadi penurunan kerugian. Kami juga mendapatkan akurasi validasi yang lebih baik. Oleh karena itu, augmentasi data telah meningkatkan akurasi model kami. 

Kesimpulan

Overfitting adalah masalah umum dalam pembelajaran mendalam, terutama dengan arsitektur jaringan neural yang kompleks seperti ConvNets. Praktisi dapat mencegah overfitting di ConvNets dengan memahami akar penyebabnya dan mengenali skenario terjadinya overfitting. Teknik seperti penghentian awal, penghentian, normalisasi batch, regularisasi, dan augmentasi data dapat membantu mengurangi masalah ini. Penerapan teknik ini pada kumpulan data CIFAR-10 menunjukkan peningkatan yang signifikan dalam generalisasi dan kinerja model. Menguasai teknik-teknik ini dan memahami prinsip-prinsipnya dapat menghasilkan model jaringan saraf yang kuat dan andal.

Tanya Jawab Umum (FAQ)

Q1. Apa itu overfitting dan mengapa ini menjadi masalah dalam deep learning? 

A. Overfitting terjadi ketika model mempelajari data pelatihan dengan terlalu baik, termasuk noise dan pola yang tidak relevan, sehingga menghasilkan performa yang buruk pada data baru yang tidak terlihat. Hal ini menjadi masalah karena model yang overfitted gagal melakukan generalisasi secara efektif, sehingga membatasi kegunaan praktisnya.

Q2. Bagaimana cara mendeteksi overfitting pada model jaringan saraf saya?

A. Anda dapat mendeteksi overfitting di ConvNets dengan menafsirkan kurva pembelajaran, yang memplot metrik pelatihan dan validasi (misalnya, kehilangan, akurasi) selama beberapa waktu. Jika metrik validasi berhenti meningkat atau mulai menurun sementara metrik pelatihan terus meningkat, ini merupakan tanda overfitting.

Q3. Apa yang dimaksud dengan penghentian dini, dan bagaimana hal ini membantu mencegah overfitting?

A. Penghentian awal adalah teknik yang memantau performa model pada set validasi selama pelatihan dan menghentikan proses pelatihan ketika performa pada set validasi mulai menurun, yang mengindikasikan overfitting. Ini membantu mencegah model mengalami overfitting dengan menghentikan pelatihan pada waktu yang tepat.

Q4. Bagaimana augmentasi data membantu mengurangi overfitting? 

A. Augmentasi data adalah proses menghasilkan data pelatihan sintetik baru dengan menerapkan transformasi (misalnya membalik, memutar, menskalakan) pada data yang sudah ada. Hal ini membantu model menggeneralisasi lebih baik dengan memaparkannya pada contoh yang lebih beragam, sehingga mengurangi risiko overfitting di ConvNets pada data pelatihan yang terbatas.

tempat_img

Intelijen Terbaru

tempat_img