تبلیغات
تبلیغات

آموزش کلاسیفیکیشن تصویر با دیتاست MNIST به کمک Keras در پایتون

آموزش کلاسیفیکیشن تصویر با دیتاست MNIST در 10 دقیقه (پایتون)

آموزش کلاسیفیکیشن تصویر با دیتاست MNIST به کمک Keras در پایتون
طبقه بندی ارقام دست نویس به کمک Kersas


اگر مبحث «یادگیری عمیق (Deep Learning)» را با «شبکه‌ی عصبی (Neural Network)» شروع کرده باشید، به این نکته پی برده‌اید که یکی از تکنیک‌های قدرتمند «یادگیری عمیق»، «شبکه‌های عصبی کانولوشنال (Convolutional Neural Networks یا CNN یا شبکه عصبی پیچشی)» هستند.

ساختار نهایی CNN، در واقع بسیار شبیه به «شبکه‌های عصبی منظم (Regular Neural Networks یا RegularNets)» می‌باشد؛ که در آن، نرون‌‌ها با وزن و بایاس‌ها وجود دارند. علاوه‌بر این و همانند شبکه‌های عصبی منظم، ما از یک تابع ضررر یا زیان (Loss Function)، مثلا: بیشینه هموار یا corrs entropy در مقابل softmax؛ و همچنین از یک بهینه‌ساز (optimizer)، مثلا: adam optimizer؛ در CNNها استفاده می‌کنیم. به‌علاوه، در CNNها، لایه‌های Convolutional، لایه‌های Pooling و لایه‌های Flatten نیز وجود دارند. CNNها عمدتا جهت طبقه‌بندی (کلاسیفیکیشن یا Classification) تصویر مورد استفاده قرار می‌گیرند؛ اگرچه ممکن است در زمینه‌های کاربردی دیگری از جمله «پردازش زبان طبیعی (Natural Language Processing)» نیز یافت شوند.

چرا شبکه‌های عصبی کانولوشنال؟

ویژگی اصلی ساختار RegularNets، متصل بودن تمامی نورون‌ها به یکدیگر است. به‌عنوان مثال، هنگامی که ما تصاویر 28 x 28 پیکسلی با مقیاس خاکستری در اختیار داشته باشیم، در نهایت، 784 یا (28 x 28 x 1) نورون در یک لایه خواهیم داشت؛ که به نظر قابل کنترل (manageable) می‌آید. با این‌حال، اکثر تصاویر شامل پیکس‌های بیشتری بوده و همچنین خاکستری نیستند. لذا با فرض اینکه ما مجموعه‌ای از تصاویر رنگی با ابعاد 4K Ultra HD در اختیار داشته باشیم، در نهایت ما 26,542,080 یا (4096 x 2160 x 3) نورن متفاوتی خواهیم داشت؛ که در لایه‌ی اول به یکدیگر متصل بوده و در واقع قابل کنترل نیست. بنابراین می‌توان گفت که RegularNets برای کلاسیفیکیشن تصویر، مقیاس‌پذیر (scalable) نیست. با این حال و به ویژه وقتی صحبت از تصاویر می‌شود، به‌نظر ارتباط یا رابطه کمی بین دو پیکسل مجزا وجود دارد، مگر آنکه نزدیک یکدیگر باشند. این منجر به ایده‌ی لایه‌های Convolutional یا لایه‌های Pooling می‌شود.

لایه‌ها در CNN

ما قادر به استفاده از لایه‌های مختلفی در یک CNN هستیم. با این حال، کانولوشن (convolution)، پولینگ (pooling) و لایه‌های تماما متصل (fully connect layers)، مهم‌ترین آنها هستند. لذا در ادامه و به‌طور مختصر، این لایه‌های را قبل از پیاده‌سازیشان معرفی خواهم کرد.

لایه‌های کانولوشن (Convolution: پیچشی یا حلقوی)

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

کانولوشن، در اصل، فیلتر کردن تصویر با یک فیلتر پیکسلی کوچکتر است؛ تا اندازه‌ی تصویر، بدون از دست دادن ارتباط بین پیکسل‌ها کاهش یابد. هنگامی که ما با استفاده از یک فیلتر 3×3، با گام 1×1 (یک تغییر پیکسل در هر مرحله)، کانولشن را به تصویر 5×5 اعمال می‌کنیم. ما در نهایت به یک خروجی 3×3 خواهیم رسید (64٪ کاهش در پیچیدگی).

