یادگیری انتقال
آموزشآموزش‌های پایه‌ای هوش مصنوعیپایتون و ابزارهای یادگیری عمیقکتابخانه‌ های یادگیری عمیقیادگیری با نظارت

یادگیری انتقال و تنظیم دقیق شبکه‌‌ های عصبی پیچشی

    0

    مقدمه

    یادگیری انتقال در مباحث یادگیری ماشین به این اشاره دارد که دانش کسب شده توسط ماشین ذخیره می‌شود و سپس از این دانش ذخیره شده برای حل مسائل متفاوت اما مرتبط دیگر استفاده می‌شود.

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

    با اینکه آموزش شبکه‌های عصبی کار زمان‌بَری است؛ خوشبختانه، امروزه راه‌هایی برای صرفه‌جویی در زمان ارائه شده که در ادامه به آن‌ها اشاره می‌کنیم:

    • معماری شبکه عصبی را تعریف کنید.
    • از ابتدا به آموزشِ آن بپردازید.

    قبلاً هم با راهکارهای اجتناب از تعریفِ معماری آشنا شده‌ایم. در همین راستا، می‌توانیم از معماری‌های از‌پیش ‌تعریف ‌شده‌ای استفاده کنیم که کارآیی خوبی دارند. از جمله این معماری‌ها می‌توان به ResNet، AlexNet، VGG، Inception، DenseNet و… اشاره کرد.

    آیا از همان ابتدا می‌توان آموزش این معماری‌ها را نادیده گرفت؟

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

    اگر مقدار‌دهی وزن‌ها به گونه‌ای تعیین شود که می‌دانیم تاثیر خوبی در دسته‌بندی مجموعه‌داده معینی خواهند داشت، چه اتفاقی می‌افتد؟ در این صورت، از مجموعه‌داده بزرگی که برای آموزش شبکه از صفر، نیاز داشتیم، بی‌نیاز می‌شویم. به علاوه، دیگر نیاز نیست چندین دوره صبر کنیم تا وزن‌ها به مقادیر مناسبی برسند و عملیات دسته‌بندی اجرا شود. فرایند مقداردهیِ اولیه باعث سهولت در این کار می‌شود.

    اجازه دهید نحوه انجام این کار را با «روش‌های انتقال یادگیری» و «تنظیم دقیق» بررسی کنیم.

    یادگیری انتقال

    شبکه «VGG16» را به عنوان مثال در نظر بگیرید که در مجموعه‌داده ImageNet آموزش داده شده است. بیایید معماری آن را ببینیم:

     

    یادگیری انتقال

     

    می‌دانیم که «ImageNet» از مجموعه‌داده‌ای تشکیل شده که حاوی ۱.۲ میلیون تصویر برای آموزش، ۵۰.۰۰۰ تصویر برای اعتبارسنجی و ۱۰۰.۰۰۰ تصویر برای آزمایش است. این مجموعه‌داده در ۱۰۰۰ دسته قابل‌دسترس است.
    حالا فرض کنید می‌خواهیم شبکه «VGG16» را در مجموعه‌داده دیگری به کار بگیریم و مجموعه‌داده منتخبِ ما «CIFAR-10» باشد، چطور می‌توانیم این کار را انجام دهیم؟ اگر طرح کلی شبکه عصبی پیچشی (Convolutional Neural Network یا CNN) را به خاطر داشته باشید، می‌دانید که یک استخراج‌کنندۀ ویژگی feature extractor و یک دسته‌بندی‌کننده classifier داریم:

     

    یادگیری انتقال

     

    چه اتفاقی می‌افتد اگر لایۀ آخر «VGG16» را با لایه‌ای جایگزین کنیم که به جای ۱۰۰۰ احتمال فقط ۱۰ احتمال می‌گیرد؟ به این ترتیب، می‌توانیم از تمام دانشی که «VGG16» در ImageNet آموزش دیده برای حل مسئله خودمان استفاده کنیم.

    همان‌طور که قبلاً مشاهده شد، ابتدا باید مرحله دسته‌بندی را تغییر دهیم تا لایۀ آخر یکی از ۱۰ نورون باشد (CIFAR 10
    دارای ۱۰ دسته می‌باشد). سپس باید شبکه‌ای را مجددا آموزش دهیم که امکان تغییر وزن لایه‌های کاملا متصل fully connected layer را فراهم کند.

    به همین منظور، مقداردهی اولیه به وزن‌های شبکه با استفاده‌ از وزن‌ حاصل از «ImageNet» انجام می‌شود. پس از آن، همه لایه‌های پیچشی و «max-pooling» فریز می‌شوند تا وزن آن‌ها تغییر پیدا نکنند. در چنین شرایطی، فقط لایه‌های کاملا متصل قابل بروزرسانی هستند و به به محض اینکه این کار به انجام رسید، می‌توان پروسه آموزش مجدد را آغاز نمود.

    پس می‌توان از مرحله استخراج ویژگی در شبکه به خوبی استفاده و فقط دسته‌بندی‌کنندۀ نهایی را به‌طور دقیق تنظیم کرد تا بتواند به شکل بهتری با مجموعه‌دادۀ ما کار کند. این فرایند را «یادگیری انتقال» نام‌گذاری کرده‌اند؛ فرایندی که در آن از از دانش مربوط مسئله دیگری برای حل مسئله‌ای که خودمان با آن دست و پنجه نرم می‌کنیم استفاده می‌شود.

    این فرایند با ذخیره کردن خصوصیاتِ حاصل از آخرین لایۀ «max pooling» و جایگذاری داده‌ها در یک دسته‌بندی‌کننده (SVM، logreg و…) انجام‌پذیر است. بگذارید مراحل انجام این کار را با یکدیگر بررسی کنیم:

    اجرای «Keras»

    ابتدا باید به بارگذاریِ مجموعه‌داده و کتابخانه‌های ضروری بپردازیم و ابعاد آن را مطابق با «VGG16» به حداقل برسانیم:

    import tensorflow as tf
    from keras import callbacks
    from keras import optimizers
    from keras.engine import Model
    from keras.layers import Dropout, Flatten, Dense
    from keras.optimizers import Adam
    from keras.applications import VGG16
    from keras.datasets import cifar10
    from keras.utils import to_categorical
    import numpy as np
    (input_shape = (48, 48, 3
    ()X_train, y_train), (X_test, y_test) = cifar10.load_data)
    (Y_train = to_categorical(y_train
    (Y_test = to_categorical(y_test

    تغییر اندازه مجموعه آموزش:

     []=X_train_resized
    :for img in X_train
    X_train_resized.append(np.resize(img, input_shape) / 255)

    X_train_resized = np.array(X_train_resized)
    print(X_train_resized.shape)

    تغییر اندازه مجموعه آزمایش:

     []=X_test_resized
    :for img in X_test
    (X_test_resized.append(np.resize(img, input_shape) / 255

    (X_test_resized = np.array(X_test_resized
    (print(X_test_resized.shape

    ساختن مدل پایه:

    (base_model = VGG16(weights=’imagenet’, include_top=False, input_shape=input_shape
    ()base_model.summary

     

    یادگیری انتقال

     

    ما تمام لایه‌ها در مدل پایه‌مان را فریز می‌کنید تا در مرحله آموزش تغییر نیابند، به عبارت دیگر، می‌خواهیم استخراج‌کننده ویژگی‌مان تغییر نکند –> یادگیری انتقال

    :for layer in base_model.layers
    layer.trainable = False
    (print(‘Layer ‘ + layer.name + ‘ frozen.’

    لایه آخر مدل‌مان را انتخاب می‌کنیم و آن را به طبقه‌بندی‌مان اضافه می‌کنیم:

    last = base_model.layers[-1].output
    (x = Flatten()(last
    (x = Dense(1000, activation=’relu’, name=’fc1′)(x
    (x = Dropout(0.3)(x
    (x = Dense(10, activation=’softmax’, name=’predictions’)(x
    (model = Model(base_model.input, x

    مدل را کامپایل می‌کنیم:

    ([‘model.compile(optimizer=Adam(lr=0.001), loss=’categorical_crossentropy’, metrics=[‘accuracy

    ()model.summary

    یادگیری انتقال

    یادگیری انتقال

    آموزش را شروع می‌کنیم:

    epochs = 10
    batch_size = 256

    آموزش می‌دهیم:

    ,model.fit(X_train_resized, Y_train
    ,batch_size=batch_size
    ,validation_data=(X_test_resized, Y_test)
    (epochs=epochs

    یادگیری انتقال

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

    (scores = model.evaluate(X_test_resized, Y_test, verbose=1
    ([print(‘Test loss:’, scores[0
    ([print(‘Test accuracy:’, scores[1

     

    یادگیری انتقال

     

     

    اصلاً مجبور به آموزش نبودیم. اتفاقا نتایج بدی هم به دست نیامد، اما این مسئله را به خاطر داشته باشید که اگر این کار را به صورت تصادفی انجام می‌دادیم، احتمال اینکه به درستی انجام شود به ۱۰ درصد کاهش پیدا می‌کرد، چرا که ۱۰ دسته داشتیم.

    هرچقدر میزان شباهت مجموعه‌داده ما و مجموعه‌داده‌ای که در ابتدا، شبکه به وسیله آن آموزش دیده بیشتر باشد، امکان حصولِ نتایج بهتر نیز افزایش پیدا می‌کند. حالا اگر مجموعه‌دادۀ ما ارتباطی با «ImageNet» نداشته باشد یا بخواهیم نتایج را به شکل چشمگیری بهبود ببخشیم، باید چه رویکردی داشته باشیم؟ انجام این کار با تنظیم دقیق میسر می‌شود.

    تنظیم دقیق

    در فرایند تنظیم دقیق، ابتدا آخرین لایه را عوض می‌کنیم تا آن را با دسته‌های موجود در مجموعه‌داده خودمان تطبیق دهیم. این کار قبلاً هم در خصوص یادگیری انتقال انجام شده است. به علاوه، لایه‌های شبکۀ دلخواه‌مان را نیز مجدداً آموزش می‌دهیم.
    معماری «VGG16» را به خاطر آورید:

     

    یادگیری انتقال

     

    در مثال قبل فقط لایه‌های مرحلۀ دسته‌بندی را تغییر دادیم، اما دانشی که شبکه در هنگام استخراج خصوصیات (الگوها) در کار قبلی بدست آورده بود را تغییر ندادیم. وزن‌ها با توجه به کار قبلی بارگذاری می‌شوند. در تنظیم دقیق، نیازی نیست خودمان را فقط محدود به آموزشِ مجددِ مرحله دسته‌بندی کنیم (یعنی لایه‌های کاملاً متصل)؛ کاری که باید انجام دهیم این است که مرحله استخراج ویژگی را هم مجدداً آموزش دهیم (یعنی لایه‌های پیچشی و ادغام pooling layer).

    باید این نکتۀ مهم را به خاطر سپرد که لایه‌های نخست در شبکه‌های عصبی به شناساییِ مجموعه‌داده‌های کلی‌تر و ساده‌تر می‌پردازند. هر چه بیشتر در مرحله معماری پیش برویم، الگوهای پیچیده‌تری مورد شناسایی قرار می‌گیرند. بنابراین، باید زمینه را برای آموزش مجدد آخرین بلوک پیچش و ادغام (pooling) فراهم کنیم. چه زمانی باید اقدام به تنظیم دقیق و یادگیری انتقال کرد؟ از کجا باید تشخیص داد که چه لایه‌ای نیاز به آموزش مجدد دارد؟

    اولین کار این است که یادگیری انتقال را انجام دهیم؛ نباید شبکه‌مان را مجدداً آموزش دهیم. اقدام بعدی، آموزش مجدد مرحله دسته‌بندی است. بعد از آن می‌توان به آموزش مجدد بلوک پیچشی هم پرداخت. اگر این مراحل را رد کنیم، اکثر مواقع به نتایج مناسبی برای مسئله خواهیم رسید. البته به نوع مسئله‌ای که داریم هم بستگی دارد. اگر:

    • مجموعه‌داده جدید کوچک است و به مجموعه‌داده اصلی شباهت دارد: باید جانب احتیاط را در هنگام تنظیم دقیق رعایت کنید؛ شاید بهتر است خصوصیات لایۀ آخرِ مرحله پیچشی را انتخاب و از ماشین بردار پشتیبانSupport Vector Machine (SVM)  (SVM) یا دسته‌­بندی‌کننده خطّی استفاده کنید.

    • مجموعه‌داده جدید بزرگ است و به مجموعه‌داده اصلی شباهت دارد: داشتن داده‌های بیشتر به این معنا نیست که دچار بیش‌برازش Over-fitting خواهیم شد؛ بنابراین، با اطمینان بیشتری می‌توان فرایند تنظیم دقیق را انجام داد.

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

    • مجموعه‌داده جدید بزرگ است و تفاوت زیادی با مجموعه‌داده اصلی دارد: باید از ابتدا به آموزشِ آن پرداخت. با این حال، توصیه می‌شود که وزن‌ها را با ImageNet مقداردهی اولیه کنید.

    در هنگام استفاده از هر یک از این روش‌ها، باید به محدودیت‌های احتمالیِ مدل‌های از ‌پیش آموزش ‌یافته هم توجه داشته باشید. برای مثال، شاید این مدل‌ها به حداقل اندازه عکس احتیاج داشته باشند. بنابراین در هنگام آموزش مجدد شبکه‌ها، معمولا نرخ یادگیری learning rate را پایین انتخاب می‌کنیم، زیرا ما با مقداردهی اولیه‌ای از وزن‌ها شروع کرده‌ایم که فکر می‌کنیم مقادیر مناسبی هستند.

    تنظیم دقیق «Keras»

    مثال تنظیم دقیق، طبقه‌بندی CIFAR10 با استفاه از VGG16، ابتدا کتابخانه‌های ضروری را اضافه می‌کنیم:

     

    ابتدا دیتاست را لود می‌کنیم، سپس ابعاد آن را برای استفاده VGG16 تغییر می‌دهیم (۴۸, ۴۸, ۳):

     

    تغییر اندازه مجموعه آزمایش:

     

    یادگیری انتقال

     

    مدل پایه را می‌سازیم:

     

    یادگیری انتقال

     

    اجازه می‌دهیم که کانولوشن آخر و مراحل طبقه‌بندی آموزش ببینند:

     

    ‌ بند خودمان را به لایه آخر مدل اضافه می‌کنیم:

    last = base_model.layers[-1].output
    (x = Flatten()(last
    (x = Dense(1000, activation=’relu’, name=’fc1′)(x
    (x = Dropout(0.3)(x
    (x = Dense(10, activation=’softmax’, name=’predictions’)(x
    (model = Model(base_model.input, x

    مدل را کامپایل می‌کنیم:

     

    می‌توانیم ساختار جدید مدل را ببینیم

     

    ()model.summary

    یادگیری انتقال

    یادگیری انتقال

     

    آموزش را شروع می‌کنیم:

     

    مدل را آموزش می‌دهیم:

     

    یادگیری انتقال

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

     

    یادگیری انتقال

    فیسبوک می‌تواند «خطرناک ترین جنایت آینده» و هوش مصنوعی سازنده‌ی آن را تشخیص دهد

    مقاله قبلی

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

    مقاله بعدی

    شما همچنین ممکن است دوست داشته باشید

    بیشتر در آموزش

    نظرات

    پاسخ دهید

    نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *