یادگیری انتقال با پایتون در مدل‌های بینایی ماشین — راهنمای کاربردی

۷۸۷ بازدید
آخرین به‌روزرسانی: ۰۵ تیر ۱۴۰۲
زمان مطالعه: ۱۴ دقیقه
یادگیری انتقال با پایتون در مدل‌های بینایی ماشین — راهنمای کاربردی

در این مطلب، یادگیری انتقال با پایتون در مدل‌های بینایی ماشین همراه با یک پروژه نمونه، به طور کامل و جامع مورد بررسی قرار گرفته است. آموزش دادن مدل‌های «شبکه عصبی پیچشی عمیق» (Convolutional Neural Networks) ممکن است روزها و حتی سال‌ها به طول بیانجامد. یک راه میان‌بر برای این فرایند، استفاده مجدد از وزن‌های مدل، از مدل‌های از پیش آموزش داده شده است که برای مجموعه داده‌های بنچ‌مارک «بینایی کامپیوتری» (Computer Vision) استانداردی مانند وظایف تشخیص تصویر ImageNet توسعه داده شده‌اند. در این مطلب، چگونگی استفاده از «یادگیری انتقال» (Transfer Learning) هنگام توسعه شبکه‌های عصبی پیچشی برای کاربردهای بینایی کامپیوتری مورد بررسی قرار خواهد گرفت. مخاطبان پس از مطالعه این مطلب، با مباحث زیر آشنا خواهند شد.

  • یادگیری انتقال شامل استفاده از مدل‌های آموزش دیده روی یک مسئله به عنوان نقطه شروع مسائل مرتبط است.
  • یادگیری انتقال انعطاف‌پذیر است و امکان استفاده از مدل‌های از پیش‌آموزش دیده را به طور مستقیم به عنوان پیش‌پردازش «استخراج ویژگی» (Feature Extraction) و به صورت یکپارچه در مدل‌های کاملا جدید فراهم می‌کند.
  • کتابخانه «کرس» (Keras) دسترسی راحت به بسیاری از مدل‌های با کارایی بالا را در وظایف تشخیص تصویر ImageNet، مانند Inception ،VGG و ResNet فراهم کند.

یادگیری انتقال با پایتون در مدل‌های بینایی ماشین

این راهنما، به پنج بخش کلی تقسیم شده است. این موارد، در ادامه بیان شده‌اند.

  • مفهوم یادگیری انتقال
  • یادگیری انتقال برای «بازشناسی تصاویر» (Image Recognition)
  • روش استفاده از مدل‌های از پیش آموزش دیده
  • مدل‌هایی برای یادگیری انتقال
  • مثال‌هایی پیرامون استفاده از مدل‌های از پیش آموزش دیده

یادگیری انتقال چیست؟

یادگیری انتقال به فرایندی اشاره دارد که طی آن یک مدل آموزش دیده روی یک مسئله، به صورتی روی مسائل مرتبط مورد استفاده قرار می‌گیرد. در «یادگیری عمیق» (Deep Learning)، یادگیری انتقال روشی است که یک مدل شبکه عصبی روی مسئله‌ای مشابه با مسئله‌ای که قرار است حل شود، آموزش داده می‌شود.

در کتاب یادگیری عمیق (Deep Learning) که توسط ایان گودفلو و همکاران نوشته و در سال ۲۰۱۶ چاپ شده، در این رابطه چنین آمده است:

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

یادگیری انتقال دارای مزایای گوناگونی از جمله کاهش زمان اجرا برای مدل‌های «شبکه عصبی» (Neural Networks) است و می‌تواند منجر به خطاهای عمومی‌سازی کمتری بشود. وزن‌ها در لایه‌های مجددا استفاده شده ممکن است به عنوان نقاطی برای فرایند آموزش مورد استفاده قرار بگیرند و در پاسخ به مسائل جدید پذیرفته شده باشند. این کاربردها، موجب می‌شود که یادگیری انتقال به عنوان نوعی از شمای مقداردهی اولیه وزن باشد. این امر ممکن است هنگامی مفید باشد که مسئله مرتبط اول، داده‌های برچسب‌گذاری شده بسیار بیشتری نسبت به مسئله کنونی داشته باشد و مشابهت ساختار مسائل ممکن است در هر دو زمینه مفید باشند. در کتابی که پیش‌تر به آن اشاره شد، در این رابطه آمده است:

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