شکل 1: کانولوشن تصویر 5در5 پیکسلی با فیلتر 3در3 پیکسلی (گام = 1در1 پکسل)

شکل 1: کانولوشن تصویر 5در5 پیکسلی با فیلتر 3در3 پیکسلی (گام = 1در1 پکسل)

لایه‌های Pooling

به‌هنگام ساخت و ایجاد CNNها، درج لایه‌های پولینگ بعد از هر لایه‌ی کانولوشن، به منظور کاهش بار محاسباتی (پیچدگی محاسباتی)، حافظه و تعداد پارامترها، مرسوم بوده و در واقع هدف اصلی این لایه، کوچک کردن (subsample) تصویر ورودی است. علاوه بر این، لایه‌های پولینگ باعث کاهش ریسک overfitting می‌شوند. همچنین کاهش اندازه‌ی تصویر ورودی باعث می‌شود تا شبکه عصبی،  نسبت به جابجایی تصویر (مستقل از موقعیت) حساسیت کمتری داشته باشد.

اساسا در این لایه و جهت کم کردن میزان پارامترها، ماکسیمم، میانگین و یا مجموع مقادیر درون پیکسل‌ها را به عنوان انداژه‌ای برای پولینگ (Pooling Size) انتخاب می‌کنیم. پولینگ ماکسیمم (Max Pooling)، یکی از رایج ترین تکنیک های پولینگ، می‌تواند به صورت زیر نمایش داده شود:

پولینگ ماکسیمم با 2در2

پولینگ ماکسیمم با 2در2

مجموعه ای از لایه های کاملاً متصل

یک شبکه‌ی کاملا متصل، همانند RegularNet است؛ که هر پارامتر به یکدیگر متصل می‌شود؛ تا رابطه‌ی صحیح و تأثیر هر پارامتر روی برچسب‌ها را تعیین کند.

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

یک لایه تماما متصل با دو لایه مخفی

یک لایه تماما متصل با دو لایه مخفی


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

مثالی از شبکه عصبی کانولوشنال

مثالی از شبکه عصبی کانولوشنال

و حال که شما ایده‌ و تصوری از شبکه عصبی کانولوشنال جهت کلاسیفیکیشن تصاویر دارید، می‌توانیم دیتاست‌های کلیشه‌ای زیادی را دریافت کنیم؛ مثلا دیتاست MNIST، که مخفف … بوده و یک پایگاه داده یا دیتابیس بزرگی از ارقام دست‌نویس می‌باشد؛ که معمولاً برای تعلیم سیستم‌های مختلف پردازش تصویر استفاده می‌شود.

دانلود دیتاست MINIST

دیتاست MNSIT، یکی از متداول‌ترین مجموعه داده‌هاییست که برای طبقه‌بندی (کلاسیفیکیشن) تصاویر، استفاده شده و از بسیاری منابع مختلف، قابل دسترسی است. در حقیقت، Tensorflow و Keras نیز این اجازه را به ما می‌دهند تا دیتاست MNIST را مستقیما از طریق API آنها وارد کرده و دانلود کنیم. بنابراین، من با وارد کردن دو خط کد زیر، مراحل کار را شروع می‌کنم:
tensorflow و دیتاست MNIST (تحت Kares) وارد پروژه می‌شوند.

نکته
اگر در هنگام اجرای این بخش، با خطای HTTPError یا HTTP Error 403: Forbidden مواجه شدید؛ بایستی از یک روش دور زدن تحریم استفاده کنید. این بخش، شروع به دانلود دیتاست از گوگل می‌کند که به خاطر تحریم، با خطا مواجه می‌شود.

دیتاست MNIST، شامل 60,000 تصویر جهت تعلیم (Training) و 10,000 تصویر تست شده از کارمندان اداره سرشماری و دانش آموزان دبیرستانی آمریکایی می‌باشد. بنابراین من در خط دوم، این دو گروه تعلیم و تست را از هم جدا کردم. همچنین تصاویر و برچسب تصاویر نیز از یکدیگر جدا شده‌اند.

