شبکه های Siamese و آموزش آن با استفاده از Keras، TensorFlow و یادگیری عمیق
در این مقاله آموزشی میآموزید شبکه های Siamese را با استفاده از Keras، TensorFlow و یادگیری عمیق آموزش دهید و پیادهسازی کنید.
مقاله آموزشی پیشرو، بخش دوم از یک مقاله سه قسمتی است که به بررسی و مطالعه مبانی شبکههای عصبی 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 را نشان میدهد. با نگاه اول متوجه خواهید شد که معماری شبکه Siamese با معماری سایر شبکههای طبقهبندی تفاوت دارد.
همانگونه که در تصویر فوق مشاهده میکنید، این شبکه دو ورودی و دو شاخه ( شبکههای همتاSister network ) دارد. هر یک از این شبکههای همتا کاملاً مشابه دیگری است. خروجی دو شبکه فرعی با یکدیگر ترکیب میشود و شبکه بر همین مبنا نرخ تشابه را خروجی میدهد.
برای درک بهتر این موضوع، به شکل 1 نگاه کنید:
- در سمت چپ دو نمونه عددی (از دیتاست MNIST) به مدل Siamese ارائه میکنیم.هدف ما این است که مشخص کنیم آیا دو عدد به یک کلاس تعلق دارند یا خیر.
- در قسمت میانی تصویر شبکه Siamese نشان داده شده است. دو شبکه فرعی معماری و پارامترهای یکسانی دارند و آینه یکدیگر هستند -به عبارت دیگر اگر وزنهای یک شبکه فرعی را به روزرسانی کنیم، وزنهای شبکه فرعی دوم هم به رزورسانی میشوند.
- هر یک از شبکههای فرعی یک لایه کاملاً متصل (FC) خروجی میدهد. به طور معمول فاصله اقلیدسی میان این خروجی را محاسبه کرده و از تابع فعالسازی سیگموید آن را عبور میدهیم تا مشخص کنیم این دو خروجی تا چه میزان با یکدیگر شباهت دارند. در صورتیکه مقدار تابع فعالسازی سیگموید نزدیک به “1” باشد، به این معنا است که دو خروجی به یکدیگر شباهت دارند و مقادیر نزدیک به “0” نشان میدهند که دو خروجی شباهت کمی با یکدیگر دارند.
برای آموزش معماری شبکه Siamese، میتوانیم از تعدادی توابع هزینه، از جمله آنتروپی متقاطع دودویی، تابع هزینه سهگانه و تابع هزینه مقایسهای، استفاده کنیم.
دو تابع آخر به سه تصویر نیاز دارند (سه تصویری ورودی به شبکه) که با جفتهای تصویری (دو تصویر ورودی) که امروز استفاده میکنیم، تفاوت دارند.
در مقاله آموزشی پیشرو برای آموزش شبکههای Siamese از تابع آنتروپی متقاطع دودویی استفاده میکنیم.
پیکربندی محیط توسعه
در این سری مقالات آموزشی از کتابخانههای Keras و TensorFlow برای آموزش شبکه های Siamese کمک میگیریم. به همین دلیل از شما می خواهم محیط توسعه یادگیری عمیق خود را هماکنون پیکربندی کنید.
برای نصب TensorFlow و یا Keras بر روی سیستم خود میتوانید از یکی از دو راهنمای مقابل کمک بگیرید:
هر دو مطالب آموزشی فوق به شما کمک خواهند کرد نرمافزارهای مورد نیاز ( برای انجام پروژه پیشرو) را بر روی سیستم خود و در یک محیط مجازی پایتون نصب کنید.
آیا در پیکربندی محیط توسعه به مشکل خوردهاید؟
ساختار پروژه
پس از آموزش شبکه 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 از 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...
همانگونه که در نمودار فوق مشاهده میکنید، مدل در مجموعه اعتبارسنجی به نرخ دقت 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 که آموزش دیده و ذخیره شده چگونه میتواند شباهتهای میان تصاویر را پیشبینی کند.