دقیقا دو هفته پیش، در نسخه انگلیسی وبلاگ در مورد YOLOv5 نوشتم (لینک) و توضیح دادم که چرا این مدل هوش مصنوعی برای تشخیص اشیاء رو دوست دارم (و حتی چرا شما باید دوستش داشته باشید) و خب طبیعتا دوست داشتم یک پروژه خیلی خیلی ساده و در عین حال باحال هم با این مدل انجام بدم.
ایدههای زیادی در سر داشتم. برای مثال ایده بازی Red Light – Green Light که در سریال اسکوییدگیم همه دیدیم. اما این ایده علیرغم خوب بودنش، آنچنان کاربردی نبود. پس تصمیم من برآن شد که یک نرمافزار دیگر توسعه بدم. نرمافزاری که هم چالش داشته باشه، هم در نهایت یک کاربرد درست ازش بشه درآورد.
نمیدونم شما یادتونه یا نه، اما نرمافزار سیمبولب، دروانی خیلی خاص و معروف شد. به همین خاطر، تصمیم من هم این شد که سیمبولب رو دوباره بسازم و بعد از این که نتایج مورد نظرم رو گرفتم در موردش وبلاگ بنویسم. پس این شما و این ماجرایی که من داشتم تا این نرمافزار رو بسازم.
گام اول: طرح مساله
در هر پروژهای، اولین گام اینه که مطرح کنیم چه مشکلی رو باید حل کنیم. یا به قول دنیل کوهن Look for the pain. خب دردی که ما اینجا به دنبال حل کردنش بودیم، چی بود؟ این که بسیاری از دانشآموزا و دانشجوها سر ریاضی عمومی یا Calculus مشکل دارند. این مشکل ریشهش کجاست؟ برای من شخصا مهم نیست که این ریشه رو بررسی کنم (البته به معنای این نیست که نظری در موردش ندارم، اما از حوصله این مطلب خارجه).
حالا درد این که بسیاری از دانشجوها و دانشآموزها مشکل دارند، چطور میشه براشون یک مسکن خوب تجویز کرد؟ بعنوان یک مهندس هوش مصنوعی، یا بهتر بگم مهندس بینایی ماشین در ذهنم این ایده چرخید و اون این بود که:
یک نرمافزار هوش مصنوعی وجود داشته باشه که از روی عکس مساله، پاسخ نهایی یا راهحل رو به افراد بده.
و این پروژه، در نظر پروژه بسیار بسیار بزرگی بود اما در نهایت، پروژه سادهای شد. در ادامه، در راهی که طی شد توضیح خواهم داد.
گام دوم: انتخاب ابزار
گام دوم برای من، انتخاب ابزار بود. اول از همه میخواستم برم سراغ OCR های آماده برای تشخیص مسائل پارامتری مثل x و y و … . اما بعد دیدم که اینجا علاوه بر حروف و اعداد، نشانهها هم هستند. ضمن این که به شکلی باید توان و … هم تشخیص داد. پس کمی پروژه رو نگه داشتم تا به ابزارها فکر کنم.
بعد از مدتی تحقیق و تفحص، به دارکنت رسیدم که برای ترین کردن YOLOv3 و YOLOv4 استفاده میشه و خب دارکنت مشکلات زیادی هم با خودش به همراه داره. برای مثال کاملا در سیپلاسپلاس نوشته شده و روی سیستمهای مختلف باید از نو کامپایل بشه. با CPU درست کار نمیکنه. کامپایل کردنش روی مک یا ویندوز دردسره و انتقال دادنش به Google Colab هم میتونه تا حد زیادی مشکلساز بشه.
بعد از اون الگوریتم YOLOv5 رو کشف کردم. تقریبا همه مراحل کاملا پایتونی پیش میرفت و این عالی بود. کم کم دیدم که میشه بعد از ترین کردن قضیه، از pytorch هم استفاده کرد و اشیاء رو تشخیص داد و از اون بهتر این بود که در تشخیص اشیاء، میشد خروجی pandas هم گرفت که مختصات شیء مورد نظر به همراه لیبلش در اون data frame خاص موجود بودند. پس به این شکل تشخیص این که ما با چه چیزی روبرو هستیم هم سادهتر از گذشته میشد.
وقتی این ابزار رو با چند چیز مختلف تست کردم، نوبت این رسید که در این پروژه حتما ازش استفاده کنم. اما این تمام ماجرا نیست. دقیقا وقتی که سمت OCR ماجرا هندل میشد، یک بحث خیلی مهم میموند. بحث این که چطوری باید مساله حل بشه؟ برای حل مساله هم از Wolfram Alpha گفتم کمک میگیرم.
خب حالا نوبتی هم باشه، نوبت اینه که دادههای مورد نیاز رو جمع کنیم. قبلتر در مورد راههایی که شما میتونید برای جمعآوری داده استفاده کنید، صحبت کردم و میتونید از اینجا بخونیدش.
گام سوم: جمعآوری داده
برای جمعآوری دادهها، نیازمند این بودم که روی چند سطح مختلف (وایتبرد، کاغذ A4 و همچنین کاغذ خطدار) و با چند دستخط مختلف، مسائل ریاضی رو بنویسم. بعد از نوشتن مسائل ریاضی، از دوستانم خواهش کردم که روی صفحات مختلف و همچنین وایتبرد، مسائل ریاضی رو بنویسند.
بعد از این که مسائل ریاضی رو روی این سطوح و با دستخطهای مختلف داشتم، نوبت عکاسی ازشون بود. از هر بار نوشتن، چندین عکس از چند زاویه گرفتم. چرا که زوایای مختلف باعث میشن توزیع نور هم در تصاویر یکسان نباشه و این خودش یک مرحله data augmentation رو برای من کاهش میداد.
حالا یه حجم زیادی داده دارم، باید بعدش چی کار کنم؟ پاسخ سادهست. الان زمانیه که ما وارد مرحله پیشپردازش داده میشیم.
گام چهارم: پیشپردازش داده
بعد از این که ما دادههای مورد نیاز خودمون رو جمع کردیم، نیازمند اینیم که داده رو پیشپردازش کنیم. به طور کلی، پیشپردازش داده به پروسهای گفته میشه که در اون قراره داده ها تمیز بشن، تغییر کنند (یا به قولی data augmentation رخ بده)، برچسب زده بشن و دادههای غیرلازم (یا همون نویز) دور ریخته بشه.
اولین مرحله برای من اینجا، تکه تکه کردن عکس بود. شاید فکر کنید که برای تکه تکه کردن عکس، از ابزار خاصی استفاده کردم یا کدی زدم. باید بگم که خیر، ابزارم دقیقا ادوبی فتوشاپ و ابزار Slice بود. بعدش با قابلیت save for web آمدم و عکسهای قطعهقطعه شده رو ذخیره کردم. پس از ذخیره نهایی عکسها، نیاز بود که عکسها برچسب زده بشن.
برچسبها، در مرحله آموزش مدل، به ما کمک میکنند که اشیاء رو در تصاویر پیدا کنیم. این برچسبها در مراحل بعدتر به کمک ما میان تا بتونیم مسائل یافت شده رو به ولفرامآلفا بدیم تا برامون حلش کنه. پس لازم بود که این اتفاقات بیفته.
گام پنجم: آموزش مدل YOLOv5
و اما گام یکی مونده به آخر دقیقا این بود که مدل آموزش داده بشه. آموزش این مدل با pytorch به شدت سرراست و راحته و کلش اجرا کردن یک دستور در ترمیناله. باز با این حال، مشکلات عدیدهای داشتم. برای مثال روی لپتاپ شخصی چون GPU مناسب نداشتم، آموزش به شدت طولانی میشد. آموزش رو به Google Colab منتقل کردم و چون پلن رایگان داشتم، اونجا هم یک سری داستان جدیدتر پیش آمد. اما بهرحال هرطور که شد، مدل آموزش داده شد و نتایج خوبی هم ازش گرفتم.
در مورد آموزش مدل و نحوه کار اون به زودی محتوای آموزشی جدیدی تولید خواهد شد که به تفصیل در اون توضیح میدم چطور میتونید YOLOv5 رو خودتون آموزش بدید و باهاش کار کنید. در حال حاضر، توضیح مراحل آموزش تا حد زیادی از حوصله این پست وبلاگ خارجه.
و گام نهایی: آزمایش مدل و نوشتن رابط ولفرام آلفا
پس از این که مدل آموزش داده شد، نیاز بود چندین خط کد پایتون نوشته شه برای چند منظور. اول این که وزنهایی که لازم بود از مدل آموزشدادهشده، لود کنه. دوم این که یک عکس رو از ورودی بگیره و مراحل inference رو روش انجام بده و در نهایت، اگر کاربرخواست اون رو بفرسته به ولفرام آلفا و مرورگر رو براش باز کنه.
برای این مرحله، برخلاف باقی مراحل وقت زیادی نذاشتم ولی با این حال کدش (بدون وزنها) در گیتهاب شخصی من موجوده و میتونید نگاهی بندازید. البته که به زودی گیتهاب بروزرسانی میشه و شما قادر خواهید بود که وزنها رو هم دانلود کنید. اما فعلا وزنها در دسترس نیستند.
در نهایت هم برای این که عملکرد قضیه رو ببینید، این ویدئو کوتاه رو میتونید تماشا کنید که هم inference رو تست میکنیم هم حل مساله با ولفرام رو:
جمعبندی و مشکلات این نرمافزار
این پروژه به عنوان یک پروژه تفریحی، واقعا تفریح خوب و سالمی بود و کلی یادگیری برای من داشت. یادگیری دقیقتر و عمیقتر YOLOv5، یادگیری دقیقتر و عمیقتر PyTorch و از همه مهمتر درگیر شدن با چند مساله و به قولی، دردهای دنیای واقعی. از نتیجه کاملا راضی بودم و هستم، اما فکر نکنم در آینده این پروژه خیلی برام راضیکننده باشه.
احتمالا بعد از مدتی به این پروژه برگردم و بزرگترین مشکلش – یعنی شباهت زیاد ورودیها به هم – رو طور دیگری هندل کنم. برای این که ببینیم یه چیزی در پوزیشن توان یه چیز دیگه قرار گرفته یه چارهای بیاندیشم و … . خلاصه که راه برای بهبودش زیاده و این بهبودها رو شخصا پیگیر هستم که در این پروژه اعمال کنم. شاید هم لازم باشه داده ورودی رو افزایش داد یا حتی مدل مورد استفاده رو عوض کرد.
در نهایت، از شما بابت وقتی که برای خوندن این مطلب گذاشتید، ممنونم. امیدوارم که این مطلب مفید واقع شده باشه و به دردتون خورده باشه. ضمن این که اگر به این تیپ مسائل و مطالب علاقمند هستید، میتونید من رو در ویرگول هم دنبال کنید و اونجا هم مطالبم رو بخونید. اگرچه در ویرگول عمده مطالبم مرتبط با بیزنس، موفقیت و ایناست.
در نهایت از شما خواهش میکنم که اگر این مطلب براتون مفید بود، یک قهوه به انتخاب خودتون مهمانم کنید تا موقع نوشیدن قهوه به یادتون باشم و از این دست مطالب، بیشتر تولید کنم.