x_train و y_train، حاوی کدهای RGB خاکستری از 0 تا 255 هستند؛ درحالی که y_train و y_test، حاوی برچسب‌های 0 تا 9 می‌باشند؛ و این برچسب‌ها، نشان‌دهنده‌ی این هستند که تصویر مرتبط با آنها، مربوط به کدام رقم (عدد) می‌باشد. برای بصری سازی این تصاویر و نمایش دادنشان، می‌توان از matplotlib استفاده کرد:

وقتی ما کد بالا را اجرا می‌کنیم، همانطور که در تصویر زیر مشاهده می شود، تجسم یا حالت بصری خاکستری از کدهای RGB را دریافت خواهیم کرد:

بصری تصویر نمونه‌ی موجود در ایندکس 7777

بصری تصویر نمونه‌ی موجود در ایندکس 7777

همچنین جهت انتقال این دیتاست به کانال آن در شبکه عصبی پیچشی، بایستی ابعاد آن را نیز بدانیم. لذا از صفت shape آرایه‌های numpy و به‌صورت زیر استفاده می‌کنیم:

شما با چاپ این ویژگی، مقدار (60000, 28, 28) را دریافت خواهید کرد. همانطور که احتمالا حدس ‌زده‌اید، عدد 60000، تعداد داده‌ی موجود در دیتاست تعلیم را نشان می‌دهد و (28, 28) نیز بیانگر اندازه‌ی تصویر است: 28 در 28 پیکسل.

تغییر ابعاد و نرمال‌سازی تصاویر

برای آنکه بتوانیم از دیتاست موجود در API پکیج Keras استفاده کنیم، به آرایه‌های 4 بعدی نامپی نیاز داریم. با این حال و همانطور که در بالا می‌بینید، آرایه‌های ما سه بعدی هستند. علاوه‌بر این، ما بایستی داده‌های خود را نرمال کنیم؛ چرا که همواره در مدل‌های شبکه عصبی، مورد نیاز است.

ما می‌توانیم با تقسیم کدهای RGB به 255 (که حداکثر کد RGB منهای حداقل کد RGB است)، به این هدف گفته شده دست یابیم. این کار، با کد زیر قابل انجام است:

ساخت شبکه‌ی عصبی پیچشی

ما مدل خود را با استفاده از API سطح بالای Keras که از TensorFlow یا Theano در وَرای خود استفاده می‌کند، می‌سازیم. البته لازم به ذکر است که APIهای سطح بالای مختلفی برای TensorFlow وجود دارند؛ مانند Layers و Keras و Estimators که به ما در ایجاد شبکه‌های عصبی با دانش سطح بالا کمک می‌کنند. اما با این حال، همه‌ی آنها، به یک شکل پیاده‌سازی نمی‌شوند و ساختار آنها نسبت به یکدیگر متفاوت است.

من از ساده‌ترین API که Keras است، استفاده خواهم کرد. لذا، مدل Sequential را از Keras وارد کرده و لایه‌های Conv2D، MaxPooling، Flatten، Dropout  و Dense را اضافه می‌کنم. قبلا در مورد لایه‌های Maxpooling، Conv2D و Dense صحبت کردم. علاوه‌براین، لایه‌های Dropout، با نادیده گرفتن برخی از نورون‌ها در هنگام تعلیم با مشکل overfitting مقابله می‌کنند؛ در حالی که لایه‌های Flatten، آرایه‌های 2بعدی را قبل از ایجاد لایه‌های تماما متصل، به آرایه‌های تک‌بعدی تبدیل می‌کنند (مثل صاف کردن).

می‌توان با هر شماره‌ای، اولین لایه‌ی Dense را آزمایش یا امتحان کنیم؛ با این حال، آخرین لایه‌ی Dense، بایستی 10 نورون داشته باشد؛ چراکه ما 10 کلاس شماره داریم (0، 1، 2، …، 9). همچنسن می‌توانید همیشه با تغییر مقادیر اندازه‌ی کرنل، اندازه‌ی pool، توابع فعال‌سازی، نرخ dropout و تعداد نورون‌ها در اولین لایه‌ی Dense، آن را آزمایش کنید.

کامپایل و متناسب‌سازی مدل

