40 گام به سوی آینده‌ای هوشمند - مجموعه وبینارهای رایگان در حوزه هوش مصنوعی
Filter by دسته‌ها
chatGTP
آموزش هوش مصنوعی و انواع آن
آموزش‌های پایه‌ای هوش مصنوعی
اصول هوش مصنوعی
پایتون و ابزارهای یادگیری عمیق
کتابخانه‌ های یادگیری عمیق
یادگیری با نظارت
یادگیری بدون نظارت
یادگیری تقویتی
یادگیری عمیق
یادگیری نیمه نظارتی
آموزش‌های پیشرفته هوش مصنوعی
بینایی ماشین
پردازش زبان طبیعی
پردازش گفتار
چالش‌های عملیاتی
داده کاوی و بیگ دیتا
رایانش ابری و HPC
سیستم‌‌های امبدد
علوم شناختی
دیتاست
اخبار
تیتر یک
رسانه‌ها
آموزش پردازش زبان طبیعی
آموزش علوم داده
اینفوگرافیک
پادکست
ویدیو
رویدادها
کاربردهای هوش مصنوعی
کسب‌و‌کار
تحلیل بازارهای هوش مصنوعی
کارآفرینی
هوش مصنوعی در ایران
هوش مصنوعی در جهان
 تعمیم پذیری و بهینه‌سازی : تکنیک‌هایی برای جلوگیری از بیش‌برازش و کم‌برازش

تعمیم پذیری و بهینه‌سازی : تکنیک‌هایی برای جلوگیری از بیش‌برازش و کم‌برازش

محور اصلی یادگیری ماشین، برقرای توازن درست بین بهینه‌سازی optimization و تعمیم پذیری generalization است. منظور از بهینه‌سازی، تنظیم مدل برای دستیابی به بهترین عملکرد ممکن است؛ تعمیم پذیری به عمومی‌سازی مدل اشاره دارد به نحوی که بتواند روی داده‌های جدید نیز عملکرد خوبی داشته باشد. همانطور که می‌بینید، مفاهیم بهینه‌سازی و تعمیم پذیری با یکدیگر همبستگی دارند.

بدیهی است وقتی مدل هنوز در حال آموزش است، یعنی زمانی که شبکه هنوز تمام الگو را به صورت کامل مدل‌سازی نکرده، به صورت طبیعی منجربه خطا کمتر بر روی داده­‌های آموزش (و همچنین منجر به خطای کمتر بر روی داده­های تست) می­‌گردد؛ که تحت عنوان کم‌برازش underfitting شناخته می­‌شود. اما بعد از چند دور آموزش، تعمیم پذیری دیگر بهبود نمی‌یابد و در نتیجه، مدل شروع به یادگیری الگویی برای برازش داده‌های آموزشی می‌کند؛ به این قضیه بیش‌برازش Overfitting گفته می‌شود. بیش‌برازش چیز خوبی نیست، چون به مدل اجازه نمی‌دهد عملکرد خوبی روی داده‌های جدید داشته باشد.

در این نوشتار چند تکنیک برای مقابله با مشکل بیش‌برازش معرفی می‌کنیم.

افزایش تعداد داده‌های آموزشی

یک راه برای حل مشکل بیش‌برازش، داشتن بی‌نهایت داده‌ی آموزشی است! بیشتر بودن داده‌های آموزشی به معنی تعمیم پذیری بهتر مدل است. اما افزایش داده‌های آموزشی همیشه امکان‌پذیر نیست و گاهی باید با همان مجموعه­ داده‌­ای که در دست دارید کار خود را انجام دهید. در این صورت، بهتر است تنها روی الگوهای اصلی تمرکز کنید؛ این الگوها تعمیم پذیری کلی خوبی به شما ارائه می‌دهند.

کاهش اندازه‌ی شبکه

آسان‌ترین راه برای جلوگیری از بیش‌برازش، کاهش اندازه‌ی مدل، یعنی کاهش تعداد لایه‌ها یا گره‌های موجود در لایه‌های آن است؛ اندازه را با نام «ظرفیت مدل» نیز می‌شناسند. به صورت تئوری، هر چه ظرفیت مدل بیشتر باشد، یادگیری بهتر اتفاق می‌افتد. اما در این صورت مدل دچار بیش‌برازش روی داده‌های آموزشی می‌شود. بنابراین می‌توان گفت مدل‌های «قوی‌تر» (با ظرفیت بالا) لزوماً تعمیم پذیری بالاتر و به تبع عملکرد بهتری ندارند. متأسفانه یک فرمول جادویی وجود ندارد که بتوان به وسیله‌ی آن تعداد مناسب لایه‌ها و گره‌های مدل را تعیین کرد. کاری که می‌توان انجام داد امتحان معماری‌های گوناگون برای مدل و ارزیابی آن‌هاست تا زمانی که اندازه‌ی مناسب و ایده‌آل پیدا شود.

این‌جا برای مثال از دیتاست IMDB استفاده می‌کنیم؛ ابتدا داده‌ها را آماده می‌کنیم:

