در این پست مقاله EfficientDet را بررسی و پیاده‌سازی می‌کنیم.

در سال ۲۰۱۹ نویسندگان مقاله EfficientNet، مقاله جدیدی تحت عنوان EfficientDet: Scalable and Efficient Object Detection ارائه کردند. هدف آن‌ها همانند EfficientNet ارائه مجموعه‌ای از شبکه‌های کارآمد بود اما این بار برای کاربردی متفاوت یعنی تشخیص اشیاء. آن‌ها در این مقاله با استفاده از چند تکنیک کاربردی و مهم موفق به ارائه بهترین شبکه‌های موجود در آن زمان برای تشخیص اشیاء شدند. این تکنیک‌ها عبارت بودند از شبکه هرمی ویژگی دو جهته وزن‌دار (BiFPN) که امکان ادغام ویژگی‌های چند مقیاسی را به صورت سریع و آسان فراهم می‌کند و یک روش مقیاس‌بندی ترکیبی که به طور یکنواخت وضوح، عمق و عرض را برای همه شبکه‌های ستون فقرات (backbone)، شبکه ویژگی و شبکه پیش‌بینی جعبه/کلاس به طور همزمان مقیاس می‌کند. ما در ادامه این تکتیک‌ها را بررسی می‌کنیم و معماری مدل ارائه شده را مشاهده می‌کنیم.

شبکه هرمی ویژگی دو جهته وزن‌دار (BiFPN)

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

Feature network design
شکل ۱: طراحی شبکه ویژگی در مدل‌های مختلف. a) مدل FPN یک مسیر بالا به پایین برای ترکیب ویژگی‌های چند مقیاسی از سطح ۳ تا ۷ معرفی می‌کند. b) مدل PANet یک مسیر اضافی پایین به بالا را به روش FPN اضافه می‌کند. c) مدل NAS-FPN از جستجوی معماری عصبی برای یافتن یک توپولوژی نامنظم شبکه ویژگی استفاده می‌کند و سپس به طور مکرر همان بلوک را اعمال می‌کند. d) شبکه ویژگی BiFPN را نشان می‌دهد که از اتصالات بالا به پایین و پایین به بالا منظم با اعمال مکرر بلوک استفاده می‌کند.

در شکل ۱ سطوح Pi یک سطح از ویژگی با رزولوشن 1/2i را نشان می‌دهند. بنابراین برای تصویر ورودی با رزولوشن 640×640 رزولوشن سطح ۳ (P3) برابر 640/23 = 80 خواهد بود. به عبارتی دیگر رزولوشن ویژگی سطح P7 نصف رزولوشن سطح P6 است و به همین ترتیب. گفتیم FPN از یک روش بالا به به پایین برای ترکیب ویژگی‌ها استفاده می‌کند و با افزایش سایز ویژگی‌های با رزولوشن پایین، آن‌ها را با ویژگی‌های سطح بعد ترکیب می‌کند. این امر را می‌توان با فرمول زیر نشان داد.

FPN Equation

روش بالا به پایین موجود در FPN باعث محدود شدن جریان اطلاعات تنها در یک مسیر می‌شود. برای حل این مشکل PANet یک مسیر پایین به بالا را نیز به این معماری اضافه می‌کند که این مورد در شکل ۱ بخش b نشان داه شده است. همانطور که در شکل ۱ بخش c نشان داده شده است، NAS-FPN از جستجوی معماری عصبی برای یافتن توپولوژی بهتر شبکه ویژگی استفاده می‌کند، اما به هزاران ساعت GPU در طول جستجو نیاز دارد و شبکه یافت شده نامنظم است و تفسیر یا تغییر آن دشوار است.

در روش پیشنهادی EfficientDet از ترکیب ایده‌های قبلی به همراه تعدادی بهینه‌سازی استفاده می‌شود. به طور مثال نودهایی که تنها یک ورودی دارند حذف می‌شوند. این کار باعث سادگی شبکه شده و تاثیری روی دقت نخواهد داشت. همچنین یک اتصال اضافه از ورودی اصلی به نود خروجی در هر سطح اضافه می‌شود تا ویژگی‌های بیشتری بدون افزایش هزینه چندان، ترکیب شوند. این موارد در شکل ۱ بخش c نشان داه شده‌اند.