با کد بالا، ما یک CNN خالیِ بهینه‌نشده‌ای را ایجاد کردیم. (که نه داده داشته و نه عملیات تعلیمی انجام گرفته است!)

اکنون زمان تنظیم یک بهینه ساز با دادن تابع ضرری (لاس یا Loss) که از یک معیارهایی (متریک) استفاده می‌کند، فرا رسیده است. سپس می‌توانیم با استفاده از داده‌های تعلیم خود، مدل را متناسب کنیم. از کدهای زیر، برای انجام این وظایف استفاده می‌کنیم:

شما می‌توانید با تغییر بهینه‌ساز، تابع زیان (لاس)، معیارها و دوره‌ها (epochs)، کامپایل را آزمایش کنید. به هر حال، بهینه‌ساز Adam، معمولا عملکرد بهینه‌سازهای دیگر را ندارد.

عدد دوره‌ها (epochs)، ممکن است کمی کوچک به نظر برسد. با این حال، شما به دقت 98 تا 99 درصدی خواهید رسید.

از آنجایی که دیتاست MNIST به محاسبات سنگینی نیاز ندارد، می‌توانید به راحتی و با تغییر مقدار epchos، شبکه را آزمایش کنید.

ارزیابی مدل

در انتها، می‌توانید مدل‌های آموزش دیده  (تعلیم یافته) را با x_test و y_test بیازمایید. با استفاده از یک خط کد زیر:

نتایج برای 10 دوره و برای چنین مدل ساده‌ای، بسیار خوب است:

ارزیابی نشان دهنده دقت 98.5% بر روی مجموعه تست است

ارزیابی نشان دهنده دقت [FK_L]98.5%[/FK_L] بر روی مجموعه تست است

ما با چنین مدل پایه‌ای، دقت 98.5 درصدی را به‌دست آوردیم. صراحتا، در بسیاری از موارد کلاسیفیکیشن تصویر (به عنوا مثال برای اتومبیل‌های خودران)، حتی نمی‌توانیم خطای 0.1 درصدی را هم تحمل کنیم؛ چرا که با یک قیاس، این خطا موجب اتفاق دادن 1 تصادف از 1000 مورد می‌شود. با این حال، برای اولین مدل ما، می‌گویم نتیجه هنوز هم بسیار خوب است.

ما همچنین می‌توانیم پیشبینی تکی را با کد زیر انجام دهیم:

مدل ما، تصویری که در ایندکس 4444 تصاویر تستی وجود دارد را به عنوان «9» کلاسیفای می‌کند؛ و در پایین، حالت بصری تصویر را مشاهده می‌کنید:

مدل ما به درستی این تصویر را به عنوان 9 (نُه) کلاسیفای کرد

مدل ما به درستی این تصویر را به عنوان 9 (نُه) کلاسیفای کرد

اگرچه واقعاً دست نویس خوبی برای شماره 9 نیست ، اما مدل ما توانست آن را به عنوان 9 طبقه‌بندی کند.

تبریک

شما با موفقیت یک شبکه عصبی پیچشی را برای طبقه بندی ارقام نوشته شده دستی با API Keras Tensorflow ایجاد کردید. شما به دقت بیش از 98٪ دست یافته‌اید و اکنون می‌توانید این مدل را نیز ذخیره کرده و یک برنامه‌ی طبقه‌بندی رقمی ایجاد کنید! همچنین اگر در مورد نحوه‌ی ذخیره‌ی مدل خود کنجکاو هستید، می‌توانید «مستندان Keras» را مطاطعه کنید.

منابع

  1. KataKoda
  2. CS231n Convolutional Neural Networks for Visual Recognition
  3. MathWorks, Introducing Deep Learning with MATLAB
  4. Wikipedia, MNIST database
  • Add to Phrasebook
    • No word lists for Persian -> Persian…
    • Create a new word list…
  • Copy
کانال تلگرام فول کده
تبلیغات

درباره نویسنده

هادی اکبرزاده

[ مدیر فول کده ]

علاقه‌مند به اشتراک‌گذاری اطلاعات در هر زمینه‌ای
برنامه‌نویس فول استک

پاسخ دهید

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

نظرات ثبت شده بدون دیدگاه