در این راهنما به معرفی روش ساخت شبکه‌های عمیق جهت مقاصد بینایی ماشین می‌پردازیم. بینایی ماشین یا «بینایی رایانه» (Computer Vision) در زمینه هوش مصنوعی حوزه‌ای فعال و در حال پیشرفت محسوب می‌شود. این حوزه با سرعت زیادی و از طریق تحقیقات وسیعی که هر روزه منتشر می‌شوند در حال توسعه است و به طور مداوم امکان‌های جدیدی در اختیار ما قرار می‌دهد که تا پیش از این به وسیله رایانه‌ها و هوش مصنوعی ممکن نبود. در تصویر زیر نتایج حاصل از بکارگیری تکنیک Mask-RCNN را مشاهده می‌کنید که یکی از قوی‌ترین و انعطاف‌پذیرترین شبکه‌های عمیق است که تاکنون برای بینایی رایانه طراحی شده است. این شبکه توانایی ایجاد قطعه‌بندی‌های پدیده‌هایی که در تصاویر زیر مشاهده می‌کنید را دارد.

Mask-RCNN
تکنیک Mask-RCNN، یک وهله از شبکه قطعه‌بندی موجود

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

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

بدین منظور باید به این سؤالات پاسخ دهیم: ما باید از کدام شبکه‌ی از پیش آموزش دیده استفاده کنیم؟ چگونه باید آن را برای رفع نیازهای خود اصلاح کنیم؟ آیا باید از شبکه‌ای با 20 لایه یا از شبکه‌ای با 100 لایه استفاده کنیم؟ کدام شبکه سریع‌تر است؟ و کدام شبکه دقیق‌ترین عملکرد را دارد؟ همه این‌ها سؤالاتی هستند که هنگام تلاش برای انتخاب بهترین CNN برای وظایف بینایی رایانه باید پاسخ داده شوند.

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

کانولوشن

عملیات کانولوشن یا پیچش، ایده اصلی تشکیل‌دهنده CNN است و شیوه استفاده از آن یک عامل تعیین‌کننده بزرگ برای عملکرد شبکه است. استفاده از شبکه‌هایی با ابعاد بالاتر از 3×3 مزیت زیادی در CNN ندارد و از این رو باید از استفاده از شبکه‌های 5×5 یا 7×7 در شبکه خود اجتناب کنید. به طور مکرر اثبات شده است که کانولوشن های 3×3 که به طور متوالی انباشت می‌شوند، به همراه VGGNet و ResNet می‌توانند به همان «میدان تأثیر» (receptive field) که کانولوشن‌های بزرگ‌تر ارائه می‌دهند دست یابند و این در حالی است که از نظر محاسباتی نیز کارایی بیشتری دارند.

انباشت کانولوشن
در تصویر فوق شیوه انباشت کانولوشن های 3×3 برای دستیابی به میدان تأثیر 5×5 با 18 پارامتر (3×3 + 3×3 = 18) را ملاحظه می‌کنید. همچنین یک کانولوشن 5×5 نیازمند 25 پارامتر برای رسیدن به همان نتیجه خواهد بود.

کانولوشن‌های 1×1 می‌توانند در نقاط مشخصی در شبکه برای کاهش ابعاد نگاشت‌های ویژگی پیش از پردازش در اندازه 3×3 مورد استفاده قرار گیرند. ResNets این کار را با استفاده از bottleneck block که در زیر نمایش یافته انجام می‌دهند. به جای پردازش یک نگاشت ویژگی عظیم با 256 عمق، ابتدا همه این اطلاعات را در نگاشت‌های ویژگی 64 بعدی فشرده می‌کنیم. زمانی که این فشردگی انجام شد، از کانولوشن 3×3 استفاده می‌کنیم که وقتی روی 64 نگاشت ویژگی به جای 256 نگاشت اعمال شود، بسیار سریع‌تر است و چنین پردازشی می‌تواند همان نتایج یا نتایج بهتری نسبت به پشته‌های معمولی 3×3 ارائه کند. در نهایت با استفاده از 1×1 مجدداً به نگاشت اصلی 256 خود بازمی‌گردیم.