from keras.datasets import imdb
import numpy as np

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

def vectorize_sequences(sequences, dimension=10000):
    # Padding
    results = np.zeros((len(sequences), dimension))
    for i, sequence in enumerate(sequences):
        results[i, sequence] = 1.  
    return results

# vectorized training data
x_train = vectorize_sequences(train_data)
# vectorized test data
x_test = vectorize_sequences(test_data)
# vectorized labels
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')

برای توضیح و نمایش آن‌چه گفته شد دو مدل با اندازه‌های مختلف می‌سازیم؛

مدل بزرگ‌تر (bigger):

from keras import models
from keras import layersbigger_model = models.Sequential()bigger_model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
bigger_model.add(layers.Dense(16, activation='relu'))
bigger_model.add(layers.Dense(1, activation='sigmoid'))
bigger_model.compile(optimizer='rmsprop',loss='binary_crossentropy',
metrics=['acc'])

 

مدل کوچک‌تر (Smaller):

smaller_model = models.Sequential()
smaller_model.add(layers.Dense(4, activation='relu', input_shape=(10000,)))
smaller_model.add(layers.Dense(4, activation='relu'))
smaller_model.add(layers.Dense(1, activation='sigmoid'))
smaller_model.compile(optimizer='rmsprop',
                      loss='binary_crossentropy',
                      metrics=['acc'])

 

حال می‌خواهیم توابع زیان اعتبارسنجی را برای هر دو شبکه‌ی کوچک و بزرگ محاسبه کنیم:

با استفاده از این کد می‌توانیم یافته‌ها را به تصویر درآوریم:

bigger_hist = bigger_model.fit(x_train, y_train,
                                   epochs=20,
                                   batch_size=512,
                                   validation_data=(x_test, y_test))
smaller_hist = smaller_model.fit(x_train, y_train,
                                   epochs=20,
                                   batch_size=512,
                                   validation_data=(x_test, y_test))
import matplotlib.pyplot as pltepochs = range(1, 21)
bigger_val_loss = bigger_hist.history['val_loss']
smaller_val_loss = smaller_hist.history['val_loss']plt.plot(epochs, bigger_val_loss, 'b+', label='bigger model')
plt.plot(epochs, smaller_val_loss, 'bo', label='Smaller model')
plt.xlabel('Epochs')
plt.ylabel('Validation loss')
plt.legend()plt.show()
[irp posts=”15709″]

تعمیم پذیری

همانطور که مشاهده می‌کنید، مدل بزرگ‌تر خیلی سریع‌تر از مدل کوچک شروع به بیش‌برازش کرده است، به نحوی که زیان اعتبارسنجی بعد از دور هشتم به میزان چشم‌گیری افزایش می‌یابد.

حال برای درک بهتر آن‌چه گفته شد، مدلی با ظرفیت خیلی بیشتر می‌سازیم و آن را با مدل بزرگ‌تر (bigger) بالا مقایسه می‌کنیم. اسم این مدل را مدل خیلی بزرگ‌تر (much bigger model) می‌گذاریم:

much_bigger_model = models.Sequential()
much_bigger_model.add(layers.Dense(512, activation='relu', input_shape=(10000,)))
much_bigger_model.add(layers.Dense(512, activation='relu'))
much_bigger_model.add(layers.Dense(1, activation='sigmoid'))
much_bigger_model.compile(optimizer='rmsprop', loss='binary_crossentropy',
                     metrics=['acc'])
much_bigger_model_hist = much_bigger_model.fit(x_train, y_train,
                      epochs=20,batch_size=512,
                       validation_data=(x_test, y_test))

 

بدین ترتیب می‌توانیم مدل‌ها را مقایسه کنیم:

much_bigger_model_val_loss = much_bigger_model_hist.history['val_loss']plt.plot(epochs, bigger_val_loss, 'b+', label='Bigger model')
plt.plot(epochs, much_bigger_model_val_loss, 'bo', label='Much Bigger model')
plt.xlabel('Epochs')
plt.ylabel('Validation loss')
plt.legend()plt.show()

 

نمودار مربوطه چنین شکلی خواهد داشت:

تعمیم پذیری

همانطور که مشاهده می‌کنید، «مدل خیلی بزرگ‌تر» تقریباً در همان ابتدای کار شروع به بیش‌برازش می‌کند.

حال توابع زیان آموزشی این مدل‌ها را با هم مقایسه می‌کنیم:

bigger_train_loss = bigger_hist.history['loss']much_bigger_model_train_loss = much_bigger_model_hist.history['loss']plt.plot(epochs, bigger_train_loss, 'b+', label='Bigger model')
plt.plot(epochs, much_bigger_model_train_loss, 'bo', label='Much Bigger model')
plt.xlabel('Epochs')
plt.ylabel('Training loss')
plt.legend()plt.show()

 

تعمیم پذیری

