پوشش رسانه‌ای جیتکس ۲۰۲۴ | با ما همراه باشید

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

شبکه های Siamese و آموزش آن با استفاده از Keras، TensorFlow و یادگیری عمیق

زمان مطالعه: 15 دقیقه

در این مقاله آموزشی می‌آموزید شبکه های Siamese را با استفاده از Keras، TensorFlow و یادگیری عمیق آموزش دهید و پیاده‌سازی کنید.

شبکه های Siamese

مقاله آموزشی پیش‌رو، بخش دوم از یک مقاله سه قسمتی است که به بررسی و مطالعه مبانی شبکه‌های عصبی Siamese می‌پردازد:

  • بخش اول: ایجاد جفت‌های تصویری برای شبکه های Siamese به کمک پایتون
  • بخش دوم: آموزش شبکه‌های عصبی Siamese به کمک Keras، TensorFlow و یادگیری عمیق
  • بخش سوم:‎ یافتن شباهت‌های‌ میان تصاویر با استفاده از شبکه‌های siamese

در صورت استفاده از پیاده‌‌سازی شبکه عصبی Siamese‌‌، می‌توانیم:

  • دو ورودی به شبکه‌مان بدهیم
  • شبکه می‌تواند پیش‌بینی کند آیا دو تصویر به یک کلاس واحد تعلق دارند یا به دو کلاس متفاوت ( برای مثال تأئید اصالت)
  • می‌توانیم ضریب اطمینان Confidence score شبکه را بررسی کنیم تا از درستی نتایج تأئید اصالت مطمئن شویم

از جمله موارد کاربرد شبکه‌های عصبی Siamese می‌توان به بازشناسایی چهره، تأئید اصالت امضا، تطبیق نسخه‌های دارویی و غیره اشاره کرد.

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

برای آشنایی با شیوه پیاده‌سازی و آموزش شبکه های Siamese با استفاده از Keras و TensdorFlow تا پایان این مقاله آموزشی با ما همراه باشید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

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

در گام بعدی شیوه پیکربندی محیط توسعه و آموزش شبکه‌های عصبی Siamese را به شما آموزش خواهیم داد.

سپس ساختار دایرکتوری پروژه را با یکدیگر بازبینی و فایل پیکربندی را اجرا خواهیم کرد و در این فرایند از سه تابع کمکی استفاده خواهیم کرد:

  • برای ایجاد جفت‌های تصویری از متدی بهره می‌گیریم و سپس با استفاده از این جفت‌های تصویری شبکه Siamese را آموزش می‌دهیم
  • از یک لایه سفارشی CNN برای محاسبه فاصله‌های اقلیدسی میان بُردارهای موجود در شبکه استفاده می‌کنیم
  • از یک برنامه کمکی برای نگاشت روند آموزشی شبکه Siamese در دیسک استفاده می‌کنیم

شبکه های Siamese چه نوع شبکه‌هایی هستند و شیوه کاری آن‌ها به چه شکل است؟

شبکه های Siamese
شکل 1: پیاده‌سازی معماری شبکه Siamese دو ورودی می‌گیرد (چپ)، دو شبکه فرعی CNN یکسان برای هر یک از ورودی‌ها دارد و هر یک از یک لایه کاملاً متصل خروجی می‌دهند. فاصله اقلیدسی خروجی دو شبکه محاسبه و از طریق تابع فعال‌سازی سیگموید میزان تشابه را مشخص کند (راست)

در بخش اول از این سری مقالات به بررسی و مطالعه مبانی شبکه‌های عصبی Siamese، روند کاری و موارد کاربرد آن‌ها در دنیای واقعی پرداختیم. در ادامه توضیح مختصری از مباحث بخش اول ارائه می‌دهم، اما به شما توصیه می‌کنم برای آن‌که درک و شناخت جامعی از این شبکه‌ها پیدا کنید، بخش اول را مطالعه کنید.

شکل 1 معماری شبکه Siamese را نشان می‌دهد. با نگاه اول متوجه خواهید شد که معماری شبکه Siamese با معماری سایر شبکه‌های طبقه‌بندی تفاوت دارد.

همان‌گونه که در تصویر فوق مشاهده می‌کنید، این شبکه دو ورودی و دو شاخه ( شبکه‌های همتاSister network ) دارد. هر یک از این شبکه‌های همتا کاملاً مشابه دیگری است. خروجی دو شبکه فرعی با یکدیگر ترکیب می‌شود و شبکه بر همین مبنا نرخ تشابه را خروجی می‌دهد.