یادگیری انتقال برای تشخیص تصاویر

طیفی از مدل‌های با کارایی بالا برای دسته‌بندی تصاویر توسعه پیدا کرده‌اند و در «چالش بزرگ و سالانه تشخیص بصری ایمیج‌نت» (ImageNet Large Scale Visual Recognition Challenge | ILSVRC) معرفی شده‌اند. به این رقابت‌ها معمولا به طور خلاصه ImageNet گفته می‌شود.

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

  • ویژگی‌های یاد گرفته شده خوب: این مدل‌ها توانایی شناسایی ویژگی‌های جنریک را از تصاویر دارند؛ زیرا روی بیش از یک میلیون تصاویر از هزار دسته آموزش دیده‌اند.
  • کارایی لبه علم: مدل‌ها، کارایی لبه علمی کسب و در وظایف تشخیص تصویر خاصی که برای آن‌ها توسعه پیدا کرده‌اند، موثر هستند.
  • دسترسی‌پذیری آسان: وزن‌های مدل به عنوان فایل‌های رایگان و قابل دانلود هستند و کتابخانه‌های زیاد «رابط‌های برنامه‌نویسی کاربردی» (Application Programming Interface | API) برای راحت‌تر شدن دانلود و استفاده از مدل‌ها به طور مستقیم، ارائه شده‌اند.
  • وزن‌های مدل در معماری مدل مشابهی، با استفاده از کتابخانه‌های یادگیری عمیق گوناگون از جمله کرس، قابل دانلود و استفاده هستند.

روش استفاده از مدل‌های از پیش آموزش دیده

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

احتمالا، سه تا از محبوب‌ترین مدل‌ها، موارد زیر هستند:

  • VGG (برای مثال، VGG16 یا VGG19)
  • GoogLeNet (برای مثال InceptionV3)
  • شبکه باقیمانده (برای مثال ResNet50)

این مدل‌ها به خاطر کارایی که دارند، به طور گسترده‌ای برای یادگیری انتقال مورد استفاده قرار می‌گیرند؛ همچنین، این مدل‌ها نمونه‌های هستند که نوآوری‌های ساختاری خاصی را معرفی کرده‌اند و به عنوان مثال‌هایی از این موارد، می‌توان به ساختارهای «سازگار و تکرار شونده» (Consistent and Repeating Structures | VGG)، «ماژول‌های ادراکی» (GoogLeNet) و «ماژول‌های باقیمانده» (ResNet) اشاره کرد. کرس، دسترسی به تعدادی از مدل‌های دارای کارایی بالا و از پیش آموزش دیده را فراهم می‌کند که برای وظایف تشخیص تصویر استفاده می‌شوند. این مدل‌ها با  Applications API در دسترس هستند و شامل تابع‌هایی برای بارگذاری یک مدل با یا بدون وزن‌های از پیش آموزش داده هستند و داده‌ها را به صورتی آماده می‌کنند که مدل داده شده انتظار دارد (برای مثال: مقیاس کردن مقادیر سایز و پیکسل).

اولین باری که یک مدل از پیش آموزش دیده شده بارگذاری شد، کرس وزن‌های مدل مورد انتظار را دانلود می‌کند که ممکن است با توجه به سرعت اینترنت، مدت زمانی به طول بیانجامند. وزن‌ها در keras/models/ directory‎، زیر پوشه خانگی کاربر، ذخیره می‌شوند و دفعات آتی که مورد استفاده قرار می‌گیرند، از این مسیر بارگذاری می‌شوند. هنگام بارگذاری یک مدل داده شده، می‌توان آرگومان «include_top» را روی False تنظیم کرد که طی آن، لایه‌های کاملا متصل مدل که برای انجام پیش‌بینی مورد استفاده قرار می‌گیرند بارگذاری نشده‌اند و این امکان را فراهم می‌کند که لایه‌های جدید اضافه شوند و آموزش ببینند. برای مثال:

1...
2# load model without output layer
3model = VGG16(include_top=False)

