مقدمه‌ای بر شبکه‌های عصبی و چارچوب Keras (کراس)

برای اجرای این مبحث نیاز به نصب کتابخانه کراس (Keras) دارید. برای نصب این کتابخانه میتوانید لینک زیر را مطالعه کنید.

http://blog.class.vision/1396/12/installing-keras-with-tensorflow-backend/

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

لود مجموعه داده (dataset)

پیش‌پردازش داده‌ها برای Keras

ابتدا تابعی ساده تعریف کرده ایم که ابعاد، نوع داده ای و اطلاعات دیتاست لود شده را چاپ کند.
این اطلاعات را قبل و بعد از پیش‌پردازش داده ها چاپ خواهیم کرد تا متوجه تغییرات بشویم!

حال برای تبدیل فورمت دیتاها به فورمت کتابخانه ی کرا س باید یک سری پیش پردازش انجام بدهیم:

x_train و x_test به فرمت لیست ساده است به همین دلیل ما ان ها را به کمک np.array به  فرمت  آرایه‌های نامپای یا ndarray  تبدیل کردیم و  y_train و y_test نیزبه فرمت لیست ساده هستند که ما باتابع keras.utils.to_categorical به شکل  یک وکتور در نظر میگیریم  که درهرخانه اش یک برچسپ 10تایی است که بسته به مقدار  y_train و y_test ان لیبل یک وبقیه خانه ها صفر هستند به اصطلاح   one-hot-encoding می گویند.

با فراخوانی تابع ساده ای که قبلاتعریف کردیم میتوانیم ابعاد، نوع داده ای و اطلاعات دیتاست لود شده  قبل وبعد از processرا چاپ کنیم

