آموزش Keras : استفاده از مدل های از پیش آموزش دیده ImageNet

در این مقاله سعی داریم به نحوه استفاده از مدل های از پیش آموزش دیده در مجموعه های داده بزرگ مانند ILSVRC بپردازیم و همچنین نحوه استفاده از آن ها را برای وظایفی متفاوت از آنچه در آن آموزش دیده بودند را یاد می گیریم. در سه پست بعدی به موضوعات زیر می پردازیم :

  1. کلاسه بندی تصویر با استفاده از مدل های از پیش آموزش دیده مختلف.
  2. آموزش یک کلاسه بند برای یک وظیفه متفاوت ، با استفاده از ویژگی های استخراج شده با استفاده از مدل های فوق الذکر. این کار یادگیری انتقالی نامیده می شود.
  3. آموزش یک کلاسه بند برای انجام وظایف مختلف ، با تغییر وزن های مدل های فوق. به این روش تنظیم دقیق ( Fine-Tune ) می گویند.

ImageNet چیست؟

ImageNet پروژه ای است که هدف آن ارائه یک پایگاه داده بزرگ از تصاویر برای اهداف تحقیقاتی است. این مجموعه داده شامل بیش از ۱۴ میلیون تصویر است که متعلق به بیش از ۲۰۰۰۰ کلاس ( یا synset ) است. آن ها همچنین برچسب نویسی های کادر محدود کننده را برای حدود ۱ میلیون تصویر ارائه می دهند که می تواند در وظایف مکان یابی اشیا مورد استفاده قرار گیرند. لازم به ذکر است که آن ها فقط url تصاویر را ارائه می دهند و شما باید آن ها را دانلود کنید.

ILSVRC چیست؟

هر ساله از سال ۲۰۱۰ رویداد یا رقابتی سالانه توسط تیم ImageNet سازماندهی می شود تحت عنوانImageLet Large Scale Visual Recognition Challenge یا ILSVRC ، که تیم های تحقیقاتی الگوریتم های بینایی رایانه ای خود را با وظایف مختلف تشخیص بصری مانند کلاسه بندی اشیا و مکان یابی اشیا مورد ارزیابی قرار می دهند. داده های آموزشی زیرمجموعه ای از ImageNet با ۱٫۲ میلیون تصویر متعلق به ۱۰۰۰ کلاس هستند. یادگیری عمیق در سال ۲۰۱۲ هنگامی مورد توجه قرار گرفت که Alex Krizhevsky و تیمش با اختلاف ۱۱ درصد برنده این رقابت شدند. گاهی از ILSVRC و Imagenet به جای یکدیگر استفاده می شود.

چرا باید از مدل های از پیش آموزش دیده استفاده کرد؟

دو نفر را تصور کنید ، یک فرد تنبل و یک فرد ورزشکار. آن ها همزمان در یک مدرسه فوتبال ثبت نام می کنند. هیچ کدام از آن ها تا به حال فوتبال بازی نکرده اند و مهارت هایی مانند دریبل زدن ، پاس دادن ، شوت زدن و غیره برای هر دوی آن ها تازگی دارد. تنها تفاوت اصلی بین این دو حتی قبل از شروع آموزش ، این است که فرد ورزشکار تحرک بیشتری نسبت به فرد تنبل دارد.

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

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

پیش تر مشاهده کرده بودیم که می توانیم شبکه های کانولوشنی ( CNN ) کوچک را برای کلاسه بندی ارقام ( با استفاده از MNIST ) یا اشیاء مختلف ( با استفاده از CIFAR10 ) ایجاد و آموزش دهیم. این شبکه های کوچک زمانی که کلاس های زیادی وجود داشته باشد و اشیاء از نظر اندازه ، شکل ، ظاهر و غیره متفاوت باشند عملکرد مطلوبی نخواهند داشت ، زیرا این مدل ها فاقد پیچیدگی لازم برای مدلسازی چنین تغییرات بزرگی در داده ها است.

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

شبکه های عمیق دارای تعداد زیادی پارامتر ناشناخته (در حد میلیون) هستند. وظیفه آموزش شبکه یافتن پارامترهای بهینه با استفاده از داده های آموزشی است. از جبر خطی ، می دانیم که برای حل معادله ای با سه پارامتر ناشناخته ، به سه معادله ( داده ) نیاز داریم. و اگر فقط دو معادله داشته باشیم ، می توانیم مقادیر دقیق حداکثر ۲ پارامتر و مقدار تقریبی پارامتر ناشناخته سوم را بدست آوریم.

به طور مشابه ، برای یافتن دقیق همه پارامترهای ناشناخته ، به داده های زیادی (در حد میلیون) نیاز داریم. اگر داده های بسیار کمی داشته باشیم ، برای اکثر پارامترها فقط مقادیر تقریبی بدست می آوریم ، که ما این را نمی خواهیم. در واقع برای شبکه های عمیق باید به نکته مهم زیر توجه کرد :

