شکل ۱۱-۵ - استفاده مجدد از لایههای pretrained در یک مسئله جدید.
انتخاب لایههایی که باید دوباره استفاده شوند
لایه خروجی مدل اصلی معمولاً برای وظیفه جدید مناسب نیست و احتمالاً حتی تعداد خروجیهای درستی ندارد، بنابراین باید جایگزین شود. لایههای پنهان بالایی هم معمولاً نسبت به لایههای پایین قابلیت reuse کمتری دارند، چون ویژگیهای سطحبالای مورد نیاز مسئله جدید ممکن است با مسئله اصلی تفاوت زیادی داشته باشند. هدف این است که تعداد مناسبی از لایههای پایین را نگه داریم.
در شروع بهتر است همه لایههای reuseشده را freeze کنیم؛ یعنی وزنهایشان trainable نباشد و gradient descent آنها را تغییر ندهد. سپس مدل را آموزش میدهیم و عملکرد را میسنجیم. در مرحله بعد میتوان یک یا دو لایه پنهان بالایی را unfreeze کرد تا backpropagation آنها را برای مسئله جدید fine-tune کند. هرچه داده آموزشی بیشتری داشته باشیم، لایههای بیشتری را میتوان باز کرد. هنگام unfreeze کردن بهتر است نرخ یادگیری کاهش یابد تا وزنهای از قبل تنظیمشده تخریب نشوند.
اگر با داده کم هنوز عملکرد مناسب نیست، میتوان لایههای پنهان بالایی را حذف کرد و لایههای باقیمانده را دوباره freeze کرد. این فرایند را تا یافتن تعداد مناسب لایههای reuseشده تکرار میکنیم. با داده فراوان، بهجای حذف لایههای بالا میتوان آنها را جایگزین کرد یا حتی لایههای جدید افزود.
Transfer Learning با Keras
فرض کنید نسخهای از Fashion MNIST فقط هشت کلاس دارد و مدلی به نام A روی آن با دقتی بیش از ۹۰٪ آموزش دیده است. اکنون یک مسئله دودویی کوچک با فقط ۲۰۰ تصویر برچسبخورده داریم و میخواهیم مدلی به نام B بسازیم. آموزش مستقیم B با معماری مشابه A روی داده کم، مثلاً دقت آزمون ۹۱٫۸۵٪ میدهد. چون دو وظیفه از تصاویر پوشاک استفاده میکنند، میتوان transfer learning را امتحان کرد.
ابتدا مدل A را بارگذاری میکنیم و همه لایههایش جز خروجی را در مدل جدید قرار میدهیم، سپس یک خروجی sigmoid برای طبقهبندی دودویی اضافه میکنیم:
# Assuming model A was already trained and saved to "my_model_A"
model_A = tf.keras.models.load_model("my_model_A")
model_B_on_A = tf.keras.Sequential(model_A.layers[:-1])
model_B_on_A.add(tf.keras.layers.Dense(1, activation="sigmoid"))
در این حالت model_A و model_B_on_A بعضی لایهها را واقعاً مشترک دارند؛ بنابراین آموزش مدل جدید میتواند مدل A را هم تغییر دهد. برای جلوگیری از این مسئله، ابتدا معماری A را clone و سپس وزنها را جداگانه کپی میکنیم:
model_A_clone = tf.keras.models.clone_model(model_A)
model_A_clone.set_weights(model_A.get_weights())
لایه خروجی جدید در ابتدا وزنهای تصادفی دارد و در epochهای اول خطا و گرادیان بزرگی تولید میکند؛ اگر همه لایهها آزاد باشند، این گرادیانها ممکن است وزنهای مفید reuseشده را خراب کنند. پس بهتر است چند epoch اول لایههای قبلی را freeze کنیم:
for layer in model_B_on_A.layers[:-1]:
layer.trainable = False
optimizer = tf.keras.optimizers.SGD(learning_rate=0.001)
model_B_on_A.compile(loss="binary_crossentropy", optimizer=optimizer,
metrics=["accuracy"])
پس از چند epoch میتوان لایههای reuseشده را unfreeze کرد، مدل را دوباره compile کرد و با نرخ یادگیری پایین fine-tune را ادامه داد:
history = model_B_on_A.fit(
X_train_B, y_train_B, epochs=4,
validation_data=(X_valid_B, y_valid_B))
for layer in model_B_on_A.layers[:-1]:
layer.trainable = True
optimizer = tf.keras.optimizers.SGD(learning_rate=0.001)
model_B_on_A.compile(loss="binary_crossentropy", optimizer=optimizer,
metrics=["accuracy"])
history = model_B_on_A.fit(
X_train_B, y_train_B, epochs=16,
validation_data=(X_valid_B, y_valid_B))
در مثال کتاب، دقت آزمون به ۹۳٫۸۵٪ رسید؛ یعنی دو واحد درصد افزایش نسبت به ۹۱٫۸۵٪ و تقریباً ۲۵٪ کاهش در نرخ خطا:
model_B_on_A.evaluate(X_test_B, y_test_B)
# [0.2546142041683197, 0.9384999871253967]
اما نویسنده بلافاصله هشدار میدهد که این نتیجه نباید بیش از حد جدی گرفته شود: ترکیبهای زیادی امتحان شده تا نمونهای با بهبود چشمگیر پیدا شود. با تغییر کلاسها یا seed ممکن است بهبود کمتر، صفر یا حتی منفی شود. این نمونه برای نشاندادن خطر «فشار دادن داده تا اعتراف کند» است؛ اگر تعداد زیادی پیکربندی امتحان و فقط بهترین نتیجه گزارش شود، بخشی از آن میتواند صرفاً حاصل شانس باشد و بازتولیدپذیری علمی آسیب ببیند.
علت اصلی این است که transfer learning در شبکههای Dense کوچک معمولاً چندان مؤثر نیست: شبکه کوچک الگوهای کمی یاد میگیرد و Denseها اغلب الگوهای بسیار خاص مسئله را میآموزند. این تکنیک در CNNهای عمیق بهتر جواب میدهد، چون لایههای پایین feature detectorهای عمومیتری میآموزند. فصل ۱۴ این موضوع را با شبکههای convolutional دوباره بررسی میکند.
پیشآموزش بدون نظارت
اگر برای مسئله پیچیده داده برچسبخورده کمی داریم و هیچ مدل pretrained مشابهی هم پیدا نمیشود، هنوز یک گزینه مهم باقی است: unsupervised pretraining. جمعآوری داده بدون برچسب معمولاً ارزانتر از برچسبگذاری است. اگر نمونههای بدون برچسب زیادی داشته باشیم، میتوان ابتدا یک مدل بدون نظارت مانند autoencoder یا GAN را روی همه آنها آموزش داد، سپس لایههای پایین autoencoder یا discriminator در GAN را reuse کرد، لایه خروجی مسئله اصلی را افزود و کل شبکه را با داده برچسبخورده fine-tune کرد.
این همان خانواده ایدههایی است که Geoffrey Hinton و همکاران در سال ۲۰۰۶ به کار بردند و نقش مهمی در احیای شبکههای عصبی و موفقیت یادگیری عمیق داشت. تا حدود ۲۰۱۰، پیشآموزش بدون نظارت - معمولاً با Restricted Boltzmann Machine یا RBM - برای شبکههای عمیق بسیار رایج بود. با کاهش مشکل vanishing gradients، آموزش کاملاً supervised رایجتر شد؛ اما unsupervised pretraining هنوز وقتی مسئله پیچیده، مدل مشابه کمیاب، داده برچسبخورده کم و داده بدون برچسب فراوان است، گزینه خوبی است.
در سالهای ابتدایی deep learning، آموزش مدل عمیق دشوار بود و از greedy layer-wise pretraining استفاده میشد: ابتدا یک مدل تکلایه بدون نظارت، مثلاً RBM، آموزش داده میشد؛ آن لایه freeze میشد، لایه بعدی اضافه و آموزش داده میشد؛ سپس همان روند لایهبهلایه تکرار میشد. امروزه معمولاً مدل بدون نظارت کامل یکباره آموزش داده میشود و autoencoder یا GAN جای RBM را گرفتهاند.
شکل ۱۱-۶ - ابتدا مدل روی کل داده، شامل نمونههای بدون برچسب، با روش بدون نظارت آموزش میبیند؛ سپس فقط با داده برچسبخورده برای وظیفه نهایی fine-tune میشود. بخش بدون نظارت میتواند لایهبهلایه یا یکباره آموزش داده شود.
پیشآموزش روی یک وظیفه کمکی
اگر داده برچسبخورده مسئله اصلی کم است، یک راه دیگر این است که شبکه اول را روی یک وظیفه کمکی آموزش دهیم که برای آن بتوان داده برچسبخورده را آسانتر جمعآوری یا تولید کرد، سپس لایههای پایین آن را برای مسئله واقعی reuse کنیم. لایههای پایین در مسئله کمکی feature detectorهایی میآموزند که احتمالاً در مسئله اصلی هم مفیدند.
مثلاً برای تشخیص هویت چهره شاید از هر فرد فقط چند تصویر داشته باشیم و جمعآوری صدها تصویر برای هر شخص عملی نباشد. در عوض میتوان تصاویر زیادی از افراد تصادفی جمع کرد و شبکهای آموزش داد که تشخیص دهد آیا دو تصویر متعلق به یک شخص هستند یا نه. چنین مدلی feature detectorهای خوبی برای چهره میآموزد و لایههای پایین آن میتوانند با داده اندک برای طبقهبند نهایی reuse شوند.
در NLP نیز میتوان میلیونها سند متنی را دانلود کرد و برچسبها را خودکار از خود داده ساخت؛ مثلاً بعضی واژهها را تصادفی mask کرد و مدلی آموزش داد که واژه حذفشده را پیشبینی کند. ادامه این مثال و مفهوم self-supervised learning در بخش بعد پیگیری میشود.
این ترجمه برای استفادهٔ آموزشی تهیه شده است. انتشار عمومی، فروش یا بازنشر آن باید با رعایت حقوق مؤلف و ناشر و اخذ مجوزهای لازم انجام شود.