برای درک بهتر این موضوع، به شکل 1 نگاه کنید:

  • در سمت چپ دو نمونه عددی (از دیتاست MNIST) به مدل Siamese ارائه می‌کنیم.هدف ما این است که مشخص کنیم آیا دو عدد به یک کلاس تعلق دارند یا خیر.
  • در قسمت میانی تصویر شبکه Siamese نشان داده شده است. دو شبکه فرعی معماری و پارامترهای یکسانی دارند و آینه یکدیگر هستند -به عبارت دیگر اگر وزن‌های یک شبکه فرعی را به روزرسانی کنیم، وزن‌های شبکه فرعی دوم هم به رزورسانی می‌شوند.
  • هر یک از شبکه‌های فرعی یک لایه کاملاً متصل (FC) خروجی می‌دهد. به طور معمول فاصله اقلیدسی میان این خروجی را محاسبه کرده و از تابع فعال‌سازی سیگموید آن را عبور می‌دهیم  تا مشخص کنیم این دو خروجی تا چه میزان با یکدیگر شباهت دارند. در صورتی‌که مقدار تابع فعال‌سازی سیگموید نزدیک به “1” باشد، به این معنا است که دو خروجی به یکدیگر شباهت دارند و مقادیر نزدیک به “0” نشان می‌دهند که دو خروجی شباهت کمی با یکدیگر دارند.

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

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

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

پیکربندی محیط توسعه

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

برای نصب TensorFlow و یا Keras بر روی سیستم خود می‌توانید از یکی از دو راهنمای مقابل کمک بگیرید:

هر دو مطالب آموزشی فوق به شما کمک خواهند کرد نرم‌افزارهای مورد نیاز ( برای انجام پروژه پیش‌رو) را بر روی سیستم خود و در یک محیط مجازی پایتون نصب کنید.

آیا در پیکربندی محیط توسعه به مشکل خورده‌اید؟

پیکربندی محیط توسعه
شکل 2: آیا در پیکربندی محیط توسعه به مشکل خورده‌اید؟ در صورت تمایل به استفاده از به نوت‌بوک‌های Jupyter که از قبل پیکربندی شده‌اند و بر روی Google Colab اجرا می‌شوند، به عضویت PyImageSearch Plus درآیید.

ساختار پروژه

پس از آموزش شبکه Siamese بهتر است ساختار دایرکتوری پروژه را با یکدیگر بررسی کنیم.

برای دانلود کد، مدل شبکه Siamese که از پیش آموزش دیده  به قسمت “Downloads” مراجعه کنید.

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

1	$ tree . --dirsfirst
2	.
3	├── output
4	│ ├── siamese_model
5	│ │ ├── variables
6	│ │ │ ├── variables.data-00000-of-00001
7	│ │ │ └── variables.index
8	│ │ └── saved_model.pb
9	│ └── plot.png
10	├── pyimagesearch
11	│ ├── config.py
12	│ ├── siamese_network.py
13	│ └── utils.py
14	└── train_siamese_network.py
15	
16	2 directories, 6 files

در ماژول pyimagesearch سه کد پایتون داریم:

  • Config.py : پارامترهای مهم از جمله ابعاد تصویر ورود، سایز دسته، تعداد دوره و غیره ذخیره می‌شود.
  • Siamese_netwrok.py : پیاده‌سازی شبکه (شبکه‌های همتا) در معماری مدل Siamese
  • Utils.py : شامل برنامه‌های کمکی است که از آن‌ها برای ایجاد جفت‌های تصویری استفاده می‌شود (که در قسمت اول راجع به آن‌ها توضیح دادیم)، فاصله اقلیدسی را به عنوان یک لایه Keras و TensorFlow محاسبه می‌کند و روند آموزش شبکه را به دیسک نگاشت می‌کند.

Train_siamese_netwrok.py  از سه کد پایتون که در ماژول pyimagesearch قرار دارند، استفاده می‌کند تا:

  • دیتاست MNIST را از دیسک بارگذاری کند
  • جفت‌های تصویری مثبت و منفی از MNIST تولید کند
  • معماری شبکه Siamese را بسازد
  • جفت‌های تصویری را به شبکه Siamese آموزش دهد
  • مدل شبکه Siamese را سریال‌سازی کند و روند آموزشی را به دایرکتوری output نگاشت کند

در گام بعدی فایل پیکربندی را ایجاد می‌کنیم.

نکته: مدل از پیش‌آموزش دیده، که از بخش “Downloads” می‌توانید به آن دسترسی داشته باشید با استفاده از TensorFlow 2.3  آموزش دیده است. به همین دلیل به شما توصیه می‌کنم از TensorFlow 2.3 استفاده کنید. چنان‌چه ترجیح می‌دهید از نسخه متفاوتی از TensorFlow استفاده کنید، مشکلی ندارد. فقط برای آموزش و سریال‌سازی مدل باید، train_siamese_network.py  را اجرا کنید. البته توجه داشته باشید که باید این مدل را برای قسمت سوم و آخر این سری مقالات آموزشی ذخیره کنید؛ در قسمت آخر این مقاله آموزشی برای مقایسه تصاویر از شبکه Siamese که آموزش دیده استفاده می‌کنیم.

ایجاد فایل پیکربندی شبکه Siamese

فایل پیکربندی ما کوتاه است. config.py  را باز کنید و کدل مقابل را وارد کنید:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

1	# import the necessary packages
2	import os
3	
4	# specify the shape of the inputs for our network
5	IMG_SHAPE = (28, 28, 1)
6	
7	# specify the batch size and number of epochs
8	BATCH_SIZE = 64
9	EPOCHS = 100