میبینیم که [y_train [0پیش از پردازش مقدار 6را داشته وبعداز پردازش به یک وکتور که برجسپ خانه ی 6 ام ان یک است تبدیل شده است.

 

آخرین گام پیش‌پردازش تبدیل داده‌ها به float32 و چون دیتا ها بین مقادیر 0تا255هستند با تقسیم x_train و x_testمقادیر را به مقدار بین 0 و  1نرمال سازی  میکنیم.

تعریف معماری مدل (model architecture)

در شبکه عصبی معماری شبکه قبل از انجام هرکاری اهمیت بالایی دارد پس ابتدا ان را به صورت بالا پیاده سازی میکنیم.

خط اول کد : نوع modelخود را ()Sequential  قرار میدهیم چون میخواهیم شبکه های عصبی مان به ترتیب پشت هم قرار بگیرند و غیر بازگشتی باشند(یعنی امکان بازگشت ازیک لایه نورون جلوتر به لایه نورون پیشین نباشد).

خط دوم کد:حال به  modelتعریف شده یک لایه با تابع add  اضافه میکنیم چون لایه اول را میخواهیم تعریف کنیم باید تعدادنورون ورودی وخروجی را مشخص کنیم.تابع داخلی که Denseهست میگوید این لایه هارا به هم بچسبان و64 که پارامتر اول تابع است  تعداد نورون های خروجی رامشخص میکند پارامتر دوم رادر یادداشت های قبلی توضیح داده شده است و  activation=’relu’قراردادیم و درنهایت  input_dim نیز تعداد نورون های ورودی رامشخص میکند.

خط سوم کد:لایه دیگری تعریف کردیم که به لایه قبلی چسبیده وتعدادنورون های خروجی 10است وبرای نرمال سازی خروجی activation=’softmax’قراردادیم وشبکه عصبی را با سه لایه جمع  کردیم.

Compile model

بعداز مشخص کردن معماری شبکه عصبی مان با دستورmodel.compileمدل ساخنه شده را کمپایل میکنیم این تابه از سه پارامتر تعیین شده که:

‘ loss= ‘ categorical_crossentropy:تابع هزینه ومعیار بد بودن شبکه را تعیین میکندو بهترین loss را انتخاب کردیم.

optimizer=’rmsprop’برای بهینه کردن تابع loss از optimizerاستفاده میکنیم.

metrics=[‘accuracy’]گزارشی که میدهیم را برمبنای accuracyقرارمیدهیم(قبلا metricرا دریادداشت های قبلی دوستان توضیح داده اند

 

 

 

 

تطبیق و بازشناسی چهره(2)

رویکرد دیگر در سال 2014 به این صورت بود که تشخیص چهره را به صورت کلاس بندی باینری ببینیم اینگونه که دو عکس مورد بررسی را به شبکه بده و در انتها لایه 128 را وصل کن به یک binary classifier که اگه دو نفر یکسان بودند true و در غیر این صورت،  false برمیگرداند.

دیتا ست در این رویکرد به صورت زیر است که یه مجموعه مقایسه ایست که یکسان بودن و نبودن را بیان می کنند و batch هم ظریب 2 می شود.

باز میبینیم که تعدادحالت های ما بسیار زیاد می شود.

Center loss

برای تصویر تنها تفکیک پذیر(separable) بودن مهم نیست بلکه باید یک فاصله ایی هم در فضا از هم داشته باشند.( discriminative باشند)

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

separable
separable
discriminative
discriminative

 

 

 

کانال عکس ابتدا وارد می شود.

 

یک شبکه را لود کردیم با پارامتر های تعداد کانال و سایز عکس ها که 96 * 96 است.

 

در کامپایل پارامتر loss را تابعی که خودمان برای loss triplet نوشتیه ایم میگذاریم.

وزن های قبلا train شده را در شبکه خودمون لود میکنیم.

عکس را داده و خروجی 128 تایی لایه آخر شبکه را در یک دیکشنری ذخیره میکنیم.

تابعی که عکس را گرفته و فاصله اقلیدسی آن را با عکس های موجود در دیتاست محاسبه کرده (threshold که براساس تست یافته ایم، cross validtion باید بزنیم تا بهترین کارایی برسیم.)و می گوید این عکس داده شده همان لیبل هست یا نه. true و false برگردان.

پارامتر ها:

  • عکس
  • لیبل عکس
  • دیتاست
  • مدل شبکه

تابعی که عکس را گرفته و recognation انجام می دهد، به این صورت که encoding عکس را از مدل گرفته و در تمام دیتاست موجود چک می شود اگر فاصله اقلیدسی آن از min_dist کوچکتر باشد نام آن را بر می گرداند.

 

تشخیص چهره کلاسیک و جدید(deeplearning)

Face verification: همانطور که قبلا توضیح داده شد این الگوریتم می گوید این دو نفر یکی هستند یا خیر.

Face identification: این الگوریتم می گوید این دو نفر یکی هستند.

مراحل شناختی برای face identification : (برای مشاهده گیف مربوطه به http://www.iamwire.com/2017/03/modern-face-recognition-deep-learning/149697 مراجعه شود.)

  1. در ابتدا باید face تشخیص داده شود و سپس آن را crop می کنیم.
  2. در این مرحله alignment روی face انجام می شود.
  3. Embedding تصویر alignment شده مرحله قبل را درمی آوریم.
  4. مقایسه برای شناخت شخص

طبق گفته های Andrew NG برای face detection  باید حتما مراحل detection و crop چهره را انجام بدهیم تا performance خوبی داشته باشیم.

Alignment: در مقاله 2014 گروه آکسفورد برای انجام alignment یک پروسس بسیار پیچیده انجام می دادند که در این پروسس از تصویر داده شده یک مدل سه بعدی در می آورد و سپس این مدل سه بعدی را frontal می کرد و به انجام همه این عملیات alignment می گفت. اما در مقالات بعدی از alignment های ساده تری استفاده شد؛ برای مثال facenet تنها چهره را کراپ می کرد و آن را وسط صفحه می انداخت. اما با توجه به تجارب بدست آمده، مشخص شده که پروسس های پیچیده برای alignment  نه تنها performance را بهتر نمی کند بله گاهی وقتا بدتر هم می کند.

در ادامه می خواهیم بررسی کنیم که چطور می توانface  را detect کرد. در ابتدا یک روش کلاسیک را بررسی خواهیم کرد.

روش HAAR Cascade : در بسیاری از device هایی که face  را detect می کند و عکس می گیرد از این روش استفاده می شود که روشی بسیار سریع است و برای آن از opencv  کلاسیک استفاده شده است.

در این روش یک سری feature استخراج می شود که می توانند Binary Classification انجام دهند. درنهایت به وسیله نتایج همه آن ها detection انجام می شود.

در واقع با HARR Cascade مثلا می توان دریافت که این تصویر چشم هست یا خیر.

Haar features:

Feature های پایه در haar features شامل مواردی است که در تصویر بالا سمت راست دیده می شود. که همان طور که در عکس های سمت چپ می بینید یک لبه یا یک خط را detect می کنند. در واقع چیزی که از تصویر بالا برداشت می شود این است که اگر بخواهیم چشم را detect کنیم احتمالا feature ای که در تصویر دوم مشاهده می کنید به کار می آید و اگر بخواهیم بینی را detect کنیم (با توجه به سایه روشن های روی بینی) احتمالا feature ای که در تصویر سوم مشاهده می شود به کار می آید.

برای استفاده از این feature ها هر کدام ها را با تمام سایز های مختلف را روی عکس حرکت می دهند.

دیتاست این classification دارای دو کلاس face و nonface است و عکس را در سایز 24*24 در نظر می گیرد. در مجموع 180000 feature برای این کار generate کرده است و چون اگر بخواهد از تمام این feature ها در قسمت های مختلف تصویر استفاده کند overload محاسباتی اش زیاد می شود، از تکنیکی به نامintegral image استفاده کرده است و بسیاری از محاسبات تکراری را حذف کرده است.

یک سری ازfeature ها مربوط هستند و یک سری دیگر نامربوط؛ مثلاfeature  هایی که روی face نیفتاده باشند نامربوط هستند.

چون feature هایی که پیدا کرده بودند بسیار زیاد بود(180000)  در مقاله ای دیگر به نام adaBoost آمده اند feature های مهم تر را استخراج کرده اند که حدود 6000 تا بودند. برای این کار feature ها را بر اساس اهمیت و کارایی شان مرتب کرده اند. در ابتدا مهم ترین feature را روی عکس انداختند و اگر این feature هدف را پیدا نمی کرد بقیه feature ها بررسی نمی شدند. برای مثال اگر مهم ترین feature بینی را تشخیص می داد و بینی ای در تصویر پیدا نمی کرد، نتیجه می گرفتند چهره ای وجود ندارد. اما اگر بینی پیدا می شد وارد گام بعدی Cascade می شد. در گام بعدی تعداد feature هایی که باید بررسی شوند بیشتر می شود.

مراحل استفاده بعد از training:

  1. لود یک classifier
  2. یک عکس لود کرده و به این classifier می دهیم.
  3. اگر چهره ای تشخیص داده شد موقعیت چهره و طول و عرض آن را پیدا میکند.
  4. مستطیل را برای آن موقعیت رسم می کند

برای پیدا کردن HaarCascade ها کافیست HaarCascade opencv را سرچ کرده و به گیت هاب opencv بروید (https://github.com/opencv/opencv/tree/master/data/haarcascades ) در آن جا یک سری xml وجود دارد که انواع مختلف HaarCascade ها برای عملیات گوناگون در آن وجود دارد. با دانلود هرکدام می توان از آن در پروژه استفاده کرد.

در این درس از HaarCascade_frontalface و HaarCascade_eye استفاده شده است و در کنار کد این فایل های را قرار می دهیم.

از cv2.CascadeClassifier برای لود classifier دانلود شده استفاده می شود. در واقع در این قسمت می گوید که classifier بر اساس چه ویژگی هایی ساخته شود. در این مثال که frontalface به آن پاس داده شده است classifier چهره ساخته شده است که اسمش را face_classifier گذاشته ایم.

از RGB2Gray بر روی عکس استفاده می کنیم و عکس را grayscale می کنیم زیرا opencv بیشتر از توابعی استفاده می کند که روی تصاویر grayscale کار می کنند.

در این قسمت از تابع detectMultiScale استفاده شده است؛ چون می خواهیم با scale های مختلف detect کنیم. برای این کار opencv عکس را چند بار resize می کند تا بتواند چهره را تشخیص بدهد و بعد از detect شدن نسبت این عکس به عکس اصلی را پیدا می کند تا موقعیت دقیق چهره را بگوید. در واقع این تابع با یک فاکتوری pyramid درست می کند.

Faces لیستی از لیست هاست که درواقع x, y, w, h چهره های detect شده را در خود دارد.

Scale factor: دومین پارامتر تابع detectMultiScale است که می گوید با چه فاکتوری عکس را resize کند؛ به عنوان مثال وقتی این پارامتر را برابر 1.3 قرار می دهیم یعنی هربار 30 درصد عکس بزرگ تر شود.

Min Neighbors: سومین پارامتر تابع detectMultiScale است که می گوید تا چه حد Neighbor بودن مجاز باشد که معمولا بین 3 تا 6 قرار می دهیم. اگر این مقدار خیلی پایین باشد ممکن است با این مواجه شویم که برای یک چهره دو bounding box در نظر گرفته است و اگر این مقدار خیلی بالا باشد ممکن است چهره را تشخیص ندهد.

حال می خواهیم  علاوه بر چهره، چشم را هم detect کنیم پس باید علاوه بر HaarCascade_frontalface، HaarCascade_eye  را هم لود کنیم.

برای پیدا کردن eye باید اول یک چهره detect شود و در ناحیه چهره باید به دنبال eye باشیم. پس در یک حلقه for ناحیه چهره را به دو صورت رنگی و grayscale (به جهت این که الگوریتم های classifier روی عکس های grayscale بهتر جواب می دهد) جدا می کنیم.

سپس دوباره detectMultiScale را این بار روی چهره کراپ شده صدا می زنیم تا چشم ها را detect کنیم.

سپس با ایجاد for جدید از eye های detect شده و داشتن موقعیت آن ها یک مستطیل روی آنها می کشیم، قاعدتا به ازای هر face دوبار for داخل اجرا می شود.

حال می خواهیم عملیات detect چهره و چشم را به صورت live با camscanner انجام دهیم.

الگوریتم مشابه الگوریتم های قبل عمل می کند. چهره ها را پیدا می کنیم و x,y,w,h را کمی تغییر می دهیم تا چهره به صورت کامل کراپ شود. چهره را کراپ کراپ کرده و کراپ شده را نشان می دهیم.

با توجه به نمودارهای زیر که درواقع الگوریتم هایline  face (چیزهای ساده ای که قبلا به عنوان بدیهیات در نظر گرفته می شد یعنی تقریبا همه می توانستند از ان استفاده کنند مانند haarCascade ) را نشان می دهد که vj در آن همان HaarCasscade می باشد. در این نمودارها به جای آن که نمودار performance کشیده شود، نمودار roc curve کشیده شده است که درواقع roc curve به ازای recall های مختلف persision  های مختلف را می کشد.  recall در واقع تعداد face ها از مجموع همه ی چهره ها را می گوید. (به بیان دیگز چندتا از چهره ها را توانست تشخیص دهد) و persision صحت چهره بودن برایش مهم است. (به عبارتی در persision مهم نیست چند تا از چهره ها تشخیص داده شده است این مهم است که با چه اطمینانی این چهره واقعا چهره است.)

در نمودارهای زیر درواقع هرچه سطح زیر نمودار بیشتر باشد بهتر است.

Multitask-Cascade-CNN از جمله مقاله های submit شده است که کد آن توسط خود نویسنده منتشر شده و افراد دیگر در قالب های تنسورفلویی آن را پیاده سازی کرده اند به همین دلیل ما به بررسی این الگوریتم می پردازیم.

مشکل convolutional neural network این است که اگر بخواهیم فیلتر ها را روی عکس جابه جا کنیم تا چهره را تشخیص بدهیم، تعداد حالت ها زیاد است و deep learning بسیار سنگین است. به همین خاطر ایده های زیادی استفاده شد تا این مشکل حل شود. از جمله این ایده ها این بود که به جای آن که  در تمام نقاط تصویرdetection  بزنیم تنها در جاهایی که ممکن است  چهره باشد بزنیم. می توان threshold الگوریتم Haarcasscade را پایین آورد تا تمام چهره ها را تشخیص دهد (recall را بالا ببریم و اگر precision پایین هم آمد مهم نیست) حالا این چهره های detect شده را اگر به شبکه کانوولووشنالی بدهیم معقول تر است. این ایده ها مربوط به سالهای 2014 و 2016  می باشد.

در سال 2016  تمام مراحل را deep learning کردند به این صورت که در گام اول که resize می باشد یک pyramid تشکیل می دهد. در گام بعدی از شبکه p-Net (proposal network)که یک شبکه کانوولوشنالی فوق العاده سبک است استفاده می شود که فقط نقاط احتمال چهره را در می آورد (علاوه بر چهره ممکن است چیز های نامربوط دیگر را هم درآورد).

در گام بعدی نتایج حاصله از مرحله قبل را کراپ کرده و به شبکه R-Net (Refinement Network) که در این شبکه هم مکان های bounding box ها را تنظیم کرده و هم بعضی از bounding box ها را حذف می کند.

در گام بعد این بار می خواهیم precision را بالا ببریم پس خروجی R-net را به شبکه O-Net(output Network) می دهیم و از بین آنها انتخاب می کند و landmark های آنها را هم می کشد.

Lossهای شبکه ها:

یک loss این شبکه ها crossentropy دو کلاسه هست  که مسئله باینری face-nonface را پوشش می دهد:

Loss box:

Loss box ها که یک مسئله regression است، در واقع فاصله تخمین تا حقیقت را محاسبه می کند که آیا مکان bounding box درست است یا خیر:

Loss landmarks: که باز هم مسئله regression است:

Loss کل شبکه که ترکیبی از هر سه loss می باشد.

درون کد اگر بخواهیم بررسی کنیم (mtcnn-test.py)

مقدار اول hyper parameter شبکه اول(p-net)

مقدار دوم hyper parameter شبکه دوم(R-net)

مقدار سوم hyper parameter شبکه سوم(O-net)

توسط detect_face.create_mtcnn سه شبکه pnet و rnet و onet را می سازیم.

یک clone از عکس های موجود در image_path می گیریم.

متد detect_face از detect_face را صدا میزنیم تا bounding box  و landmark ها را به عنوان خروجی بدهند.

که درواقع bounding box لیستی از چهارتایی های x,y,w,h و points لیستی از x,y های 5 تا  landmark داخل هر چهره است.

یادداشت های کلاسی جلسه 18

  • مغز انسان سلسله مراتبی است.
  • هدف افراد که بر روی cognitive مطالعه می کنند بالا رفتن توان پیشگویی مغز است ، لذا این افراد به این نتیجه رسیدند که اگر صرفا بر روی افزایش کارایی مدل کار کنند (با بهبود شبکه ی کانولوشنی) توانایی پیشگویی نرون های مغز نیز افزایش می یابد ،یعنی کارایی و توانایی پیشگویی نرون ها دارای correlation هستند.

 

  • مدل alexnet مشابه لایه IT مغز میمون عمل میکند(کنار هم قرار دادن object های مشابه)  پس می توان از این مدل برای تحقیقات پردازش تصویر استفاده کرد

 

  • رویکرد مغز به گونه ای است که تبدیل تصویر انجام می دهد و تصاویر را به یک فضای نرونی دیگر انتقال می دهد
  • فضای نرونی مناسب ،به گونه ای است که با یک classifier ساده (خط،صفحه،….) قابل تفکیک باشد.

 

 

                                                                                                                      

Transfer learning : برای استفاده از یک شبکه ی کانولوشنالی لزوما به داده های زیاد احتیاج نداریم .می توان از نتایج مدلی دیگر استفاده کرد

  • لایه های ابتدایی یک مدل ، ویژگی های عمومی را تشخیص می دهند(خط

،لبه،…) پس می توانیم از این لایه ها در شبکه ی مورد نظر خود استفاده کنیم اما لایه آخر classifier است پس باید مطابق نیاز آن را تغییر دهیم

  • Freeze : با فریز کردن ، لایه ها در فرایندtraining شرکت نخواهند کرد

 

  • *****بسته به شباهت مسأله حل شده به مسأله مورد نظر و همچنین تعداد داده های موجود ، تعداد لایه های Freeze و training تعیین می کنیم.

 

  • یکی از راه های استفاده از شبکه های کانولوشنالی حذف همه ی لایه های fully_conected است . در این صورت از شبکه به عنوان یک Feature

Extractor استفاده می شود

 

  • اگر لایه های C یک شبکه را حذف کنیم می توانیم سایز عکس ها را به دلخواه تعیین کنیم(لزوما نباید سایزی که شبکه قبلا با آن آموزش دیده باشد)

 

  • شبکه های C برای مسایل خاص استفاده می شوند و نمی توانند تشخیص دهند که object کجای تصویر قرار دارد

 

 

یادداشت های کلاسی جلسه 17

Data augmentation

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

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

استفاده از ImageDataGenerator

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

به همین خاطر با هربار اجرا، پاسخ جدیدی خواهد داد که ترکیبی رندوم از این هاست.

توضیح آپشن ها:

rotation_range عددی بین 0و180 درجه که حداکثر میزان چرخاندن را نشان میدهد

width_shift & height_shift حداکثر جابجا شدن و شیفت شدن افقی و عمودی

shear_rangeبا شکل توضیح بدهم بهتره، این:

zoom_range حداکثر میزان داخل تصویر زوم کردن(به نوعی همان crop کردن

horizontal_flip اگر true باشد می تواند تصویر را آینه(قرینه افقی)  کند.دقت کنید “میتواند” یعنی ممکن هم هست که نکند.

fill_mode شیوه پر کردن پیکسل های تازه ایجاد شده

کدها برگرفته از فصل دو کتاب Deep Learning with Python و گیت هاب نویسنده کتاب و توسعه دهنده کراس François Chollet است.

تطبیق و بازشناسی چهره (1)

جلسه بیستم – Face

برای شروع این مبحث ابتدا لازم تا با مفاهیم Face Verification و Face Recognition آشنا شویم. در مسائل Face Verification ما با دو تصویر سر و کار داریم و باید شبکه ای داشته باشیم که بتواند تشخیص بدهد آیا این عکس ها متعلق به دو فرد مختلف هستند یا خیر. یعنی مسائل Face Verification نوعی از مسائل binary هستند. اما در مسائل Face Recognition دیتابیسی شامل تصاویری از افراد متفاوت داریم و مدل باید تشخیص دهد که عکس ورودی جدید متعلق به کدام یک از این افراد است. هر مساله Face Verification را می توان به n مساله Face Recognition شکست؛ به این صورت که عکس جدید را با تصویر هر کدام از افراد موجود در دیتابیس بررسی کنیم و ببینیم که آیا این دو تصویر متعلق به یک فرد هستند یا خیر.

مفهوم دیگری که در ابتدا لازم است با آن آشنا شویم One Shot Learning است. اگر می خواستیم مساله Face Recognition را با روش های قدیمی حل کنیم، باید تعداد زیادی تصویر از افراد مختلف (مثلا 20 نفر) جمع آوری کنیم و سپس شبکه ای train کنیم که لایه آخر آن یک softmax با 20 نورون باشد. اما این رویکرد در حل مسائل واقعی عملی نیست؛ چون برای اضافه کردن یک فرد جدید، نیاز است تا ساختار شبکه (لایه آخر) را تغییر دهیم و شبکه را مجددا train کنیم. هم چنین ممکن است گاهی نیاز به اضافه کردن فردی به دیتابیس داشته باشیم که تعداد زیادی عکس از او در دسترس نباشد. در این جا نیاز به One Shot Learning داریم. هدف One Shot Learning این است که تنها با یک عکس از هر گروه، بتوانیم شبکه را train کنیم.

(اخیرا مبحثی به نام Zero Shot Learning نیز مطرح شده که در آن برای اضافه کردن یک کلاس به شبکه می توان از عکس جدیدی استفاده نکرد و به جای آن کلاس جدید با توجه به کلاس های قبلی که شبکه یاد گرفته توصیف می شود. هم چنین مفهوم دیگری به نام Low Shot Learning هم مطرح است که در آن از هر کلاس تعداد کمی عکس – مثلا 2 یا 3 تصویر – داریم.)

در مبحث Feature Extraction دیدیم که شبکه های کانولوشنال می توانند از تصاویر Separable Features استخراج کنند که با یک خط از هم تفکیک شوند. اما اگر بخواهیم برای این feature ها یک classifier با KNN داشته باشیم ممکن است به نتیجه خوبی نرسیم. (در شکل زیر نزدیک ترین همسایه به نقطه قرمز درون مربع زرد، نقطه سبز است.) برای همین گاهی لازم است به Discriminative Features داریم؛ یعنی feature ها علاوه بر قابل تفکیک بودن با یک خط، باید از هم فاصله داشته باشند.

رویکرد ما در این مسائل این است که به جای یاد دادن هر فرد به مدل، یک تابع شباهت یا similarity function به مدل یاد بدهیم که به آن اصطلاحا parameter learning گفته می شود. در این نوع از learning از هر عکس یک encoding یا embedding استخراج می کنیم و سپس با تعریف معیار فاصله، سعی می کنیم تا به شرایطی برسیم که فاصله دو عکس متفاوت از دو فرد یکسان عدد کوچک و فاصله دو عکس از فرد متفاوت عدد بزرگی به ما بدهد. با شبکه هایی که تا کنون نوشته ایم هم می توانیم تا حدی به این هدف دست پیدا کنیم. به این صورت که لایه softmax را دور ریخته و فاصله لایه های قبل از آخر را با یکدیگر حساب کنیم. در این صورت احتمالا برای افراد درون training set به performance خوبی هم می رسیم؛ اما شبکه generalize نیست و برای افرادی که در training set نباشند نتیجه خوبی نخواهد داشت. (شبکه های Siamese)

پس به طور کلی در پارامتر لرنینگ هدف این است که از هر تصویر یک encoding استخراج کنیم؛ به طوری که داشته باشیم:

بنابراین نیاز است تا cost function ای پیدا کنیم که به ما برای رسیدن به این هدف کمک کند. از انواع cost function هایی که برای این منظور طراحی شده Triplet loss است که در سال ۲۰۱۵ و توسط گوگل معرفی شد. برای استفاده از این cost function لازم است تا batch size مضربی از ۳ باشد. سه عکسی که به شبکه داده می شوند Anchor، Positive (عکس دیگری از Anchor) و Negative (عکسی از فرد دیگری) نام دارند و می خواهیم داشته باشیم:

این فرمول یک ایراد دارد و آن این است که اگر f مستقل از ورودی رفتار کند و به ازای هر ورودی دقیقا یک خروجی یکسان بدهد (مثلا 0) این شرایط همیشه برقرار است. برای حل این مشکل و همچنین برای رسیدن به Discriminative Features به فرمول فوق margin اضافه می کنیم. در نتیجه با این فرمول فاصله دو فرد متفاوت حداقل باید به اندازه آلفا باشد.

اما از این نامساوی نمی توان برای محاسبه loss function استفاده کرد. برای این که این عبارت را به یک فرمول تبدیل کنیم داریم:

با توجه به این فرمول، اگر cost function برابر 0 باشد، به هدف رسیده ایم. اما اگر cost function بزرگ تر از صفر باشد لازم است تلاش کنیم تا آن را کوچک تر کنیم. (بهینه سازی)

نکته قابل تامل این است که این روش نیاز به تعداد تصاویر زیادی دارد؛ درنتیجه تعداد مجموعه عکس های سه تایی ای که می توانیم انتخاب کنیم خیلی زیاد است. اما برای درصد بالایی از آن ها loss function در همان ابتدا یا پس از اولین epoch صفر است. طی کردن کل پروسه train برای تصاویر با cost function برابر 0 هیچ تاثیری در وزن های شبکه ندارد و تنها زمان بر است. پس لازم است گزینه های چالشی تر برای train انتخاب شوند. استفاده از عکس های دوقلوها، گریم های سنگین و … می توانند باعث بهبود عملکرد شبکه شوند.

Transfer learning

ما برای کانولوشن ها (CNN) نیاز به میلیون ها دیتا داریم. البته براساس Transfer learning
ما می توانیم از مدل آموزش دیده ی شخص دیگری که مدلش را بر روی دیتاهای بسیار آموزش داده است استفاده کنیم به طوری که نیازی نباشد تا برای آموزش شبکه کانولوشن خودمان ملیون ها دیتا را بررسی و تحلیل کنیم. به عنوان مثال در تصویر زیر برای تشخیص گربه ایرانی از گربه ی خیابانی و یا هرچیز دیگری:

اگر یکی از مدل های آموزش دیده شده ایمیجنت را به صورت بالا انتخاب کنیم. این مدل لایه ایی قابلیت تشخیص اجزای مختلفی از اشیاء مختلفی را دارد به صورتی که هر لایه برای تشخیص جزئی از شی آموزش داده شده است و لایه آخر هم یک کلاسیفایر است که میتوانیم در کاربردهای مختلف آنرا حذف کنیم و یک softmax جدید بجای آن قرار دهیم. که در اینجا ما برای تشخیص گربه ایرانی از گربه ی خیابانی و یا هرچیزی غیر از گربه می توانیم لای آخر را حذف کنیم و یک softmax جدید سه کلاسه (برای تشخیص گربه ایرانی، خیابانی و هرچیز دیگری) بجای آن قرار دهیم.
و یا به صورت زیر:

در این حالت به جای اینکه به این فکر کنم که چه مشخصه هایی از تصویری که به مدل داده ام را استخراج کنم، عکس را به مدل آموزش دیده ی یک شخص دیگری می دهیم بعد مشخصه های لایه های ماقبل آخر را از مدل میگیرم به عنوان مثال لایه ماقبل آخر Alexnet ، 4096 تا است که به عنوان مشخصه های تصویر از مدل Alexnet میگیریم.
حال در مدل freeze شده لایه های سمت چپ لبه ها را تشخیص می دهند و هرچه از سمت چپ به سمت راست حرکت میکنیم لایه های مشهودتری مثل گوش گربه را به خوبی تشخیص می دهد.
اگر با مسئله جدیدی برخوردیم مثلا دو آبجکت را در نظر بگیریم که در دیتاست ما، دیتاهای کمی از آنها وجود دارد. برای بهینه تر کردن مدل ما به صورت زیر:

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

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

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

از کراس مدل ذخیره شده مان را لود میکنیم البته قبل از این باید با دستور pipe h5 py را نصب کنیم. بعد از این باید یک سری پرپروسسینگ به صورت زیر روی تصویر انجام بدهیم. کتابخانه های مورد نیاز را ایمپورت میکنیم:

نکته : عبارت %matplotlib inline یک کلمه ی کلیدی در jupyter notebook است(یعنی در محیط برنامه نویسی پایتون نمی توان از آن استفاده کرد) که اگر از نوشتن آن صرف نظر کنیم تا ۹۰ درصد امکان عدم نمایش خروجی در نوتبوک را دارد لذا بهتر است از آن استفاده کنیم.
در ادامه تصویر مورد نظر را وارد میکنیم تصویر را از testset ایمپورت میکنیم testset جایی است که در فرآیند training شرکت نداشته است.

پارامتر target_size را به اندازه شبکه ایی که قبلا تعریف کرده یم قرار میدهیم که در اینجا چون اندازه شبکه را قبلا ۱۵۰ در ۱۵۰ تعریف کرده ایم لذا از همین اندازه استفاده میکنیم.
بعد از نمایش تصویر آنرا بر ۲۵۵ تقسیم میکنیم تا نرمال شود.
بعد از اجرا خروجی به صورت زیر خواهد بود:

که مقدار model.predict و model.predict_classes در بالای تصویر هست. که مقدار model.predict_classes خروجی sigmoid در شبکه کانوشوال است.
نکته: خروجی Sigmid مقداری بین صفر و یک را برمیگرداند که هرچه به صفر نزدیکتر باشد با احتمال قوی تری می گوید که تصویر گربه است و هرچه به یک نزدیک باشد بلعکس خواهد بود و اگر مدل نتواند تصوری را تشخیص دهد مقداری در حدود نیم خواهد داد.

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

و فضای نورونی جدیدی را به صورت زیر داریم:

در بخش اول کد با include_top=false همه ی fully connectedها را دور میریزم. با input_shape=(150, 150, 3) ابعاد عکس را تعیین میکنیم که به ترتیب طول و عرض و convolutionاست . در این جا وزن ها را روی چالش ‘imagenet’ تنظیم کردیم .

conv_base.summary():(VGG)summary هست ولی با (150, 150, 3) تنظیم شده است و با pollingهم به اتمام رسیده است. در توضیح Non-trainable هم وقتی freeze نکرده باشیم قاعدتا Non-trainable هم نداریم . بیشتر بودن وزن include_top نیز به خاطر fully connected میباشد.

base_dirمسیری هست که دیتای تمیز شده در آن موجود میباشد. extract_features هم عکس ها را Fitمیکند به شبکه وبعد featureها را برمیدارد و در numpy arrayذخیره میکند . featuresخود به این معنی است که تعدادی عکس با این dimensional میخواهیم و موقتا با صفر پرشده است . در generatorچون بحث در کلاس است به صورت binaryمیباشد .

inputs_batch در این جا 20 تا (3* 150* 150)داریم و features_batch20تا 512*4*4است. آرایه های labelsو featuresقرار است تا ماتریس های 2000تایی رو پر بکند. Featuresدر این جا لایه آخر convolutionاست. این جا خروجی قرار است با train_features, train_labelsباشد که در train_labels خروجی 1*2000 داریم.

در قطعه کد بالا reshapeها کار floatکردن را مثل دیتاست هدی انجام میدهد.ما در این جا برای trainکردن یک classifierداریم . در این جا ayers.Dropout(0.5) برای overfitنشدن هست(به این منظور که یکسان زیاد میبینیم)که راه دیگر data augmentation هست . activation=’sigmoid’ است چون کلا در این جا دو کلاسه هستیم . ما به جای generator،model.fit داریم چون از دایرکتوری چیزی را نمیخواند . حال این سوال مطرح میشود که چرا data augmentation مفید نمیباشد؟
باید بگوییم این جا 30 تا epoch 2000 تایی داریم وبا numpy array یک بار این 2000 تا عکس را trainمیکنیم نه 30 بار! ولی در augmentation چون نمیتوانیم reuseکنیم و عکس جدید میخواهد مفید نیست!

نگاهی به فرآیند بینایی در مغز

یکی از سخت ترین کارهایی که در مغز انجام می شود فرآیند بینایی است و به همین دلیل 50 درصد از مغز به بینایی و پردازش های مربوط به آن اختصاص یافته است.
همانطور که در تصویر زیر مشخص است فرآیند بینایی در مغز به صورت سلسله مراتبی از ناحیه ی v1 شروع میشود و با گذر از نواحی v2 و v4 به ناحیه ی IT می رسد.

که در ناحیه ی IT با کار گذاشتن الکترودها و گرفتن خروجی های مختلف بر اساس دیدن اشیاء مختلف می توان به صورت تجربی تشخیص داد که فرد چه چیزی را می بینید. در واقع با بررسی خروجی های ناحیه IT میتوان چیزی که فرد در لحظه دیده است را تشخیص داد. به عنوان مثال می توان فردی را که در حال خواب دیدن است زیر آزمایش قرار داد و با گرفتن خروجی های این ناحیه خواب او را ضبط کرد و بعد از بیدار شدن خوابش را به صورت یک فیلم به او نشان داد.
چرا فرآیند بینایی در مغز به صورت سلسله مراتبی است؟
با کار گذاشتن الکترود در بخشهای مختلف مغز یک موجود می توان فهمید که بر اساس چیزی که میبیند در قسمت های مختلف مغزش یک سری اکتیویشن های مختلفی اتفاق می افتد. به عنوان مثال در قسمت v2 در 60 میلی ثانیه اکتیویشن نشان داده می شود و در قسمت IT حدودا بعد از 100 میلی ثانیه اکتیویشن نشان داده می شود. بنابراین می توان نتیجه گرفت که این اتفاق ها بر اساس یک سلسله مراتب خاص هست که نشان داده می شود:

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

فضاهای نورونی خوب و بد

اگر یک شی  به صورت زیر روی فضای نورونی n-بعدی ترسیم کنیم هرکدام از نورون ها مقداری خواهند داشت و در نتیجه یک نقطه در این فضای نورونی مشخص می‌شود:

اگر این شئ تغییراتی کند، به عنوان مثال اگر سر شخص کمی بچرخد در همان فضا موقعیت سر شخص بر اساس مقادیر مختلف هرکدام از محورهای نورونی مقداردهی می شود و اگر تمام تغییرات یک فرد را در این فضای n بعدی رسم کنیم می‌توانیم  یک حجم در این فضا را به این شئ خاص در تمام تغییراتش نسبت داد.
اکنون یک فضای نورونی خوب را به صورت زیر می‌توان ترسم کرد:

و فضای نورونی یک شخص را با یک ابرصفحه (در فضای دو بعدی با خط، در سه بعدی با صفحه و در فضای n بعدی با ابرصفحه) تفکیک کنیم و به آن بفهمانیم که اگر بالای ابرصفحه را دیدی شخص A و اگر پایین صفحه را دیدی شخص B را دیده ایی.
مسئله ایی که در اینجا مطرح میشود این است که اگر مشخصه ها را به صورت پیکسلی و درهم تنیده به صورت زیر داشته باشیم ما نمیتوانیم با استفاده از ابر صفحه فضاها را از هم تفکیک کنیم:


در اینجا مغز در قالب ساختار سلسله مراتبی قابلیت تفکیک این فضای پیکسلی را دارد یعنی به صورت زیر میتواند فضای A و B را ازهم جدا کند:

بعد از این تجزیه می توان با یک طبقه‌بند ساده A و B را تشخیص داد. بر این اساس اگر به انسان یک شی با تغییرات خاصی نشان بدهند این شی در فضایی خاصی از این فضای نورونی قرار میگیرد و اگر یک شی دیگر را نشان بدهند باز در قسمت دیگری از این فضای نورونی قرار خواهد گرفت.

معرفی تعدادی از معماری‌های شبکه های کانولوشنالی معروف

در این قسمت می خواهیم به معرفی تعدادی از شبکه های نورونی کانولوشنالی (CNN) معروف بپردازیم. این شبکه ها از آن جهت معروفند که امروزه بسیاری از افراد در مقالات یا پروژه های خود از آن ها استفاده می کنند و هم چنین در زمان معرفی شدنشان توانستند جایزه ی ImageNet که یکی از معتبر ترین جوایز در این زمینه است را برنده شوند.

ImageNet

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

۱- LeNet-5

اولین شبکه ی کانولوشنالی که بسیار مطرح شد شبکه ی LeNet-5 بود که در مقاله ی”Gradient-based learning applied to document recognition ” نوشته شده توسط LeCun, Bottou, Bengio, Haffner و در سال 1998 ارائه شد. نام شبکه نیز از نام Yann Lecun یکی از نویسندگان این مقاله برداشته شده است. این شبکه را می توان به عنوان اولین شبکه که فیلتر های کانولوشنالی در آن استفاده شده است نام برد. هدف این شبکه، خواندن کد پستی از پشت بسته های پستی بود.

شکل بالا شبکه ی Lenet را نمایش می دهد. این شبکه در ابتدا یک ورودی 32*32 دریافت می کند و سپس از 6 فیلتر کانولوشنالی 5*5 که گام(stride) آن برابر 1 است عبور می کند. حاصل یک تنسر 6*28*28 است. سپس از فیلتر subsampling که در این جا فیلتر AveragePool 2*2 با گام 2 است عبور می کند. این فیلتر موجب می شود که طول و عرض آرایه نصف شود اما عمق آن تغییری نمی کند در نتیجه به آرایه ی 6*14*14 می رسیم. این بار از 16 فیلتر کانولوشنالی 5*5 با گام 1 عبور می دهیم که حاصل 16*10*10 است. دوباره از یک AveragePool مانند قبل عبور می دهیم که حاصل 16*5*5 میشود. و در انتها نیز از دو لایه ی Fully connected عبور داده می شوند.

۲- AlexNet

دومین شبکه ی نورونی کانولوشنالی مهمی که می توان نام برد شبکه ی AlexNet است که توسط Alex Krizhevsky و حدود چهارده سال بعد از LeNet یعنی در سال 2012 معرفی شد. این شبکه دارای 8 لایه (پنج لایه ی کانولوشنالی و سه لایه fully connected) است که موجب شده در دسته ی شبکه های کم عمق (Shallow) قرار گیرد.

شکل بالا شبکه ی AlexNet را نمایش می دهد.(دلیل این که لایه ها دوطبقه ای هستند، استفادهاز دو GPU برای پردازش آن است) درشکل ورودی شبکه یک عکس 3*224*224 است اما ورودی درست 3*227*227 است! در ابتدا 96 فیلتر کانولوشنالی 11*11 همراه با 4 گام و padding=0 اعمال می شود. خروجی آرایه ی 96*55*55 است.(تعداد پارامتر های هر لایه ی کانولوشنالی برابر است با : طول لایه * عرض لایه * عمق ورودی * تعداد فیلتر ها (به طور مثال در اینجا برابر است با 11*11*3*96))در مرحله ی بعد از لایه ی maxpool 3*3 با اندازه ی گام 2 عبور داده می شود که خروجی 96*27*27 می شود.(تعداد پارامتر های قابل یادگیری در maxpool صفراست.) در مرحله بعد از 256 فیلتر کانولوشنالی 5*5 با گام یک و padding=2 عبور می دهیم که خروجی 256*27*27 است. در مرحله ی بعد نیز دوباره از فیلتر maxpool 3*3 با گام 2 عبور می دهیم که خروجی 13*13*96 است. در سه مرحله ی بعد از فیلتر های کانولوشنالی با گام و padding یک استفاده می کنیم که تعداد آن ها به ترتیب 384 ، 384 ، 256 است که خروجی نهایتا 256*13*13 می شود. سپس از یک لایه ی maxpool 3*3 با گام یک عبور می دهیم و خروجی آن 256*6*6 می شود. در آخر نیز سه لایه ی fullyconected قرار دارد. دو لایه 4096 تایی و یک لایه 1000 تایی با اکتیویشن softmax برای تعیین کلاس های موجود در مساله. (به طور مثال اگر قصد انتخاب بین سه کلاس سگ، گربه، موش را داشته باشیم اندازه لایه ی آخر را سه در نظر می گیریم.)

ورودی

نوع فیلتر

تعداد

اندازه

گام

حاشیه

خروجی

3*227*227

Conv

96

11*11

4

0

96*55*55

96*55*55

maxpool

1

3*3

2

96*27*27

96*27*27

conv

256

5*5

1

2

256*27*27

256*27*27

Maxpool

1

3*3

2

256*13*13

256*13*13

Conv

384

3*3

1

1

384*13*13

384*13*13

Conv

384

3*3

1

1

384*13*13

384*13*13

Conv

256

3*3

1

1

256*13*13

256*13*13

Maxpool

1

3*3

2

256*6*6

9216

Fullyconected

4096

4096

Fullyconected

4096

4096

Fullyconected

1000

نکات مهم :

• تابع relu برای اولین بار معرفی و استفاده شد.
• بعد از دو لایه ی maxpool اول از نرمال ساز استفاده شده بود که دیگر مورد استفاده قرار نمی‌گیرد.
• برای اولین بار از dropout استفاده شده.
• اندازه ی batch در آن 128 است.
• میزان خطای آن در مسابقه ی imagenet برای خطای 5 کلاس برتر ، مقدار 15.4% بود که حدود سه درصد نسبت به سال گذشته بهبود داشت.

۳- ZFNet

نویسنده های این شبکه، Matthew Zeiler و Rob Fergus بودند که نام شبکه نیز از آن ها گرفته شده.این شبکه از ایده زیادی برخوردار نیست و مهم ترین ایده آن ، قسمت Visualization آن است. ابزاری که با استفاده از آن، کاربرد هر نورون در شبکه تا حدی مشخص می‌شود و به درک شبکه های کانولوشنالی کمک بزرگی کرد. در این ابزار می‌توان دید که در لایه های نخست، شبکه خطوط و لبه های ساده را تشخیص می‌دهد و در لایه های بعد نورون ها مفاهیم پیچیده تری مانند صورت انسان یا نوشته را تشخیص می‌دهند. بعضی از نورون ها برای ما قابل فهم نیستند. ولی معلوم شده حذف آن ها هم تاثیری مانند حذف دیگر نورون ها در عملکرد نهایی شبکه دارد.
این شبکه همان شبکه AlexNet است با این تفاوت که در لایه اول، به جای (11*11 stride4)، از (7*7 stride2) استفاده شده است(چون سایز فیلتر در AlexNet بزرگ گرفته شده بود و stride آن زیاد بود.) و در لایه های 3، 4 و 5 به ترتیب به جای 384 ، 384 و 256 فیلتر، از 1024، 512 و512 فیلتر استفاده شده است.

نکات مهم:

• ZFNet، در مسابقه ImageNet خطای ۵ کلاس برتر را به 14.8% کاهش داد و همین باعث شد تا برنده Challenge ImageNet سال 2013 شود.
• ارائه ابزار Visualization

۴- VGG

این شبکه، به دلیل این که تعداد HyperParameter ها را کاهش داده، پیچیدگی کمتری نسبت به AlexNet و ZFNet دارد و به دلیل همین سادگی، از محبوبیت بالایی برخوردار است.
در VGG در هر جا:
CONV به معنی فیلتر 3*3 با stride 3 و same است.
و POOL به معنی پولینگ 2*2، با stride 2 است.
سایز تصویر ورودی 3*224*224 است. سپس دو بار CONV با عمق 64 روی آن اعمال می شود.(با CONV اول، تصویر 64*224*224 می شود و با CONV دوم دوباره 64*224*224 می شود.) سپس POOL روی آن اعمال می شود وتصویر 64*112*112 می شود.(پولینگ روی عمق تاثیر نمی گذارد.) بقیه مراحل در شکل زیر قابل مشاهده هستند:

در مقاله VGG، که در سال 2015 ارائه شد، چند مدل مختلف تست شده اند و مدلی دارای 16 لایه تحت عنوان VGG-16 بیش ترین کارایی را داشته است.

نکات مهم:

• در این معماری، به ازای هر تصویر، 93MB حافظه اشغال می شود.
• 138 میلیون پارامتر قابل یادگیری دارد.
• در سال 2014، خطای ۵ کلاس برتر مسابقه ImageNet را به 7.3% بهبود بخشیده است. با این حال این شبکه برنده نشد.

۵- GoogLeNet (Inception)

این شبکه توسط Google در سال 2014 ارائه شد. نام آن ادای احترامی به Yann Lecun، سازنده LeNet، اولین شبکه کانولوشنالی، است. این شبکه با ایده عمیق تر کردن شبکه های کانولوشنالی که طبق گفته سازنده، برگرفته از دیالوگی در فیلم Inception است! برای همین به این نام نیز شناخته می‌شود.

در این شبکه با این رویکرد که هایپر پارامتر های شبکه را هم به گونه ای به پارامتر قابل یادگیری تبدیل کنند، ماژولی به نام Inception module طراحی شد.

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


در این شبکه با قرار دادن دو لایه ی پولینگ در ابتدای کار، پارامتر های قابل یادگیری مساله را بسیار کاهش داده اند. در ادامه از ۹ لایه یInception module استفاده شده. جزئیات بیشتر در تصویر زیر مشخص است.
در تصویر بالا بلاک های آبی نشان دهنده لایه کانولوشنالی، قرمز نشان دهنده پولینگ، زرد سافت مکس و سبز کنار هم گذاشتن خروجی های قبلی است.

نکات مهم:

• معرفی ایده جدید Inception module
• داشتن تنها ۵ میلیون پارامتر قابل یادگیری. این تعداد نسبت به شبکه های AlexNet و VGG به ترتیب ۱۲ و ۳۶ برابر کمتر است.
• این شبکه در سال2014 با کاهش میزان خطای ۵ کلاس برتر در مسابقه ImageNet به 6.7% برنده شد.

۶- Microsoft ResNet

این شبکه توسط Microsoft ارائه شد که نام آن مخفف Residual Network است. در این شبکه ارتباطاتی خارج از ساختار کانولوشنالی در کنار آن بین لایه ها در نظر گرفته شده تا ورودی های لایه قبلی را بدون واسطه به لایه بعدی منتقل کند و در مرحله back propagation یا اصلاح شبکه، ارور هر لایه را به لایه قبلی انتقال دهد تا بتوان شبکه را عمیق تر کرد و آن را سریع تر آموزش داد. به این ارتباطات skip connections و به ساختار حاصل از آن Residual block می‌گویند.

با این ترفند توانستند شبکه ای با عمق ۱۵۲ لایه را آموزش دهند که اختلاف زیادی با شبکه های قبلی داشت.

نکات مهم:

• معرفی مفهوم جدید skip connections و residual block.
• عمیق کردن قابل توجه شبکه.
• این شبکه در سال 2015 در مسابقه ImageNet میزان خطای ۵ کلاس برتر را به 3.6% کاهش داد.

خلاصه

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

برای مطالعه بیشتر

LeNet

AlexNet

ZF Net

VGG Net

GoogLeNet

Microsoft ResNet

منابع

ImageNet

CNNs Architectures: LeNet, AlexNet, VGG, GoogLeNet, ResNet and more …

We Need to Go Deeper: A Practical Guide to Tensorflow and Inception

An Overview of ResNet and its Variants

آموزش یک شبکه عصبی کانولوشنالی از ابتدا در Kears

مجموعه داده

مجموعه داده گربه در مقابل سگ برای این مثال استفاده شده است. این مجموعه داده در چالش بینایی کامپیوتر اواخر سال ۲۰۱۳ توسط سایت Kaggle.com در دسترس عموم قرار گرفت. مجموعه داده اصلی دارای ۲۵۰۰۰ تصویر (۱۲۵۰۰ از هر کلاس) است که می‌توانید آن را از اینجا دریافت کنید.

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

برای بررسی صحت انجام کار، تعداد تصاویر آموزشی، ارزیابی و آزمون را بررسی میکنیم.

تعریف معماری مدل (model architecture)

ما از یک مدل کانولوشنالی برای حل این مساله استفاده می‌کنیم. از قبل از سال ۲۰۱۳ استفاده از شبکه های کانولوشنالی خیلی رایج نبود ولی بعد از آن تقریبا در همه مدل های بینایی ماشین با روش یادگیری عمیق، از این شبکه ها استفاده می‌شود.شبکه ما از ۴ لایه ی کانولوشنالی و پولینگ بعد از هر کدام، یک لایه متراکم (Dense) پنهان و یک لایه متراکم برای لایه خروجی که دارای یک نورون است استفاده می‌کنیم.تابع فعال سازی لایه آخر sigmoid است. در پیاده سازی مدل برای تشخیص اعداد دست نویس دیتاست هدی، ما در لایه آخر از تابع softmax استفاده کردیم. با تابع softmax خروجی نورون های لایه آخر به صورتی می‌شود که مقدار هر کدام عددی بین ۰ و ۱ است و مجموع همه برابر یک خواهد بود. این تابع برای لایه آخر مسائل طبقه بندی به کار می‌رود.در این مسال مابه جای استفاده از دو نورون با تابع softmax از یک نورون با تابع sigmoid استفاده می‌کنیم. این تابع عددی بین ۰ و ۱ برمی‌گرداند. چون تنها دو کلاس داریم، مقدار یکی از نورون ها برابر اختلاف دیگری با عدد ۱ است. پس می‌توانیم عدد ۰ را متناظر با یکی از کلاس ها (مثلا گربه)‌ و عدد ۱ را متناظر با کلاس دیگر (سگ) قرار دهیم. در این صورت به جای دو نورون در لایه خروجی، با یک نورون همان کار را انجام می‌دهیم.

نگاهی به ابعاد و تعداد اطلاعات در هر یک از لایه های شبکه می‌اندازیم.نگاهی به ابعاد و تعداد اطلاعات در هر یک از لایه های شبکه می‌اندازیم.

چون این مساله تنها دو کلاس داریم، از تابع binary_crossentropy برای محاسبه میزان خطا استفاده می‌کنیم. با توجه به اینکه تعداد تصاویر یکسانی از سگ و گربه برداشته ایم معیار Accuracy معیارمناسبی برای ارزیابی خواهد بود.

پیش پردازش داده (Data preprocessing)

مراحل آماده سازی تصاویر برای شروع عملیات یادگیری:

  1. خواندن تصویر
  2. تبدیل فرمت jpeg به پیکسل های RGB
  3. تبدیل آن به tensor (آرایه چند بعدی) از اعداد حقیقی
  4. نرمال کردن اعداد (تبدیل بازه ۰ تا ۲۵۵ به بازه ۰ تا ۱)

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

اطلاعات بیشتر در مستندات Keras :

https://keras.io/preprocessing/image/

اگر بخواهیم نگاهی به خروجی کلاس های generator بیاندازیم خواهیم دید در هر گام پیمایش، آن ها یک دسته(batch) از تصاویر رنگی ۱۵۰ در ۱۵۰ پیکسل (3, 150, 150, 20) و به تعداد تصاویر، عنوان آن ها را (۰ برای گربه و ۱ برای سگ) برمی‌گرداند. با ادامه پیمایش این روند به تعداد نامحدود تکرار می‌شود.

 

آموزش مدل (fitting model)

حالا نوبت آموزش مدل می‌شود. برای این کار به جای تابع fit از تابع fit_generator استفاده می‌کنیم که همان  کار را انجام می‌دهد ولی با generator ها کار می‌کند. این تابع برای اولی ورودی یک generator مانند آنچه  ساختیم می‌گیرد و با آن مدل را تغذیه می‌کند. چون generator ها بدون اطلاع از تعداد تصاویر، مدام  خروجی ها را برمی‌گردانند، باید به گونه ای تعداد گام های پیمایش را به ازای هر دوره(epoch) مشخص کنیم. پس علاوه بر generator باید مقدار ورودی steps_per_epoch را هم به تابع بدهیم. چون تعداد تصاویر ۲۰۰۰ تا و اندازه هر تکه ۲۰ است، ما برای هر دوره به ۱۰۰۰ گام برای پیمایش نیاز داریم.

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

حالا نمودار میزان خطا و میزان دقت را در طول آموزش رسم می‌کنیم.

این تصاویر نشان دهنده وقوع overfitting است. دقت اطلاعات آموزشی ما به نزدیک ۱۰۰٪ رسیده ولی دقت  اطلاعات ارزیابی بعد از ۵ دوره به حدود ۷۰٪ رسیده و بعد از آن تغییری نکرده. چون تعداد تصاویر ما کم است  و شبکه اطلاعات را حفظ کرده و قدرت عمومیت بخشی ندارد.

شبکه با Dropout

برای جلوگیری از این اتفاق روش Dropout را امتحان می‌کنیم.

حالا دوباره نمودار های دقت و خطا را بررسی می‌کنیم.

همان طور که تصاویر مشخص است این روش تاثیر اندکی روی سیستم گذاشته و شبکه را کمی بهبود داده  ولی هنوز هم مشکل overfitting برطرف نشده. برای مقابله با این مشکل باید از روش data augmentation  استفاده کنیم که در آینده با آن آشنا خواهیم شد.

در آخر مدل را برای استفاده های بعدی ذخیره می‌کنیم.

 

کدها برگرفته از فصل دو کتاب Deep Learning with Python و گیت هاب نویسنده کتاب و توسعه دهنده  کراس François Chollet است.