داده های بیشتر => یادگیری بهتر

اما مشکل اینجاست که به دست آوردن چنین مجموعه عظیمی از داده های برچسب خورده برای آموزش شبکه ، بسیار دشوار است.

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

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

خب، به اندازه کافی با موضوع آشنا شدیم ، حال بیایید ببینیم چگونه از مدل های از پیش آموزش دیده برای کلاسه بندی تصویر در Keras استفاده کنیم.

مدل های از پیش آموزش دیده موجود در Keras

برگزیدگان ILSVRC بسیار سخاوتمندانه ، مدل های خود را به صورت منبع باز در اختیار عموم قرار داده اند. مدل های زیادی مانند AlexNet ،VGGNet ، Inception ، ResNet ، Xception و بسیاری دیگر وجود دارد که ما می توانیم آن ها را برای انجام وظایف خود انتخاب کنیم. به غیر از برندگان ILSVRC ، بسیاری از گروه های تحقیقاتی نیز مدل های خود را که برای کارهای مشابه آموزش دیده اند ، به اشتراک می گذارند ، از جمله MobileNet ، SqueezeNet و غیره.

این شبکه ها برای کلاسه بندی تصاویر در یکی از ۱۰۰۰ دسته یا کلاس آموزش دیده اند.

Keras همراه با مدل های زیادی عرضه می شود. یک مدل آموزش دیده دارای دو بخش است : معماری مدل و وزن مدل . وزن ها، فایل های بزرگی هستند و بنابراین با Keras همراه نیستند. با این حال ، اگر خواستید وزن های آموزش داده شده بر روی داده های ImageNet را بارگذاری کنید ، فایل وزن به صورت خودکار دانلود می شود و دارای مدل های زیر است ( از نسخه Keras نسخه ۲٫۱٫۲ ) :

  • VGG16
  • InceptionV3
  • ResNet
  • MobileNet
  • Xception
  • InceptionResNetV2

بارگذاری یک مدل در Keras

ما می توانیم با استفاده از کد زیر، مدل ها را در Keras بارگذاری کنیم.

import numpy as np
# import the models for further classification experiments
from tensorflow.keras.applications import (
        vgg16,
        resnet50,
        mobilenet,
        inception_v3
    )

# init the models
vgg_model = vgg16.VGG16(weights='imagenet')

inception_model = inception_v3.InceptionV3(weights='imagenet')

resnet_model = resnet50.ResNet50(weights='imagenet')

mobilenet_model = mobilenet.MobileNet(weights='imagenet')

در کد بالا ، ابتدا ماژول پایتون حاوی مدل های مربوطه را وارد می کنیم. سپس معماری مدل و وزن های imagenet را برای شبکه ها بارگذاری می کنیم. اگر نمی خواهید شبکه را با وزن imagenet راه اندازی کنید ، “imagenet” را با None جایگزین کنید.

بارگذاری و پیش پردازش یک تصویر

ما می توانیم تصویر را با استفاده از هر کتابخانه ای مانند OpenCV ، PIL ، skimage و غیره بارگذاری کنیم. Keras همچنین یک ماژول تصویر ارائه می دهد که توابعی را برای وارد کردن تصاویر و انجام برخی از پیش پردازش های اولیه مورد نیاز قبل از اعمال آن به شبکه به منظور پیش بینی ، ارائه می دهد. ما از توابع keras برای بارگذاری و پیش پردازش تصویر استفاده می کنیم. به طور خاص ، مراحل زیر را روی یک تصویر ورودی انجام می دهیم:

  1. بارگذاری تصویر که با استفاده از تابع ()load_img انجام می شود. Keras از فرمت PIL برای بارگذاری تصاویر استفاده می کند. بنابراین ، تصویر در قالب width x height x channels خواهد بود.
  2. با استفاده از تابع ()img_to_array تصویر را از فرمت PIL به فرمت Numpy و در قالب (width x height x channels) تبدیل می کنیم.
  3. شبکه ها یک Tensor چهار بُعدی را به عنوان ورودی در قالب (اندازه دسته ، طول ، عرض ، کانال ها) می پذیرند که این کار با استفاده از تابع ()expand_dims در Numpy انجام می شود.
import matplotlib.pyplot as plt
from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.applications.imagenet_utils import decode_predictions

# assign the image path for the classification experiments
filename = 'images/cat.jpg'

# load an image in PIL format
original = load_img(filename, target_size=(224, 224))
print('PIL image size',original.size)
plt.imshow(original)
plt.show()