خط 5 ابعاد ورودی IMG_SHAPE  را مقداردهی می‌کند. از آنجایی‌که از دیتاست عددی MNIST استفاده می‌کنیم، تصاویر ما 28×28 با یک کانال سیاه و سفید هستند.

سپس BATCH_SIZE   و تعداد تکرار آموزش را مشخص می‌کنیم.

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

در گام بعدی مسیرهای خروجی را مشخص می‌کنیم:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

11	# define the path to the base output directory
12	BASE_OUTPUT = "output"
13	
14	# use the base output path to derive the path to the serialized
15	# model along with training history plot
16	MODEL_PATH = os.path.sep.join([BASE_OUTPUT, "siamese_model"])
17	PLOT_PATH = os.path.sep.join([BASE_OUTPUT, "plot.png"])

خط 12 مسیر BASE_OUTPUT  را به عنوان دایرکتوری output راه‌اندازی می‌کند.

سپس از مسیر BASE_OUTPUT  برای پیدا کردن مسیر دسترسی به MODEL_PATH  استفاده می‌کنیم؛ MODEL_PATH  مدل سریال سازی شده Keras/ TensorFlow است.

از آنجایی که برای پیاده‌سازی شبکه Siamese به یک لایه Lambda نیاز داریم، از فرمت SaveModel استفاده می‌کنیم که طبق سند TensorFlow بهتر می‌تواند اشیای و پیاده‌سازی‌های سفارشی را مدیریت کند.

خروجی فرمت SaveModel یک دایرکتوری مدل شامل بهینه‌ساز، توابع زیان و متریک‌ها (saved_model.pb ) و هم‌چنین وزن‌های مدل خواهد بود ( که در یک دایرکتوری /variables  ذخیره می‌شوند).

پیاده‌سازی معماری شبکه Siamese با استفاده از Keras و TensorFlow

معماری شبکه Siamese
شکل 3: در هنگام ساخت مدل Siamese، معماری پایه ConvNet را پیاده‌سازی خواهیم کرد که از آن برای شبکه‌های همتا استفاده کردیم.

معماری شبکه Siamese از 2 یا بیش از 2 شبکه همتا تشکیل می‌شود ( در شکل 3  با رنگ قرمز نشان داده شده‌اند). در واقع شبکه همتا، یک شبکه عصبی کانولوشن ساده است که یک لایه کاملاً متصل (FC) را خروجی می‌دهد که برخی مواقع به آن لایه تعبیه شده گفته می‌شود.

در هنگام ساخت معماری شبکه Siamese :

  • برای شبکه‌های همتا نمونه سازیInstantiate  می‌کنیم
  • یک لایه Lambda می‌سازیم که فاصله اقلیدسی میان خروجی‌های دو شبکه همتا را محاسبه کند
  • یک لایه FC با یک گره و یک تابع فعال‌سازی سیگموید ایجاد می‌کنیم

در نتیجه یک شبکه Siamese ایجاد می‌شود.

اما ابتدا باید  شبکه همتای معماری شبکه Siamese را پیاده‌سازی کنیم.

در دایرکتوری پروژه خود، Siamese_netwrok.py  را باز کنید:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

1	# import the necessary packages
2	from tensorflow.keras.models import Model
3	from tensorflow.keras.layers import Input
4	from tensorflow.keras.layers import Conv2D
5	from tensorflow.keras.layers import Dense
6	from tensorflow.keras.layers import Dropout
7	from tensorflow.keras.layers import GlobalAveragePooling2D
8	from tensorflow.keras.layers import MaxPooling2D

خط 2 تا 8 پکیج‌های پایتون مورد نیاز را بارگذاری می‌کنند. اگر قبلاً هم با استفاده از Keras یا TensorFlow یک CNN آموزش داده‌اید، به خوبی اهمیت بارگذاری این پکیج‌ها را درک می‌کنید.

برای آشنایی بیشتر با CNNها به شما توصیه می‌کند مقاله آموزشی من را با موضوع Keras و کتاب من تحت عنوان یادگیری عمیق برای بینایی کامپیوتر به کمک پایتون را مطالعه کنید.

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

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

10	def build_siamese_model(inputShape, embeddingDim=48):
11	 # specify the inputs for the feature extractor network
12	 inputs = Input(inputShape)
13	
14	 # define the first set of CONV => RELU => POOL => DROPOUT layers
15	 x = Conv2D(64, (2, 2), padding="same", activation="relu")(inputs)
16	 x = MaxPooling2D(pool_size=(2, 2))(x)
17	 x = Dropout(0.3)(x)
18	
19	 # second set of CONV => RELU => POOL => DROPOUT layers
20	 x = Conv2D(64, (2, 2), padding="same", activation="relu")(x)
21	 x = MaxPooling2D(pool_size=2)(x)
22	 x = Dropout(0.3)(x)