علاوه بر این، هنگامی که «include_top» برابر با «False» است، آرگومان «input_tensor» باید تعیین شود که این امکان را فراهم می‌کند که ورودی دارای سایز ثابت مورد انتظار مدل تغییر کند. برای مثال:

1...
2# load model and specify a new input shape for images
3new_input = Input(shape=(640, 480, 3))
4model = VGG16(include_top=False, input_tensor=new_input)

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

نتیجه، یک بردار است که می‌توان از آن به عنوان توصیف‌گر ویژگی برای یک ورودی استفاده کرد. کرس این قابلیت‌ها را با آرگومان «pooling» فراهم می‌کند که می‌توان آن را روی «avg» یا «max» تنظیم کرد. برای مثال:

1...
2# load model and specify a new input shape for images and avg pooling output
3new_input = Input(shape=(640, 480, 3))
4model = VGG16(include_top=False, input_tensor=new_input, pooling='avg')

تصاویر را می‌توان با استفاده از تابع preprocess_input()‎ برای یک مدل داده شده آماده کرد. برای مثال، مقیاس‌دهی تصاویر به صورتی انجام می‌شود که برای تصاویر در مجموعه داده آموزش هنگام توسعه مدل انجام می‌شود.

1...
2# prepare an image
3from keras.applications.vgg16 import preprocess_input
4images = ...
5prepared_images = preprocess_input(images)

در نهایت، کاربر ممکن است بخواهد از یک معماری مدل روی مجموعه داده خود استفاده کند، اما از وزن‌های از پیش آموزش دیده شده استفاده نکند و به جای آن، مدل را با وزن‌های تصادفی مقداردهی اولیه کند و آن را از پایه آموزش دهد. این کار با تنظیم آرگومان «weights» روی «None»، به جای مقدار پیش‌فرض آن که «imagenet» است، انجام‌پذیر است. علاوه بر آن، آرگومان «classes» را می‌توان برای تعریف تعداد کلاس‌ها در مجموعه داده، تنظیم کرد که سپس، برای کاربر روی لایه خروجی مدل تنظیم می‌شود. برای مثال:

1...
2# define a new model with random weights and 10 classes
3new_input = Input(shape=(640, 480, 3))
4model = VGG16(weights=None, input_tensor=new_input, classes=10)

اکنون که API معرفی شد، نگاهی به سه مدل با استفاده از Keras Applications API انداخته می‌شود.

بارگذاری مدل از پیش آموزش دیده VGG16

مدل VGG16 توسط «Visual Graphics Group | VGG» در دانشگاه آکسفورد توسعه داده شده است و در مقاله‌ای با عنوان «شبکه‌های عصبی خیلی عمیق برای بازشناسی تصویر بزرگ مقیاس» (Very Deep Convolutional Networks for Large-Scale Image Recognition) که در سال ۲۰۱۴ منتشر شده، توضیح داده شده است.

به طور پیش‌فرض، مدل انتظار تصاویر ورودی رنگی را دارد که به اندازه 224×224 بازمقیاس‌دهی شوند. مدل را می‌توان به صورت زیر بارگذاری کرد.

1# example of loading the vgg16 model
2from keras.applications.vgg16 import VGG16
3# load model
4model = VGG16()
5# summarize the model
6model.summary()

با اجرای قطعه کد بالا، مدل VGG16 بارگذاری می‌شود و وزن‌های مدل را در صورت نیاز بارگذاری می‌کند. مدل می‌تواند به طور مستقیم برای دسته‌بندی یک تصویر در یکی از ۱۰۰۰ کلاس مورد استفاده قرار بگیرد. در این شرایط، معماری مدل برای تایید اینکه به درستی بارگذاری شده است، خلاصه‌سازی می‌شود.

_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 224, 224, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
_________________________________________________________________
predictions (Dense) (None, 1000) 4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

بارگذاری مدل از پیش آموزش دیده InceptionV3

InceptionV3 سومین تکرار از معماری inception  است که در ابتدا برای مدل GoogLeNet توسعه پیدا کرده بود. این مدل توسط توسعه‌دهندگان در گوگل توسعه پیدا کرده و در مقاله‌ای با عنوان «بازبینی معماری ادراکی برای بینایی کامپیوتری» (Rethinking the Inception Architecture for Computer Vision) توصیف شده است.