ابعاد نگاشت ویژگی
یک لایه تنگنای ResNet که با استفاده از کانولوشن های 1×1 اقدام به کاهش ابعاد نگاشت ویژگی می‌کند.

از آنجا که فعال‌سازی‌ها به طور عمده به کانولوشن‌های کد اتصال یافته‌اند، یک قاعده سرانگشتی مناسب که می‌توان برای شروع استفاده کرد ReLU است. با استفاده از ReLU در اغلب موارد بدون نیاز به تنظیمات ظریفی که در ELU، PReLU یا LeakyReLU مورد نیاز است، نتایج خوبی به دست می‌آید. با این حال همچنان بحث‌های زیادی در خصوص این که کدام فعال‌سازی بهترین گزینه است در جریان است. اما در استفاده‌های عملی تفاوت‌های این موارد بسیار اندک است و ارزش این همه آزمایش کردن را ندارد؛ مگر این که آن 1 درصد عملکرد بیشتر، واقعاً برای شما مهم باشد. زمانی که مطمئن شدید طراحی‌تان به طور کامل با ReLU کار می‌کند، در ادامه در صورت نیاز می‌توانید موارد دیگر را نیز بررسی کنید و پارامترهایشان را تنظیم کنید تا مطمئن شوید که نهایت دقت ممکن را به دست آورده‌اید.

بدین ترتیب این بخش را می‌توان چنین جمع‌بندی کرد که در اغلب موارد برای پردازش از پشته‌های 3×3 می‌توان استفاده کرد. استفاده از کانولوشن های 1×1 برای فشرده‌سازی و بسط ویژگی‌ها می‌تواند باعث کاهش هزینه محاسباتی شود.

Pooling

Pooling در CNN برای جمع‌بندی ویژگی هنگام نمونه‌برداری کاهشی استفاده می‌شود، زیرا بدین ترتیب می‌توانیم وارد لایه‌های عمیق‌تر شبکه بشویم. زمانی که به انتهای هر «مرحله» (stage) می‌رسیم و می‌خواهیم نمونه‌برداری کاهشی بکنیم، ظرفیت نگهداری اطلاعات فضایی به دلیل نمونه‌برداری کاهشی، پایین می‌آید. از این رو برای نگهداری این اطلاعات باید دست به pooling بزنیم تا آن چه را که داریم جمع بدی کنیم. دو نوع متداول از pooling به نام‌های Max و Average هستند.

در مورد بهتر بودن هر کدام از تکنیک‌های Max و Average نیز بحث زیادی در میان جامعه تحقیقاتی در جریان است. اگر بخواهیم صریحاً صحبت کنیم، تفاوت بین این دو نوع قابل اغماض است، بدین ترتیب یکی از پارادایم‌های رایج این است که از max pooling در سراسر شبکه برای نگهداری بهترین ویژگی‌ها و از average pooling در نقاط انتهایی برای دریافت بازنمایی برداری نهایی از ویژگی‌ها پیش از لایه متراکم آخر استفاده می‌شود و سپس همه چیز به softmax تحویل داده می‌شود.

max poling
یک تصویرسازی از max poling

بدین ترتیب مباحث مطرح شده در این بخش را می‌توان به صورت زیر جمع‌بندی کرد:

  • به عنوان روش پیش‌فرض بهتر است در سراسر شبکه از روش max pooling استفاده کنیم و در انتها و پیش از لایه متراکم softmax از average pooling سراسری استفاده کنیم.
  • می‌توان پیکربندی/سبک‌های دیگر را نیز بررسی کرد؛ اما تفاوت به دست آمده در اغلب موارد بسیار ناچیز خواهد بود.

عمق و ساختار شبکه