# convert the PIL image to a numpy array
# IN PIL - image is in (width, height, channel)
# In Numpy - image is in (height, width, channel)
numpy_image = img_to_array(original)
plt.imshow(np.uint8(numpy_image))
plt.show()
print('numpy array size',numpy_image.shape)

# Convert the image / images into batch format
# expand_dims will add an extra dimension to the data at a particular axis
# We want the input matrix to the network to be of the form (batchsize, height, width, channels)
# Thus we add the extra dimension to the axis 0.
image_batch = np.expand_dims(numpy_image, axis=0)
print('image batch size', image_batch.shape)
plt.imshow(np.uint8(image_batch[0]))

خروجی :

PIL image size (224, 224)
numpy array size (224, 224, 3)
image batch size (1, 224, 224, 3)
تصویر گربه از دیتاست Imagenet

پیش بینی کلاس اشیاء

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

  1. هر کانال موجود در دسته های تصویر ورودی را با کم کردن از مقدار میانگین ، پیش پردازش می کنیم. میانگین ، آرایه ای از سه عنصر است که با میانگین پیکسل های کانال های R ، G ، B از تمام تصاویر بدست آمده از ImageNet حاصل می شود. مقادیر ImageNet عبارتند از : [۱۰۳٫۹۳۹ ، ۱۱۶٫۷۷۹ ، ۱۲۳٫۶۸]. این کار با استفاده از تابع ()preprocess_input انجام می شود.
  2. نتیجه کلاسه بندی را که یک تنسور با ابعاد (batch size x 1000) است را بدست می آوریم. این کار توسط تابع ()predict انجام می شود.
  3. نتیجه را به برچسب هایی که برای انسان قابل خواندن باشد تبدیل می کنیم. بردار بدست آمده در بالا دارای مقادیر زیادی است تا منطقی به نظر برسد. Keras ، تابع ()decode_predictions ارائه می دهد که با استفاده از نتیجه کلاسه بندی ، آن را بر اساس اطمینان پیش بینی مرتب کرده و نام کلاس ( به جای شماره کلاس ) را دریافت می کند. ما همچنین می توانیم با استفاده از آرگومان های موجود در تابع ، تعداد نتایج مورد نظر خود را مشخص کنیم. خروجی ، شناسه کلاس ، نام کلاس و اطمینان پیش بینی را نشان می دهد.
# prepare the image for the VGG model
processed_image = vgg16.preprocess_input(image_batch.copy())

# get the predicted probabilities for each class
predictions = vgg_model.predict(processed_image)
# print predictions
# convert the probabilities to class labels
# we will get top 5 predictions which is the default
label_vgg = decode_predictions(predictions)
# print VGG16 predictions
for prediction_id in range(len(label_vgg[0])):
    print(label_vgg[0][prediction_id])

خروجی :

('n02123597', 'Siamese_cat', 0.30934194)
('n01877812', 'wallaby', 0.08034124)
('n02326432', 'hare', 0.07509843)
('n02325366', 'wood_rabbit', 0.0505307)
('n03223299', 'doormat', 0.048173614)
  1. مقایسه نتایج مدل های مختلف. بگذارید نتایج مدل های مختلف را برای چند تصویر امتحان کنیم. اگر تصویر گربه را به عنوان ورودی در نظر بگیریم و آن را بر روی ۴ مدل اجرا کنیم ، خروجی زیر را دریافت می کنیم.
نتیجه تشخیص تصویر گربه

اگر تصویر سگ به عنوان ورودی باشد، خروجی زیر را خواهیم داشت :

نتیجه تشخیص تصویر سگ

و نتیجه خروجی پرتقال :

نتیجه تشخیص تصویر پرتقال

برای ورودی تصویر گوجه فرنگی، خروجی زیر را به دست می آوریم :

نتیجه تشخیص تصویر گوجه فرنگی

و نتیجه خروجی هندوانه :

نتیجه تشخیص تصویر هندوانهنتیجه تشخیص تصویر هندوانه

خب ، به نظر می رسد ILSVRC ، گوجه فرنگی و هندوانه را تشخیص نمی دهد. در پست های آینده خواهیم دید که چگونه یک کلاسه بند را با استفاده از همین مدل ها با داده های خود آموزش دهیم تا هر مجموعه دیگری از اشیاء را که در مجموعه داده ILSVRC وجود ندارد، شناسایی کند. که این موضوع دو پست بعدی ما خواهد بود. با ما همراه باشید!

بیشتر خوانید :

منبع Learn OpenCV

درباره‌ی امیر اقتدائی

همچنین ببینید

آیا می خواهید در زمینه یادگیری ماشین استخدام شوید؟

آیا می خواهید در زمینه یادگیری ماشین استخدام شوید؟

مسیر های شغلی زیادی در حوزه یادگیری ماشین وجود دارد، اما از کجا بفهمیم که …

دیدگاهتان را بنویسید

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