این مدل انتظار دارد که تصاویر به صورت مربعی و در اندازه 299×299 باشند. مدل را می‌توان به صورت زیر بارگذاری کرد.

1# example of loading the inception v3 model
2from keras.applications.inception_v3 import InceptionV3
3# load model
4model = InceptionV3()
5# summarize the model
6model.summary()

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

بارگذاری مدل از پیش آموزش دیده ResNet50

شبکه باقیمانده یا به طور خلاصه ResNet، یک مدل است که از ماژول باقیمانده شامل اتصالات میان‌بر، استفاده می‌کند. این مدل توسط توسعه‌دهندگان مایکروسافت توسعه داده شده و در مقاله‌ای با عنوان «یادگیری باقیمانده عمیق برای بازشناسی تصویر» در سال ۲۰۱۵ منتشر شده است.

مدل نیاز به تصاویر رنگی با ابعاد 224×224 دارد.

1# example of loading the resnet50 model
2from keras.applications.resnet50 import ResNet50
3# load model
4model = ResNet50()
5# summarize the model
6model.summary()

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

مثال‌هایی از استفاده از مدل‌های از پیش آموزش دیده

اکنون که چگونگی بارگذاری مدل‌ها در کرس آموزش داده شد، نگاهی به مثال‌هایی از چگونگی استفاده از این مدل‌ها در کاربردهای واقعی، ارائه شده است. نیاز به یک تصویر برای کار با این مثال‌ها است. در ادامه، تصویری از یک سگ ارائه شده است. این تصویر توسط «جاستین مورگان» (Justin Morgan) گرفته شده و دارای گواهینامه آزاد است. مخاطبان باید این تصویر را دانلود کرده و با نام «dog.jpg»، در پوشه جاری خود ذخیره کنند.

یادگیری انتقال با پایتون در مدل‌های بینایی ماشین -- راهنمای کاربردی

مدل‌های از پیش آموزش دیده شده به عنوان دسته‌بند

یک مدل از پیش آموزش دیده شده را می‌توان به طور مستقیم برای دسته‌بندی تصاویر یکی از هزار کلاس (دسته) شناخته شده در وظیفه دسته‌بندی تصویر ILSVRC، استفاده کرد. از مدل VGG16 برای دسته‌بندی تصاویر جدید استفاده می‌شود. ابتدا، عکس باید بارگذاری، و سپس به ابعاد 224×224 و مقادیر پیکسلی که مورد انتظار مدل است، تغییر داده شود. مدل روی نمونه‌های یک آرایه عمل می‌کند، بنابراین ابعاد یک تصویر بارگذاری شده باید ۱ واحد برای تصویری با 224×224 پیکسل و سه کانال، توسعه پیدا کنند.

1# load an image from file
2image = load_img('dog.jpg', target_size=(224, 224))
3# convert the image pixels to a numpy array
4image = img_to_array(image)
5# reshape data for the model
6image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
7# prepare the image for the VGG model
8image = preprocess_input(image)

سپس، مدل را می‌توان بارگذاری کرد و پیش‌بینی انجام شود. این یعنی، احتمال پیش‌بینی شده از تصویر متعلق به هر یک از ۱۰۰۰ کلاس انجام شده است. در این مثال، تنها نگرانی موجود پیرامون محتمل‌ترین کلاس‌ها است، بنابراین می‌توان پیش‌بینی‌ها را رمزگشایی و برچسب‌ها یا نام کلاس‌ها با بالاترین احتمال را بازیابی کرد.

1# predict the probability across all output classes
2yhat = model.predict(image)
3# convert the probabilities to class labels
4label = decode_predictions(yhat)
5# retrieve the most likely result, e.g. highest probability
6label = label[0][0]

با آزمودن همه این موارد در کنار هم، مثال زیر یک تصویر جدید را بارگذاری و محتمل‌ترین کلاس را پیش‌بینی می‌کند.