ایده دیگری که در ترکیب ویژگی‌ها در EfficientDet مطرح شده است ترکیب وزن‌دار ویژگی‌های سطوح مختلف است. بر خلاف روش‌های قبلی که برای ویژگی‌های سطوح مختلف وزن‌های یکسان در نظر گرفته می‌شد، نویسندگان در این مقاله تاکید دارند با توجه به این‌که ویژگی‌های ورودی مختلف در وضوح‌های متفاوتی هستند، معمولاً به طور نابرابری روی ویژگی خروجی تاثیر می‌گذارند. برای حل این مسئله آن‌ها برای هر ورودی یک وزن جداگانه در نظر می‌گیرند و به شبکه اجازه می‌دهند تا این وزن‌ها را با توجه به اهمیت هر ویژگی یاد بگیرد. آن‌ها برای ترکیب وزن‌ها از فرمول زیر استفاده می‌کنند:

Fast normalized fusion

بنابراین برای مثال نحوه محاسبه P6out در شکل ۱ بخش d به صورت زیر خواهد بود (P6td ویژگی میانی محاسبه شده در سطح ۶ است):

همچنین برای بهبود بیشتر کارایی، از کانولوشن تفکیک‌پذیر عمقی برای ترکیب ویژگی‌ها و از نرمال‌سازی دسته‎ای (batch normalization) و فعال‌ساز پس از هر کانولوشن استفاده می‌شود.

مقیاس‌بندی ترکیبی

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

در EfficientDet با در نظر گرفتن ایده مطرح شده در EfficientNet به طور همزمان تمامی ابعاد (عمق، عرض و رزولوشن) شبکه‌ها (ستون فقرات، BiFPN، شبکه پیش‌بینی جعبه/کلاس) با استفاده از یک ضریب مقیاس ساده φ افزایش مقیاس داده می‌شود. البته بر خلاف EfficientNet که از یک جستجو شبکه‌ای برای یافتن پارامترهای مقیاس‌بندی استفاده می‌شد، در EfficientDet با توجه به اینکه با مسئله تشخیص اشیاء روبرو هستیم و پارامترهای بسیار بیشتری برای تنظیم وجود دارد، از یک روش مقیاس‌بندی ابتکاری استفاده می‌شود.

مقیاس‌بندی شبکه ستون فقرات

EfficientDet از همان ضرایب مقیاس‌بندی عرض/عمق EfficientNet-B0 تا B6 مجدداً استفاده می‌کند. این کار کمک می‌کند تا به راحتی از وزن‌های از پیش آموزش داده شده EfficientNet روی ImageNet دوباره استفاده شود.

مقیاس‌بندی شبکه BiFPN

عمق BiFPN (تعداد لایه‌ها) به صورت خطی افزایش می‌یابد اما عرض (تعداد کانال‌ها) به صورت نمایی افزایش می‌یابد. به طور دقیق‌تر عمق و عرض شبکه BiFPN توسط فرمول‌های زیر افزایش مقیاس می‌یابند (D نشان‌دهده عمق و W نشان‌دهنده عرض می‌باشد):

Equation 1

مقیاس‌بندی شبکه پیش‌بینی جعبه/کلاس

عرض این شبکه همیشه برابر با عرض شبکه BiFPN در نظر گرفته می‌شود، اما عمق (تعداد لایه‌ها) آن به صورت خطی طبق رابطه زیر افزایش مقیاس می‌یابد:

Equation 2

رزولوشن تصویر ورودی

از آنجایی که سطوح ویژگی ۳ تا ۷ در BiFPN استفاده می‌شوند، وضوح تصویر ورودی باید بر 27 = 128 قابل تقسیم باشد، بنابراین وضوح به صورت خطی با استفاده از معادله زیر افزایش می‌یابد:

شبکه‌های مقیاس‌یافته

با استفاده از فرمول‌های فوق با مقادیر مختلف φ، شبکه‌های EfficientDet-D0 تا D7 طبق جدول ۱ بدست می‌آیند. شبکه‌های D7 و D7x شبکه BiFPN یکسانی دارند اما D7 از رزولوشن بزرگتری استفاده می‌کند و D7x از شبکه ستون فقرات بزرگتر و یک سطح ویژگی بیشتر (P3 تا P8) استفاده می‌کند.

Scaling configs for EfficientDet D0-D7
جدول ۱: تنظیمات مقیاس برای شبکه‌های EfficientDet

معماری EfficientDet