تعادل بین عمق، دقت و سرعت شبکه بسیار ساده است. هر چه لایه‌های بیشتری استفاده شوند، دقت کلی بالاتر می‌رود؛ اما باعث می‌شود که شبکه شما کندتر اجرا شود، زیرا تعداد محاسبات افزایش می‌یابد. به طور کلی، شما می‌توانید عمق‌های مختلف را بررسی کرده و بهترین نقطه که بالاترین نتیجه را به دست می‌دهد بیابید. پس از کمی آزمایش احتمالاً می‌توانید به خوبی این نقطه را حدس نیز بزنید. در برخی موارد باید آگاه باشید که تعادل بین دقت و سرعت تحت قاعده «بازده نزولی» (diminishing returns) است یعنی هر چه لایه‌های بیشتری اضافه بکنیم، دقت کمتری در هر لایه منفرد اضافه می‌شود.

standard benchmark

در مورد ساختار شبکه نیز، بنچمارک‌های استاندارد مانند ImageNet و بصری‌سازی‌های زیبا مانند دو مورد فوق باعث می‌شوند که کار ما آسان‌تر باشد. اگر سرعت در اولویت باشد، دو مورد MobileNet-v2 و Depthwise-Separable convolution blocks باید گزینه پیش‌فرض باشند. MobileNets این مزیت اضافی را نیز دارد که برای اجرا روی CPU بهینه‌سازی شده و می‌تواند در برخی موارد نتایج تقریباً آنی ارائه کند. شبکه‌های دیگر از نظر عملکرد روی GPU مشابه به نظر می‌رسند چون MobileNets بار پردازش را روی CPU قرار می‌دهد. این یک مزیت بزرگ است، چون محاسبات CPU از نظر قیمتی بسیار ارزان‌تر از GPU است.

عنوان دقیق‌ترین شبکه جهان همچنان مشخص نیست. دقت SENet و NASNet کسری از درصد با هم متفاوت است. اگر صرفاً قصد انتقال یادگیری را دارید بهتر است از NASNet استفاده کنید، زیرا چند پیاده‌سازی داخلی برای کتابخانه‌های یادگیری عمیق مانند Keras دارد. با این حال هنگامی که همه چیز را از صفر آغاز می‌کنید، کدنویسی SENet و بلوک‌های Squeeze-Excitation در عمل بسیار ساده‌تر خواهد بود. بدین ترتیب برای ساخت یک پروتوتایپ سریع با چیزی که تعادل خوبی بین دقت و سرعت داشته باشد می‌توانید از ResNet و Residual Blocks استفاده کنید.

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

اگر بخواهیم نکاتی که در این بخش مطرح شدند را جمع‌بندی کنیم:

  • استفاده از کانولوشن‎های MobileNet-v2 / Depthwise Separable و وضوح پایین برای سرعت بالا مناسب است.
  • کانولوشن‌های SENet / Squeeze-Excitation یا NASNet و وضوح تصویر بالا برای دقت مناسب هستند.
  • یک ResNet / Residual Blocks معمولی برای ایجاد تعادلی بین سرعت و دقت مناسب خواهد بود.

پیش‌پردازش داده و داده‌افزایی (Data Augmentation)

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

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

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

mean-normalisation

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

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

مواردی که در این بخش مطرح شدند را می‌توانید به صورت زیر جمع‌بندی کنید:

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

منظم‌سازی (Regularization)

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

در این حالت می‌توان از چند گزینه استفاده کرد که شامل dropout، spatial dropout، cutout، L1، L2، افزودن نویز گاوسی و موارد بسیار زیاد دیگر است. dropout به طور عملی ساده‌ترین استفاده را دارد زیرا معمولاً تنها کافی است آن را در چند جا قرار دهید و یک پارامتر منفرد را تنظیم کنید. برای نمونه می‌توانید آن را پیش از چندین لایه متراکم آخر در شبکه خود قرار دهید. اگر حس می‌کنید همچنان دچار بیش‌برازش هستند می‌توانید dropout را در لایه‌های قبلی در شبکه نیز قرار دهید و یا این که احتمال dropout را تغییر دهید. بدین ترتیب شکاف بین دقت مجموعه داده‌های آموزشی و تست کاهش می‌یابد.