1# example of using a pre-trained model as a classifier
2from keras.preprocessing.image import load_img
3from keras.preprocessing.image import img_to_array
4from keras.applications.vgg16 import preprocess_input
5from keras.applications.vgg16 import decode_predictions
6from keras.applications.vgg16 import VGG16
7# load an image from file
8image = load_img('dog.jpg', target_size=(224, 224))
9# convert the image pixels to a numpy array
10image = img_to_array(image)
11# reshape data for the model
12image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
13# prepare the image for the VGG model
14image = preprocess_input(image)
15# load the model
16model = VGG16()
17# predict the probability across all output classes
18yhat = model.predict(image)
19# convert the probabilities to class labels
20label = decode_predictions(yhat)
21# retrieve the most likely result, e.g. highest probability
22label = label[0][0]
23# print the classification
24print('%s (%.2f%%)' % (label[1], label[2]*100))

با اجرای مثال، چیزی بیش از «سگ» بودن شی موجود در تصویر، پیش‌بینی می‌شود. این مدل، پیش‌بینی می‌کند که تصویر متعلق به نژاد سگ پرورشی «دوبِرمَن پینچِر» (Doberman) با احتمال 33.59%‎ است که امکان دارد درست باشد.

Doberman (33.59%)

مدل از پیش آموزش داده به عنوان پیش‌پردازش‌گر استخراج ویژگی

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

تصویر را می‌توان به صورتی که در مثال پیش انجام شد، برای مدل بارگذاری و آماده کرد. این لایه‌ها یک مجموعه پیچیده از ویژگی‌ها را برای توصیف یک تصویر ورودی داده شده فراهم می‌کنند و ممکن است یک ورودی ارزشمند را هنگام آموزش دادن یک مدل جدید برای دسته‌بندی یا وظایف بینایی کامپیوتر مشابه فراهم کنند. تصویر را می‌توان برای مدل، به صورتی که در مثال پیشین انجام شده است، بارگذاری و آماده کرد. مدل با بخش خروجی دسته‌بند مدل بارگذاری می‌شود، اما به صورت دستی لایه خروجی نهایی حذف می‌شود. این یعنی دومین لایه کاملا متصل آخر با ۴۰۹۶ گره یک لایه خروجی جدید خواهد بود.

1# load model
2model = VGG16()
3# remove the output layer
4model.layers.pop()
5model = Model(inputs=model.inputs, outputs=model.layers[-1].output)

این بردار از ۴۰۹۶ عدد، برای نمایش ویژگی‌های پیچیده از یک تصویر ورودی داده شده است که می‌توان آن را روی یک فایل ذخیره کرد تا بعدا بارگذاری شود و به عنوان ورودی برای آموزش مدل جدید مورد استفاده قرار گیرد.

1# get extracted features
2features = model.predict(image)
3print(features.shape)
4# save to file
5dump(features, open('dog.pkl', 'wb'))

با آزمودن همه این موارد در کنار هم، یک مثال کامل از استفاده از مدل به عنوان یک مدل استخراج ویژگی مستقل، در ادامه آمده است.

1# example of using the vgg16 model as a feature extraction model
2from keras.preprocessing.image import load_img
3from keras.preprocessing.image import img_to_array
4from keras.applications.vgg16 import preprocess_input
5from keras.applications.vgg16 import decode_predictions
6from keras.applications.vgg16 import VGG16
7from keras.models import Model
8from pickle import dump
9# load an image from file
10image = load_img('dog.jpg', target_size=(224, 224))
11# convert the image pixels to a numpy array
12image = img_to_array(image)
13# reshape data for the model
14image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
15# prepare the image for the VGG model
16image = preprocess_input(image)
17# load model
18model = VGG16()
19# remove the output layer
20model.layers.pop()
21model = Model(inputs=model.inputs, outputs=model.layers[-1].output)
22# get extracted features
23features = model.predict(image)
24print(features.shape)
25# save to file
26dump(features, open('dog.pkl', 'wb'))

با اجرای قطعه کد بالا، تصویر بارگذاری می‌شود و مدل به عنوان مدل استخراج ویژگی آماده می‌شود. ویژگی‌ها از تصویر بارگذاری شده استخراج می‌شوند و شکل بردار ویژگی چاپ می‌شود که نشان می‌دهد دارای ۴۰۹۶ عدد است. سپس، این ویژگی در یک فایل جدید به نام dog.pkl در پوشه کاری جدید ذخیره می‌شود.

(1, 4096)

این فرایند را می‌توان برای هر تصویر در مجموعه داده آموزشی جدید تکرار کرد.

مدل از پیش آموزش داده شده به عنوان استخراج‌گر ویژگی

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

برای مثال، می‌توان مدل VGG16 را بدون بخش دسته‌بندی با تعیین آرگومان «include_top» روی «False» و تعیین شکل ترجیح داده شده تصاویر در مجموعه داده به صورت 300×300، بارگذاری کرد.

1# load model without classifier layers
2model = VGG16(include_top=False, input_shape=(300, 300, 3))

می‌توان از API تابع کرس برای افزودن یک لایه Flatten جدید پس از آخرین لایه pooling در مدل VGG16 استفاده کرد، سپس یک مدل دسته‌بند جدید با یک لایه کاملا متصل Dense  و یک لایه خروجی که احتمال را برای ۱۰ کلاس پیش‌بینی می‌کند، تعریف کرد.

1# add new classifier layers
2flat1 = Flatten()(model.outputs)
3class1 = Dense(1024, activation='relu')(flat1)
4output = Dense(10, activation='softmax')(class1)
5# define new model
6model = Model(inputs=model.inputs, outputs=output)

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

1# example of tending the vgg16 model
2from keras.applications.vgg16 import VGG16
3from keras.models import Model
4from keras.layers import Dense
5from keras.layers import Flatten
6# load model without classifier layers
7model = VGG16(include_top=False, input_shape=(300, 300, 3))
8# add new classifier layers
9flat1 = Flatten()(model.outputs)
10class1 = Dense(1024, activation='relu')(flat1)
11output = Dense(10, activation='softmax')(class1)
12# define new model
13model = Model(inputs=model.inputs, outputs=output)
14# summarize
15model.summary()
16# ...

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

_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 300, 300, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 300, 300, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 300, 300, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 150, 150, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 150, 150, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 150, 150, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 75, 75, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 75, 75, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 75, 75, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 75, 75, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 37, 37, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 37, 37, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 37, 37, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 37, 37, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 18, 18, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 18, 18, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 18, 18, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 18, 18, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 9, 9, 512) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 41472) 0
_________________________________________________________________
dense_1 (Dense) (None, 1024) 42468352
_________________________________________________________________
dense_2 (Dense) (None, 10) 10250
=================================================================
Total params: 57,193,290
Trainable params: 57,193,290
Non-trainable params: 0
_________________________________________________________________

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

این امر را می‌توان با تنظیم خصوصیت «trainable» روی «False» برای هر یک از لایه‌ها در مدل VGG بارگذاری شده، پیش از آموزش، انجام داد. برای مثال:

1# load model without classifier layers
2model = VGG16(include_top=False, input_shape=(300, 300, 3))
3# mark loaded layers as not trainable
4for layer in model.layers:
5	layer.trainable = False
6...

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

1# load model without classifier layers
2model = VGG16(include_top=False, input_shape=(300, 300, 3))
3# mark some layers as not trainable
4model.get_layer('block1_conv1').trainable = False
5model.get_layer('block1_conv2').trainable = False
6model.get_layer('block2_conv1').trainable = False
7model.get_layer('block2_conv2').trainable = False
8...

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۴ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
Machine Learning Mastery
۱ دیدگاه برای «یادگیری انتقال با پایتون در مدل‌های بینایی ماشین — راهنمای کاربردی»

سلام
ممنون از آموزش و توضیحاتتون
من وقتی سعی میکنم مطابق توضیحاتتون مدل های VGG و … رو بارگذاری کنم با این ارور مواجه میشم “# load model without classifier layers
model = VGG16(include_top=False, input_shape=(300, 300, 3)) ” با توجه به جستجوهایی که انجام دادم این مشکل مربوط به محدودیت‌های اینترنت هست ولی متاسفانه ابزارهای کمکی که امتحان کردم جواب نداد. ممکنه راهنماییم کنید که ببینم مشکل از کجاست؟ یا راهی هست که بشه وزن های یک مدل رو ذخیره کرد و بعد ازشون استفاده کرد؟

نظر شما چیست؟

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