تابع build_siamese_model دو پارامتر می‌پذیرد:

  • inputShape : ابعاد (طول، عرض و تعداد کانال‌ها) تصاویر ورودی. چنان‌چه از دیتاست MNIST استفاده کنیم، تصاویر ورودی 1×28×28 خواهند بود.
  • embeddingDim : ابعاد لایه آخر شبکه که کاملاً متصل است را خروجی می‌دهد.

خط 12 ابعاد ورودی را برای شبکه همتا مقداردهی می‌کند.

خط 15 تا 22 دو مجموعه از مجموعه‌ لایه‌‌های CONV => RELU => POOL  تعریف می‌کند. هر لایه CONV در مجموع 64 فیلتر 2×2  را می‌آموزد. سپس تابع فعال‌سازی ReLU را اجرا کرده و ادغام بیشینه Max pooling  را با یک گام 2×2 اعمال می‌کنیم.

و پایان ساخت معماری شبکه Siamese:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

24	 # prepare the final outputs
25	 pooledOutput = GlobalAveragePooling2D()(x)
26	 outputs = Dense(embeddingDim)(pooledOutput)
27	
28	 # build the model
29	 model = Model(inputs, outputs)
30	
31	 # return the model to the calling function
32	 return model

 

خط 25 ادغام میانگین عمومی Global average pooling را بر روی حجم 64×7×7  اعمال می‌کند (با فرض ورودی 28×28 شبکه) و در نتیجه یک خروجی 64 بُعدی به دست می‌آید.

pooledOutput را می‌گیریم و سپس یک لایه کاملاً متصل به اندازه بُعد embeddingDim اعمال می‌کنیم (خط 26)؛ این لایه Dense خروجی شبکه همتا خواهد بود.

خط 29، Model شبکه همتا را می‌سازد که به تابع فراخون می‌شود.

در ادامه می‌توانید خلاصه‌ای از مدل را مشاهده کنید:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