پس می‌توان اینطور نتیجه گرفت که هرچه شبکه بزرگ‌تر باشد، زودتر به زیان آموزشی صفر می‌رسد. به بیان دیگر، ظرفیت بالاتر به معنای یبش‌برازش روی داده‌های آموزشی است.

منظم‌سازی

همانطور که در قسمت قبلی مشاهده کردید، احتمال بیش‌برازش در مدل‌های کوچک در مقایسه با مدل‌های پیچیده، پایین‌تر است. منظور از مدل ساده، مدلی است که تعداد پارامترهای آن کمتر و بنابراین آنتروپی مقادیر آن در کل پایین‌تر است. برای حل این مشکل می‌توان توزیع وزن‌ها را انطباق داد یا به عبارت دیگر، منظم‌سازی regularization کرد. این کار اغلب از طریق افزودن توابع زیان به شبکه انجام می‌شود. دو نوع منظم‌سازی وجود دارد:

  • منظم‌سازی L1: تابع هزینه‌ی اضافه شده متناسب با مقدار قدر مطلق ضرایب وزن‌هاست.
  • منظم‌سازی L2: تابع هزینه‌ی اضافه شده متناسب با مربع مقادیر ضرایب وزن‌هاست.

همانطور که در کد پایین مشاهده می‌کنید، منظم‌سازی یکی از پارامترهای Keras است:

from keras import regularizers

l2_model = models.Sequential()
l2_model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
                          activation='relu', input_shape=(10000,)))
l2_model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
                          activation='relu'))
l2_model.add(layers.Dense(1, activation='sigmoid'))l2_model.compile(optimizer='rmsprop',
                 loss='binary_crossentropy',
                 metrics=['acc'])

 

با استفاده از این کد می‌توان عملکرد را مشاهده کرد:

l2_model_hist = l2_model.fit(x_train, y_train,
                             epochs=20,
                             batch_size=512,
                             validation_data=(x_test, y_test))

 

سپس بدین طریق نمودار مربوطه را رسم می‌کنیم:

l2_model_val_loss = l2_model_hist.history['val_loss']plt.plot(epochs, bigger_val_loss, 'b+', label='Bigger model')
plt.plot(epochs, l2_model_val_loss, 'bo', label='L2-regularized model')
plt.xlabel('Epochs')
plt.ylabel('Validation loss')
plt.legend()
plt.show()
[irp posts=”15659″]

تعمیم پذیری

همانطور که مشاهده می‌کنید، مدل با منظم‌سازی L2 در مقایسه با مدل بزرگ‌تر (bigger در قسمت قبلی) کمتر مستعد بیش‌برازش است.

استفاده از تکنیک Dropout

Dropout یکی از کارآمدترین روش‌های منظم‌سازی به شمار می‌رود. Dropout را می‌توان صفر کردن به صورت تصادفی یا خارج کردن برخی از ویژگی‌های لایه تعریف کرد که به صورت تصادفی و در طول فرآیند آموزش انجام می‌شود. نکته‌ی کلیدی که باید به آن توجه داشت این است که dropout را تنها می‌توان هنگام آموزش انجام داد؛ زیرا در مرحله‌ی آزمایش، مقادیر حذف نمی‌شوند، بلکه تنها می‌توان آن‌ها را مقیاس‌بندی کرد. نرخ dropout معمول بین 2/0 و 5/0 است.

در keras می‌توانید تابع dropout را در لایه‌ی dropout که بلافاصله بعد از لایه‌ی موردنظر قرار می‌گیرد، اضافه کنید. به این کد توجه کنید:

model.add(layers.Dropout(0.5))
drop_model = models.Sequential()
drop_model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
drop_model.add(layers.Dropout(0.5))
drop_model.add(layers.Dense(16, activation='relu'))
drop_model.add(layers.Dropout(0.5))
drop_model.add(layers.Dense(1, activation='sigmoid'))drop_model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['acc'])

 

نمودار مربوطه را رسم می‌کنیم:

drop_model_val_loss = drop_model_hist.history['val_loss']

plt.plot(epochs, bigger_val_loss, 'b+', label='Original model')
plt.plot(epochs, drop_model_val_loss, 'bo', label='Dropout-regularized model')
plt.xlabel('Epochs')
plt.ylabel('Validation loss')
plt.legend()
plt.show()

 

تعمیم پذیری

جمع‌بندی

برای جلوگیری از مشکل بیش‌برازش در شبکه‌های یادگیری عمیق، چندین روش کارآمد وجود دارد:

  • افزایش شمار داده‌های آموزشی
  • ساده‌ کردن شبکه یا تنظیم ظرفیت آن (اگر ظرفیت بیشتر از حد لازم باشد، احتمال بیش‌برازش افزایش می‌یابد)
  • منظم‌سازی
  • استفاده از تکنیک dropout

میانگین امتیاز / 5. تعداد ارا :

مطالب پیشنهادی مرتبط

اشتراک در
اطلاع از
0 نظرات
بازخورد (Feedback) های اینلاین
مشاهده همه دیدگاه ها
[wpforms id="48325"]