در شکل ۲ معماری کلی EfficientDet نشان داده شده است. EfficientDet از پارادایم تشخیص‌دهنده‌های تک مرحله‌ای (one-stage) پیروی می‌کند. از EfficientNet با وزن‌های از پیش آموزش داده شده بر روی ImageNet به عنوان شبکه ستون فقرات استفاده می‌شود. از BiFPN به عنوان شبکه ویژگی استفاده می‌شود که ویژگی‌های با سطوح ۳ تا ۷ را از ستون فقرات می‌گیرد و سپس ویژگی‌های ترکیب شده را به یک شبکه جعبه/کلاس می‌دهد تا کلاس اشیاء و جعبه مرزی آن‌ها تشخیص داده شود. وزن‌های شبکه جعبه/کلاس در تمام سطوح ویژگی‌ها مشترک است.

EfficientDet architecture
شکل ۲: معماری EfficientDet. بر اساس محدودیت‌های منابع مختلف، هم لایه‌های BiFPN و هم لایه‌های شبکه جعبه/کلاس، طبق جدول ۱ چندین بار تکرار می‌شوند.

پیاده‌سازی

پیاده‌سازی آماده مدل EfficientDet در تنسورفلو موجود است. برای استفاده از این مدل آماده و از پیش آموزش داده شده تنها نیاز است تا از دستورات زیر استفاده نمایید.

ما در اینجا از مدل EfficientDet-D0 استفاده کردیم که شما می‌توانید با توجه به نیاز خود از نسخه‌های دیگر EfficientDet نیز استفاده کنید. برای ارزیابی مدل از یک تصویر نمونه با نام example.jpg استفاده شده است و پس از پیش‌پردازش‌های لازم عمل تشخیص بر روی تصویر به کمک مدل مورد نظر انجام شده است. در نهایت نیز جعبه‌های مرزی تشخیص داده شده به همراه کلاس اشیاء با کمک تابع visualize_detections بر روی تصویر به نمایش در می‌آید. نتیجه اجرای کد فوق بر روی تصویر نمونه ما در شکل ۳ آورده شده است.

شکل ۳: نتیجه اجرای مدل EfficientDet-D0 بر روی یک تصویر نمونه

پیاده‌سازی از پایه

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

معماری اصلی مدل در پوشه model و در فایل det.py موجود می‌باشد. ما تنها به بررسی بخش‌های اصلی کد یعنی متدهای __init__ و forward از کلاس EfficientDet می‌پردازیم.

در متد __init__ ابتدا نسخه EfficientDet مورد نظر چک می‌شود. سپس شبکه‌های ستون فقرات، BiFPN و شبکه‌های جعبه (Regresser) و کلاس (Classifier) تعریف می‌شوند. از ChannelAdjuster برای بدست آوردن ویژگی‌های سطوح P3 تا P7 استفاده می‌شود. دقت نمایید که تعداد لایه‌های BiFPN و Regresser و Classifier دقیقا طبق جدول ۱ مشخص می‌شوند. در نهایت نیز در تابع forward ورودی به ترتیب از ستون فقرات، adjuster، شبکه BiFPN و شبکه‌های جعبه و کلاس عبور داده می‌شود تا خروجی‌های نهایی که مشخص کننده جعبه‌های مرزی (box_outputs) و کلاس‌های تشخیص داده شده (cls_outputs) می‌باشند، بدست آید.

معماری شبکه BifPN نیز در پوشه model و در فایل bifpn.py موجود می‌باشد. ما در اینجا نگاهی اجمالی به کدهای این کلاس خواهیم داشت.

در متد __init__ عملیات کانولوشن و وزن‌های اولیه در هر سطح تعریف می‌شوند. همچنین عملیات مورد استفاده برای افزایش (upsample) و کاهش سایز (downsample) مشخص می‌شوند. تابع فعال‌ساز نیز طبق توضیحات مقاله تابع swish انتخاب می‌شود. در تابع forward ورودی دقیقا طبق شکل ۴ پردازش و خروجی داده می‌شود. از تابع _fuse_features نیز برای ترکیب وزن‌دار ویژگی‌ها استفاده می‌شود.

BifPN Layer
شکل ۴: نحوه ترکیب ویژگی‌های سطوح مختلف در BiFPN. فلش‌های آبی نشان‌دهنده upsample و فلش‌های قرمز نشان‌دهنده downsample می‌باشند.

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