1	Model: "model"
2	_________________________________________________________________
3	Layer (type) Output Shape Param # 
4	=================================================================
5	input_3 (InputLayer) [(None, 28, 28, 1)] 0 
6	_________________________________________________________________
7	conv2d (Conv2D) (None, 28, 28, 64) 320 
8	_________________________________________________________________
9	max_pooling2d (MaxPooling2D) (None, 14, 14, 64) 0 
10	_________________________________________________________________
11	dropout (Dropout) (None, 14, 14, 64) 0 
12	_________________________________________________________________
13	conv2d_1 (Conv2D) (None, 14, 14, 64) 16448 
14	_________________________________________________________________
15	max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0 
16	_________________________________________________________________
17	dropout_1 (Dropout) (None, 7, 7, 64) 0 
18	_________________________________________________________________
19	global_average_pooling2d (Gl (None, 64) 0 
20	_________________________________________________________________
21	dense (Dense) (None, 48) 3120 
22	=================================================================
23	Total params: 19,888
24	Trainable params: 19,888
25	Non-trainable params: 0
26	_________________________________________________________________

مدلی که ساختیم به شرح زیر است:

  • هر شبکه همتا یک ورودی 1×28×28 دریافت می‌کند.
  • سپس یک لایه CONV اعمال می‌کنیم تا 64 فیلتر را بیاموزد. ادغام بیشینه با یک گام 2×2 اعمال می‌شود تا ابعاد را به 64×14×14  کاهش دهد.
  • یک لایه CONV دیگر ( که 64 فیلتر را می‌آموزد) و لایه ادغام اعمال می‌شوند و ابعاد را به 64×7×7 کاهش می‌دهند.
  • ادغام میانگین عمومی اعمال می‌شود تا حجم 64×7×7 به 64 بُعد کاهش دهد.
  • خروجی 64 بُعدی ادغام به لایه FC که 48 گره دارد، منتقل می‌شود.
  • بُردار 48 بعدی، خروجی شبکه همتا خواهد بود.

در کد train_siamese_network.py  شیوه ایجاد دو نمونه از شبکه همتا را می‌آموزید و سپس ساخت معماری شبکه Siamese به پایان می‌رسد.

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

پس از پیاده‌سازی فایل پیکربندی، شبکه همتای معماری شبکه siamese، نوبت به توابع کمکی و متدهایی می‌رسد که در فایل utils.py  ماژول pyimagesearch قرار دارند.

فایل utils.py  را باز کنید:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

1	# import the necessary packages
2	import tensorflow.keras.backend as K
3	import matplotlib.pyplot as plt
4	import numpy as np

خط 2 تا 4 پکیج‌های پایتون که به آن‌ها نیاز داریم را بازگذاری می‌کنند.

Keras/ TensorFlow بَک‌اِند را بارگذاری می‌کنیم و از این طریق می‌توانیم لایه سفارشی Lambda فاصله اقلیدسی را بسازیم.

از کتابخانه matplotlib برای ساخت یک تابع کمکی استفاده می‌کنیم؛ این تابع کمکی روند آموزش شبکه را نگاشت می‌کند.

اکنون تابع make_pairs  را داریم که در بخش اول این سری مقالات آن را به طور کامل معرفی کردیم:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

6	def make_pairs(images, labels):
7	 # initialize two empty lists to hold the (image, image) pairs and
8	 # labels to indicate if a pair is positive or negative
9	 pairImages = []
10	 pairLabels = []
11	
12	 # calculate the total number of classes present in the dataset
13	 # and then build a list of indexes for each class label that
14	 # provides the indexes for all examples with a given label
15	 numClasses = len(np.unique(labels))
16	 idx = [np.where(labels == i)[0] for i in range(0, numClasses)]
17	
18	# loop over all images
19	for idxA in range(len(images)):
20	  # grab the current image and label belonging to the current
21	  # iteration
22	  currentImage = images[idxA]
23	  label = labels[idxA]
24	
25	  # randomly pick an image that belongs to the *same* class
26	  # label
27	  idxB = np.random.choice(idx[label])
28	  posImage = images[idxB]
29	
30	  # prepare a positive pair and update the images and labels
31	  # lists, respectively
32	  pairImages.append([currentImage, posImage])
33	  pairLabels.append([1])
34	
35	  # grab the indices for each of the class labels *not* equal to
36	  # the current label and randomly pick an image corresponding
37	  # to a label *not* equal to the current label
38	  negIdx = np.where(labels != label)[0]
39	  negImage = images[np.random.choice(negIdx)]
40	
41	  # prepare a negative pair of images and update our lists
42	  pairLabels.append([0])
43	  pairLabels.append([0])
44	
45	 # return a 2-tuple of our image pairs and labels
46	 return (np.array(pairImages), np.array(pairLabels))

 

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

  • برای آموزش شبکه Siamese به جفت مثبت و هم‎چنین به جفت منفی نیاز داریم
  • جفت مثبت به تصاویری گفته می‌شود که به یک کلاس واحد تعلق دارند ( برای مثال دو نمونه از عدد 8)
  • جفت منفی به تصاویر گفته می‌شود که به کلاس‌های مختلف تعلق دارند ( برای مثال، یک تصویر 1 را نشان می‌دهد و تصویر دیگر 3)
  • تابع make_pairs  یک مجموعه ورودی از images و labels مرتبط با آن‌ها را دریافت می‌کند و سپس جفت‌های مثبت و جفت‌های منفی را برای آموزش ایجاد می‌کند و آن‌ها را به تابع فراخون باز می‌گرداند.

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

تابع بعدی ما euclidean_distance  است که یک vectors  دوگانه دریافت می‌کند و سپس با استفاده از توابع Keras/ TensorFlow فاصله اقلیدسی میان آن‌ها را محاسبه می‌کند:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

48	def euclidean_distance(vectors):
49	 # unpack the vectors into separate lists
50	 (featsA, featsB) = vectors
51	
52	 # compute the sum of squared distances between the vectors
53	 sumSquared = K.sum(K.square(featsA - featsB), axis=1,
54	  keepdims=True)
55	
56	 # return the euclidean distance between the vectors
57	 return K.sqrt(K.maximum(sumSquared, K.epsilon()))

تابع euclidean_distance  فقط یک پارامتر، vectors ، می‌گیرد؛ vectors  خروجی لایه‌های کاملاً متصل شبکه‌های همتا و هم‌چنین معماری شبکه Siamese است.

vectors  را به دو بخش featsA و featsB تقسیم می‌کنیم (خط 50) و سپس مجموع تفاوت مربعSquared difference  میان این بُردارها را محاسبه می‌کنیم (خط 53 و 54).

سپس ریشه دوم مجموع تفاوت‌های مربع را به دست می‌آوریم و تابع را روند می‌کنیم و فاصله اقلیدسی به دست می‌آید (خط 57).

به یاد داشته باشید که ما به جای NumPy و SciPy، از توابع Keras/TensorFlow باری محاسبه فاصله اقلیدسی استفاده می‌کنیم.

حتماً می‌پرسید چرا؟

بهتر نیست از توابع فاصله NumPy و SciPy استفاده کنیم؟

چرا به خودمان زحمت بدیم و مجدداً فاصله اقلیدسی را با Keras/TensorFlow پیاده‌سازی کنیم؟

زمانی که به کد train_siamese_network.py  برسیم، دلیل آن‌ را بهتر درک خواهید کرد، اما لب کلام این است که برای ساخت معماری شبکه Siamese، باید بتوانیم فاصله اقلیدسی میان خروجی‌های شبکه همتا و معماری Siamese را محاسبه کنیم.

برای دستیابی به این هدف از یک لایه سفارشی Lambda استفاده خواهیم کرد که با استفاده از آن می‌توانیم توابع دلخواه Keras/TensorFlow را درون یک مدل تعبیه کنیم ( چرا از توابع Keras/TensorFlow برای محاسبه فاصله اقلیدسی استفاده می‌کنیم؟)

آخرین تابع، plot_training 1  با فراخوان model.fit ، روند آموزشی و 2 یک خروجی plotPath  می‌پذیرد.

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

59	def plot_training(H, plotPath):
60	 # construct a plot that plots and saves the training history
61	 plt.style.use("ggplot")
62	 plt.figure()
63	 plt.plot(H.history["loss"], label="train_loss")
64	 plt.plot(H.history["val_loss"], label="val_loss")
65	 plt.plot(H.history["accuracy"], label="train_acc")
66	 plt.plot(H.history["val_accuracy"], label="val_acc")
67	 plt.title("Training Loss and Accuracy")
68	 plt.xlabel("Epoch #")
69	 plt.ylabel("Loss/Accuracy")
70	 plt.legend(loc="lower left")
71	 plt.savefig(plotPath)

متغیر روند آموزشی مدل H خواهد بود و بر همین اساس زیان و دقت آموزش و اعتبارسنجی را نگاشت می‌کنیم. نگاشت خروجی در دیسک و در plotPath ذخیره می‌شود.

ایجاد کد آموزش شبکه Siamese با استفاده از Keras و TensorFlow

اکنون می‌توانیم کد آموزش شبکه Siamese را اجرا کنیم!

در کد train_siamese_network.py :

  • دیتاست MNIST را از دیسک بارگذاری می‌کنیم.
  • جفت‌های تصویری آموزشی و آزمایشی را ایجاد می‌کنیم.
  • دو نمونه ازbuild_siamese_model  ایجاد می‌کنیم که در نقش شبکه‌های همتا عمل کنند.
  • خروجی‌های شبکه‌های همتا را از طریق تابع سفارشی euclidean_distance  نمایش می‌دهیم و فرایند ساخت معماری شبکه Siamese را به اتمام می‌رسانیم.
  • تابع فعال‌سازی سیگموید را بر روی خروجی فاصله اقلیدسی اجرا می‌کنیم.
  • معماری شبکه Siamese را با جفت‌های تصویری آموزش می‌دهیم.

 

ممکن است در نگاه اول این فرایند پیچیده به نظر برسد. اما تمامی این کارها را می‌توانیم با کمتر از 60 خط کد انجام دهیم!

train_siamese_network.py  را باز کنید و :

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

1	# import the necessary packages
2	from pyimagesearch.siamese_network import build_siamese_model
3	from pyimagesearch import config
4	from pyimagesearch import utils
5	from tensorflow.keras.models import Model
6	from tensorflow.keras.layers import Dense
7	from tensorflow.keras.layers import Input
8	from tensorflow.keras.layers import Lambda
9	from tensorflow.keras.datasets import mnist
10	import numpy as np

خط 2 تا 10 پکیج‌های پایتون که به ان‌ها نیاز داریم را بارگذاری می‌کنند. مهم‌ترین این پکیج‌ها عبارتند از:

  • build_siamese_model : مولفه‌های شبکه همتای معماری شبکه Siamese را می‌سازد.
  • config : پیکربندی‌های آموزش را ذخیره می‌کند.
  • utils  : شامل توابع کمکی است که از آن‌ها برای ساخت جفت‌های تصویری، نگاشت روند آموزشی، محاسبه فاصله اقلیدسی به کمک توابع Keras/TensorFlow استفاده کردیم.
  • Lambda : فاصله اقلیدسی را می‌گیرد و در معماری شبکه Siamese تعبیه می‌کند.

پس از بارگذاری پکیج‌های مورد نیاز می‌توانیم دیتاست MNIST را از دیسک بارگذاری و پیش‌پردازش کنیم و جفت‌های تصویری را ایجاد کنیم:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

12	# load MNIST dataset and scale the pixel values to the range of [0, 1]
13	print("[INFO] loading MNIST dataset...")
14	(trainX, trainY), (testX, testY) = mnist.load_data()
15	trainX = trainX / 255.0
16	testX = testX / 255.0
17	
18	# add a channel dimension to the images
19	trainX = np.expand_dims(trainX, axis=-1)
20	testX = np.expand_dims(testX, axis=-1)
21	
22	# prepare the positive and negative pairs
23	print("[INFO] preparing positive and negative pairs...")
24	(pairTrain, labelTrain) = utils.make_pairs(trainX, trainY)
25	(pairTest, labelTest) = utils.make_pairs(testX, testY)

خط 14 دیتاست عددی MNIST را از دیسک بارگذاری می‌کند.

سپس تصاویر MNIST را از [0,255] به [0,1] مقیاس‌بندی می‌کنیم و بدین وسیله آن‌ها را پیش پردازش می‌کنیم (خط‌های 15 و 16) و سپس یک کانال بُعد اضافه می‌کنیم (خط‌های 19 و 20).

از تابع make_pairs  برای ایجاد جفت‌های مثبت و منفی مجموعه‌های آموزشی و آزمایشی استفاده می‌کنیم (خط‌های 24 و 25). برای آشنایی بیشتر با تابع make_pairs  بخش اول این مقاله را مطالعه کنید.

حالا معماری شبکه Siamese را می‌سازیم:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

27	# configure the siamese network
28	print("[INFO] building siamese network...")
29	imgA = Input(shape=config.IMG_SHAPE)
30	imgB = Input(shape=config.IMG_SHAPE)
31	featureExtractor = build_siamese_model(config.IMG_SHAPE)
32	featsA = featureExtractor(imgA)
33	featsB = featureExtractor(imgB)

خط 29 تا 33 شبکه‌های همتا را می‌سازند.

  • ابتدا دو ورودی، برای هر کدام از تصاویر موجود در جفت تصویری یک ورودی، می‌سازیم (خط‌های 29 و 30).
  • خط 31 معماری شبکه همتا را می‌سازد که نقش featureExtractor را دارد.
  • هر یک از تصاویر موجود در جفت تصویری از featureExtractor رد می‌شود و در نتیجه یک بُردار ویژگی 48 بُعدی شکل می‌گیرد (خط‌های 32 و 33). از آنجایی که در هر جفت دو تصویر وجود دارد، دو بُردار ویژگی 48 بُعدی خواهیم داشت.

شاید این سؤال برای‌تان پیش بیاید که چرا build_siamese_model  را دوبار فراخون نکردیم؟خب ما دو شبکه همتا داریم، درست است؟

درسی که در بخش اول یاد گرفتید را هیچ وقت فراموش نکنید:

« دو شبکه همتا معماری و پارامترهای یکسانی دارند و آینه یکدیگر هستند. به عبارت دیگر اگر وزن‌های یک شبکه فرعی را به روزرسانی کنیم، وزن‌های شبکه فرعی دوم هم به رزورسانی می‌شوند.»

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

و برای اتمام فرایند ساخت معماری شبکه Siamese:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

35	# finally, construct the siamese network
36	distance = Lambda(utils.euclidean_distance)([featsA, featsB])
37	outputs = Dense(1, activation="sigmoid")(distance)
38	model = Model(inputs=[imgA, imgB], outputs=outputs)

خط 36 برای محاسبه euclidean_distance  میان featsA و  featsB شبکه از یک لایه Lambda استفاده می‌کند (به یاد داشته باشید که اگر هر یک از تصاویر موجود در جفت‌های تصویری را از طریق استخراج کننده ویژگی شبکه همتا منتقل کنیم این مقادیر ایجاد می‌شوند (خروجی)).

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

خروجی تابع [0,1] مقیاس‌بندی شده و به همین دلیل در اینجا از تابع فعال‌سازی سیگموید استفاده می‌کنیم. اگر به 0  نزدیک باشد بدین معنی است که جفت‌های تصویری شباهت کمی با یکدیگر دارند ( و متعلق به کلاس‌های گوناگونی هستند) و اگر مقدار خروجی نزدیک به 1  باشد، می‌توانیم نتیجه بگیریم که جفت‌های تصویری شباهت زیادی به هم دارند ( و احتمال اینکه به یک کلاس یکسان تعلق داشته باشند، زیاد است).

خط 38 Model شبکه Siamese را می‌سازد. inputs شامل جفت تصویری، یعنی همان imgA و imgB است. outputs شبکه تابع فعال‌سازی سیگموید است.

پس از اتمام فرایند ساخت معماری شبکه Siamese می‌توانیم آموزش را آغاز کنیم:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

40	# compile the model
41	print("[INFO] compiling model...")
42	model.compile(loss="binary_crossentropy", optimizer="adam",
43	 metrics=["accuracy"])
44	
45	# train the model
46	print("[INFO] training model...")
47	history = model.fit(
48	 [pairTrain[:, 0], pairTrain[:, 1]], labelTrain[:],
49	 validation_data=([pairTest[:, 0], pairTest[:, 1]], labelTest[:]),
50	 batch_size=config.BATCH_SIZE, 
51	 epochs=config.EPOCHS)

خط‌های 42 و 43 تابع هزینه آنتروپی متقاطع دودویی را در نظر می‌گیرند و شبکه Siamese را کامپایل می‌کنند.

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

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

خط 47 تا 51 شبکه Siamese را با جفت‌های تصویری آموزش می‌دهند.

پس از اتمام فرایند آموزش مدل، می‌توانیم آن را در حافظه ذخیره کنیم و روند آموزشی را ترسیم کنیم:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

53	# serialize the model to disk
54	print("[INFO] saving siamese model...")
55	model.save(config.MODEL_PATH)
56	
57	# plot the training history
58	print("[INFO] plotting training history...")
59	utils.plot_training(history, config.PLOT_PATH)

تبریک! شما توانستید با موفقید کد آموزش شبکه Siamese را اجرا کنید!

آموزش شبکه Siamese با استفاده از Keras و TensorFlow

اکنون می‌توانیم شبکه Siamese را با استفاده از Keras و TensorFlow آموزش دهیم! برای دانلود کد به بخش “Downloads” مراجعه کنید.

سپس یک terminal باز کنید و فرمان مقابل را اجرا کنید:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

1	$ python train_siamese_network.py
2	[INFO] loading MNIST dataset...
3	[INFO] preparing positive and negative pairs...
4	[INFO] building siamese network...
5	[INFO] training model...
6	Epoch 1/100
7	1875/1875 [==============================] - 11s 6ms/step - loss: 0.6210 - accuracy: 0.6469 - val_loss: 0.5511 - val_accuracy: 0.7541
8	Epoch 2/100
9	1875/1875 [==============================] - 11s 6ms/step - loss: 0.5433 - accuracy: 0.7335 - val_loss: 0.4749 - val_accuracy: 0.7911
10	Epoch 3/100
11	1875/1875 [==============================] - 11s 6ms/step - loss: 0.5014 - accuracy: 0.7589 - val_loss: 0.4418 - val_accuracy: 0.8040
12	Epoch 4/100
13	1875/1875 [==============================] - 11s 6ms/step - loss: 0.4788 - accuracy: 0.7717 - val_loss: 0.4125 - val_accuracy: 0.8173
14	Epoch 5/100
15	1875/1875 [==============================] - 11s 6ms/step - loss: 0.4581 - accuracy: 0.7847 - val_loss: 0.3882 - val_accuracy: 0.8331
16	...
17	Epoch 95/100
18	1875/1875 [==============================] - 11s 6ms/step - loss: 0.3335 - accuracy: 0.8565 - val_loss: 0.3076 - val_accuracy: 0.8630
19	Epoch 96/100
20	1875/1875 [==============================] - 11s 6ms/step - loss: 0.3326 - accuracy: 0.8564 - val_loss: 0.2821 - val_accuracy: 0.8764
21	Epoch 97/100
22	1875/1875 [==============================] - 11s 6ms/step - loss: 0.3333 - accuracy: 0.8566 - val_loss: 0.2807 - val_accuracy: 0.8773
23	Epoch 98/100
24	1875/1875 [==============================] - 11s 6ms/step - loss: 0.3335 - accuracy: 0.8554 - val_loss: 0.2717 - val_accuracy: 0.8836
25	Epoch 99/100
26	1875/1875 [==============================] - 11s 6ms/step - loss: 0.3307 - accuracy: 0.8578 - val_loss: 0.2793 - val_accuracy: 0.8784
27	Epoch 100/100
28	1875/1875 [==============================] - 11s 6ms/step - loss: 0.3329 - accuracy: 0.8567 - val_loss: 0.2751 - val_accuracy: 0.8810
29	[INFO] saving siamese model...
30	[INFO] plotting training history...
شبکه های Siamese
شکل 4: آموزش دیتاست MNIST به شبکه Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

همان‌گونه که در نمودار فوق مشاهده می‌کنید، مدل در مجموعه اعتبارسنجی به نرخ دقت  10/88% ~ دست یافت. به زبان ساده مدل 88% مواقع می‌تواند به درستی یکسان بودن کلاس تصاویر ورودی را مشخص کند.

شکل 4 روند آموزش مدل را در بیش از 100 تکرار نشان می‌دهد. عملکرد مدل تا اندازه‌ای منجسم و ثابت است. با توجه به این که مقدار هزینه اعتبارسنجی کمتر از مقدار هزینه آموزش است می‌توان امیدوار بود که بتوانیم نرخ دقت مدل را با «آموزش بیشتر» افزایش داد.

اگر نگاهی به دایرکتوری output بیندازید، یک دایرکتوری به نام siamese_model خواهید دید:

برای دانلود کد بر روی این لینک کلیک کنید.

آموزش شبکه های Siamese با استفاده از Keras، TensorFlow و یادگیری عمیق

1	$ ls output/
2	plot.png siamese_model
3	$ ls output/siamese_model/
4	saved_model.pb variables

این دایرکتوری شامل شبکه Siamese ذخیره شده است. در سومین بخش از این سری مقالات شیوه مقایسه و یافتن شباهت‌های میان تصاویر ورودی را با استفاده از این شبکه‌ها می‌آموزید.

چکیده

در این مقاله آموزشی شیوه پیاده‌سازی و آموزش شبکه های Siamese را با استفاده از Keras ،TensorFlow و یادگیری عمیق آموختید.

در این نوشتار شبکه Siamese را با دیتاست MNIST آموزش دادیم. ورودی شبکه Siamese دو تصویری (تصویر عدد) است و سعی می‌کند مشخص کند این دو تصویر به یک کلاس واحد تعلق دارند یا به دو کلاس مختلف.

برای مثال، اگر دو تصویر به شبکه بدهیم و هر دوی آن‌ها شامل 9 باشند، شبکه Siamese اعلام می‌کند که شباهت زیادی میان دو تصویر است و دو تصویر به یک کلاس واحد تعلق دارند.

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

در این مقاله آموزش برای سهولت از دیتاست MNIST استفاده کردیم تا مبانی شبکه های Siamese را به خوبی بیاموزیم. این فرایند آموزش را می‌توانید در حوزه‌هایی از جمله تشخیص چهره، تأئید اصالت امضا و تطبیق نسخه‌های دارویی و غیره به کار ببندید.

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

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

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

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