اگر dropout شکست بخورد می‌توانید موارد دیگر را نیز بررسی کنید در گزینه‌هایی مانند L1 و L2 امکان تغییر پارامترهای بیشتری وجود دارد و از این رو می‌توان آن‌ها را طوری کالیبره کرد که وظیفه منظم‌سازی بهتر از dropout اجرا شود. در طیف وسیعی از موارد، لازم نیست بیش از یک تکنیک منظم‌سازی را با هم ترکیب کنید یعنی می‌توانید از یک گزینه در سراسر شبکه استفاده کنید.

اگر بخواهیم موارد مطرح شد در این بخش را جمع‌بندی کنیم، باید به نکات زیر اشاره کنیم:

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

آموزش

هنگامی که نهایتاً بخواهید شبکه خود را آموزش دهید، چند الگوریتم بهینه‌سازی وجود خواهند داشت که می‌توان از بین آن‌ها انتخاب کرد. افراد زیادی اعلام می‌کنند که SGD با توجه به دقت، بهترین نتایج را در اختیار شما قرار می‌دهد. با این وجود تنظیم دقیق زمان‌بندی و پارامترهای نرخ یادگیری می‌تواند امری چالش‌برانگیز و دشوار باشد. از سوی دیگر استفاده از نرخ یادگیری تطبیقی مانند Adam، Adagrad، یا Adadelta کاملاً آسان و ساده است؛ اما ممکن است آن دقت بهینه SGD را به دست نیاورید.

بهترین کاری که در این بخش می‌توان انجام داد، پیروی از همان سبک تابع‌های فعال‌سازی است. یعنی ابتدا انواع آسان‌تر را امتحان کنی تا ببینید آیا پاسخ مناسبی دریافت می‌کنید یا نه و سپس با استفاده از موارد پیشرفته‌تر اقدام به تنظیم دقیق و بهینه‌سازی کنید. توصیه کلی این است که کار خود را با Adam آغاز کنید، چون استفاده از آن بسیار آسان است. تنها باید دقت کنید که نباید نرخ یادگیری را مقدار بالایی تعریف کنید و با عددی در حدود 0.0001 می‌توانید نتایج خوبی به دست آورید. در ادامه می‌توانید از صفر از SGD استفاده کنید و یا این که ابتدا با Adam شروع کنید و سپس با SGD به تنظیم دقیق بپردازید. در واقع در برخی مقاله‌های تحقیقاتی مشخص شده است که سوئیچ کردن از Adam به آرشیوهای mid-training برای SGD بهترین دقت را به ساده‌ترین روش ارائه می‌کند. به تصویر زیر دقت کنید:

وقتی از داده‌ها صحبت می‌کنیم، هر چه بیشتر باشد، همواره بهتر خواهد بود. تنها نکته‌ای که باید واقعاً در نظر داشت این است که چه زمان نرخ بازدهی، نزولی می‌شود. برای نمونه اگر تا به اینجا 95 درصد دقت کسب کرده‌اید و تخمین می‌زنید که اگر داده‌های آموزشی را دو برابر کنید به دقت 96% می‌رسید، احتمالاً زمان آن رسیده است که بررسی کنید آیا واقعاً به آن 1% دقت نیاز دارید یا نه، چون منابع و تلاشی که برای رسیدن به آن مورد نیاز است بسیار زیاد است. البته باید مطمئن باشید که داده‌هایی که گردآوری می‌کنید بازتاب‌دهنده موارد لازمی است که در کاربرد واقعی وظیفه خود شاهد خواهید بود. در غیر این صورت مهم نیست که از چه الگوریتمی استفاده می‌کنید، چون داده‌هایی که به صورت ضعیفی انتخاب کرده‌اید، به کار نخواهند آمد.

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

==

میثم لطفی (+)

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

بر اساس رای 8 نفر

آیا این مطلب برای شما مفید بود؟

نظر شما چیست؟

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