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


یکی از وظایف پایه در مبحث بینایی ماشین Image Classification می باشد. در ادامه با چالش های عکس در این زمینه آشنا می شوید.

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

viewpoint variation : یکی دیگر از چالش ها، اختلاف بین زاویه های مختلف یک شیء می باشد.

Illumination : نورپردازی های مختف کار تشخیص شیء را دچار چالش می کند.

Deformation : حالت های مختلف یک شیء و تغییر حالت آن از دیگر مشکلات این فیلد می باشد.

Occlusion : ناقص بودن یک شیء ممکن است مدل را برای تشخیص دچار مشکل کند.

Background clutter : هم شکلی با محیط کار تشخیص شیء از محیط را دشوار تر می کند.

Intraclass variation : تنوع یک دسته شیء هم از دیگر چالش های این حوزه محسوب می شود.

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

 

محوریت ساخت مدل:

  • Collect a dataset of images and labels (جمع آوری عکس ها و لیبل ها)
  • Use Machine Learning to train an image classifier (آموزش مدل)
  • Evaluate the classifier on a withheld set of test images (ارزیابی مدل)

یک مدل ساده بر روی دیتاست هدی

طبقه بند چند لایه softmax

 

تعیین تابع هزینه و روش بهینه سازی

 

تعیین داده‌های آموزشی، سایز mini-batch و تعداد epoch

 

نکته : مدل ساخته شده بعد از مدتی (چندبار دیدن عکس ها) شروع به حفظ دیتاست و ساخت توابع پیچیده میکند که باعث ایجاد مشکلی به نام overfitting می شود.


شبکه های کانولوشنی

تا قبل از سال 2012 تصور بر این بود که تعداد لایه های درونی را نباید بیش از 2 تا نشود که میزان خطا بالاتر تر نرود این بدلیل استفاده از تابع activation ناکارآمد sigmoid بود که با معرفی و استفاده از تابع ReLu و بالاتر رفتن تعداد لایه ها میزان خطا کمتر شد.

ایده ایجاد شبکه های کانولوشنی

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

Padding

لبه ها به اندازه پیکسل های درونی در کانولوشن شرکت نمی کنند درنتیجه خروجی کوچک می شود ( اگر تعداد لایه های کانولوشنی زیاد باشد حجم زیادی از دیتا از بین میرود )

با اضافه کردن مقادیری در اطراف عکس ورودی سعی در شرکت بیشتر لبه ها در این عمل داریم که به آن padding می گویند.

اگر در اطراف عکس مقدار 0 گذاشته شود zero-padding انجام داده ایم.

 

انواع کانولوشن

Valid : اگر از سایز ورودی با سایز خروجی برابر نباشد در حقیقت کانولوشن valid انجام داده ایم (اگر ورودی n*n و سایز فیلتر f*f باشد خروجی (n-f+1)*( n-f+1) می شود

Same : اگر به مقداری padding بدهیم که سایز ورودی با سایز خروجی یکی شود کاولوشن same خواهد بود) اگر ورودی n*n و سایز فیلتر f*f باشد و به اندازه p واحد padding بدهیم خروجی (n+2p-f+1)*( n+2p-f+1)  یا همان n*n می شود.

* نکته: برای اینکه کانولوشن same شود باید به اندازه 2/(f-1) به عکس ورودی padding بدهیم

* نکته: سایز فیلتر باید فرد در فرد باشد

Stride : مقدار جابجایی فیلتر به صورت افقی (چندتا چندتا جلو بره)

نکته : اگر ورودی n*n و سایز فیلتر f*f باشد و به اندازه p واحد padding بدهیم و stride s داشته باشیم خروجی

[( n+2p-f)/s+1]*[( n+2p-f)/s+1]   می شود(اگر عدد رند نشد به سمت پایین گرد میکنیم)

parameter : پارامتری که در فرایند training مشخص می شود و تابع cost بر اساس آن بهینه می شود ( مانند وزن های شبکه)

Hyper parameter : پارامتری که با فرآیند training بدست نمی آید ( مانند k در k nearest neighbor، مقدار stride)

 

کانولوشن چند بعدی

در این نوع کانولوشن باید بعد هم عمق با ورودی باشد یعنی اگر ورودی 6*6*3(یک عکس RGB 6*6) باشد، فیلتر میتواند 3*3*3 باشد.

 

 

* نکته: در این مثال از یک فیلتر استفاده کردیم پس بعد سوم خروجی 1 است یعنی خروجی 1*4*4 است (بعد خروجی = تعداد فیلتر استفاده شده)

* نکته: مقادیر مرکزی کانولوشن هر بعد با هم جمع می شود و bias نیز به آن اضافه می شود

** مثال: با 10 فیلتر 3*3*3 تعداد پارامتر آن لایه چقدر می شود؟   ((3*3*3)+1)*10 = 280

 

** مثال:


در شبکه های عصبی کانولوشنالی از لایه های conv  و pool  به شکل زیر استفاده میکنیم :

همان طور که مشاهده می کنید قبل از اولین لایه Dense یا fully connected همیشه از متد flatten استفاده میشود تا نرون ها به صورت یک وکتور در بیایند.

در لایه آخر نیز اگر خروجی مدل ما باینری باشد میتوان از activation=sigmoidاستفاده کرد اما اگر خروجی مدل چند حالت مختلف باشد مثل مدل بالا که برای هدی هست و 10 تا خروجی دارد از softmax استفاده شده.

به ورودی و خروجی هر لایه نیز تنسور گفته می شود.

تصاویر مجموعه داده هدی در تابعی که قبلا نوشته ایم، load_hoda به صورت flat شده و یک وکتور در آمده اند.
در این فراخوانی طول و عرض تصاویر 28 قرار داده شده است، پس خروجی این تابع وکتورهای 784 تایی است.
دقت کنید که قبل از ورودی شبکه کانولوشنالی تصویر را به شکل اصلی خود یعنی 28×28 برگردانده ایم.
همچنین چون تصاویر سیاه و سفید است تعداد کانال تصویر را 1 قرار داده ایم.

 

با دستور ()model.summary ورودی و خروجی هر لایه را میبینیم :

همانطور که مشاهده میکنید با هر بار conv گرفتن پارامتر های جدیدی به دست می آید که میتوانند با تابع cost بهینه شوند.

لایه dropout هم هر بار تعدادی از نرون ها را میکشد برای جلوگیری از پدیده overfitting .

و با هر بار pooling همان طور که مشاهده میکنید پارامتری برای آموزش نمی دهد و تنها دو هایپر پارامتر s و f دارد و تنها ابعاد داده را کوچکتر میکند با ازبین بردن برخی جزییات از طرق ماکسیمم گیری،میانگین گیری و ….

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

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

Training loss: : تابع آموزش

Test loss;  :  تابع تست

روش جدید:

Overfitting : ایجاد شدن فاصله زیاد بین دیتا test و train . هنگامی که داده ها را حفظ میکند.

روش قدیمی:

Early stoping : قبل از کامل شدن نمودار و به آخر رسیدن آن،اگر در نقطه ای به نتیجه مطلوبی رسیده بودی در همان نقطه عملیات را متوقف کرده و بیش از آن train  نکنیم.

برای برطرف کردن مشکل over fitting راه کارهاییوجود دارد از جمله regularisasion

یکی ازاین روش هارا در اینجا میخوانیم :

Dropout

این مقاله توسط هینتون منتشر شده است. به این معناست که بصورت تصادفی به برخی (50درصد)از نورون ها(در فرایند training) شلیک میکنیم تا نتوانند فرایند خود را ادامه دهند و در فرایند بک پروبگیشن شرکت نمیکنند و در فرایند برگشت به روز نمی شوند.

در این روش با توجه به تصادفی بودن داده هایی که در فرایند شرکت میکنند، امکان حفظ شدن وجود ندارد پس مشکل overfitting  نیز حل میشود.

همیشه این طور نیست که این روش پرفورمنس را بطور حتمی افزایش دهد.

 

دستور استفاده از این روش:

model.add(Dropout(0.5))

عدد 0.5 احتمال زنده ماندن نورون هاست.اگر 1 بگذاریم هیچ نورونی را نمیکشد.

 

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

 

شبکه های کانوولوشنی:

این شبکه ها نیاز به دیتا های ورودی زیادی دارند که وزن زیادی نداشته باشند.

ورودی های آنها لازم نیست هم سایز باشند.

Locality: کنار هم بودن پیکسل ها

 

گوشه ای از قدرت شبکه های کانوولوشنی در اسلاید ها قرار داده شده است.

Object detection : تشخیص برخی آبجکت های درون عکس های مختلف توسط شبکه.

Image clastering: از بین مجموعه عکس ها عکس های شبیه را کنار هم قرار میدهد(میوه ها، حیوانات و …)

بعد از سال 2012 دیگر ا روش های قبلی کسی نتوانست به پرفورمنس بالا برسد و همه از روش کانوولوشنی استفاده کردند.

 

همه ی داده های ما لزوما کوچک نیستند و دیا های خیلی بزرگ هم داریم که train آنها بسیار زمان میبرد چون تعداد لایه های زیادی دارند و مجموع وزن آنها بسیار زیاد میشود.

 

مشکلات بینایی کامپیوتر:

پدینگ برای جلوگیری از موارد زیر است.

تعداد لایه های ورودی بسیار زیاد باشد و باعث شود خروجی کوچک شود و اینفورمیشین های زیادی loss شود.

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

مقدمه‌ای بر پیاده سازی شبکه‌های عصبی ترتیبی در کراس

تعریف یک مدل ساده روی دیتاست هدی (ادامه):

تا اینجا با نحوه لود کردن مجموعه داده در keras ، پیش پردازش داده ها، تعریف معماری مدل و طبقه بند چندلایه softmax آشنا شدیم.

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

Compile model :

Model.compile() :

در دستور compile تابع loss  معیار بد بودن شبکه را نشان می دهد و optimizer مشخص می کند چگونه باید آن را بهبود دهیم تا این معیار به مینیمم مقدار خود برسد.

کد:

model.compile (loss=’categorical_crossentropy,

optimizer=’rmsprop’

 metrics=[‘accuracy’])

در این قسمت یک مدل به دست می آید که ورودی، خروجی، معیار بد بودن و نحوه بهینه کردن آن مشخص شده است و از این پس منتظر data است تا بهینه کردن را آغاز کند.

با دستور fit این عملیات آغاز می شود.

نکته: دستور fit روی data های train صورت می گیرد.

آموش مدل با داده‌های آموزشی، تعیین سایز mini_batch و تعداد epoch:

Model.fit() :

x_train و y_train به عنوان پارامتر اول و پارامتر دوم به آن داده می شود.

epochs که به عنوان پارامتر سوم به آن داده شده است نشان می دهد شبکه باید چند بار data های موجود را مرور کند.

همچنین batch_size به عنوان پارامتر آخر مشخص می کند پس از دیدن چند data شروع به بهینه کردن مسئله کند.

برای مثال batch_size = 64 نشان می دهد به شصت و چهارمین data که برسد ، میانگین خطا ها را در نظر می گیرد و بر اساس این میانگین تابع را optimize می کند.

در فرمول C = Σ(y-a)2 / n  مقدار n  نشان دهنده ی batch_size است.

نکته: اعداد معروف batch_size (طبق گفته دکتر Andrew ng ،استاد دانشگاه استنفورد): 16 ، 32 ، 64 ، 128 ، 256 ، 512 و نهایتا 1024 است.

Batch_size یک hyper parameter است و بزرگ و کوچک بودن آن در فرآیند training تاثیر دارد.  همچنین این پارامتر روی سرعت همگرا شدن تاثیرگذار است. علاوه بر سرعت، هرچه سایز batch بزرگ تر باشد، نرمال سازی (batch_normalization)  بهتر است.

برای مثال اگر بخواهد هر کدام از data های هدی که می آید، شبکه را به روز کند دید کلی نسبت به شبکه ندارد. همچنین اگر بخواهد همه ی data ها را ببیند سپس بهینه ساری را انجام دهد، هزینه بالا می رود و سرعت پایین می آید بنابراین batch_size باید عددی بین یک و تعداد کل داده ها باشد که به آن mini_batch می گویند.

کد:

model.fit(x_train, y_train,

epochs=5,

( batch_size=64

وقتی کد را اجرا کنیم چون در کد های قبلی metric را accuracy تعریف کرده بودیم هر epoch که تمام می شود accuracy را اعلام می کند.

خروجی کد:

Epoch 1/5

1000/1000 [==============================] – 9s 9ms/step – loss: 0.2789 – acc: 0.9100

Epoch 2/5

1000/1000 [==============================] – 10s 10ms/step – loss: 0.2689 – acc: 0.9180

Epoch 3/5

1000/1000 [==============================] – 10s 10ms/step – loss: 0.2637 – acc: 0.9210

Epoch 4/5

1000/1000 [==============================] – 10s 10ms/step – loss: 0.2591 – acc: 0.9250

Epoch 5/5

1000/1000 [==============================] – 10s 10ms/step – loss: 0.2555 – acc: 0.9210

هرچه پایین تر می رود مقدار loss کمتر می شود. اگر بخواهیم loss کمتر و accuracy بیشتر شود می توانیم epoch را بیشتر کنیم.

ارزیابی مدل روی داده های آزمون:

در ارزیابی هم از accuracy استفاده می شود.

Model.evaluate() :

در دستور evaluate به جای x_train و y_train ، از x_test و y_test به عنوان پارامتر اول و دوم استفاده می شود.

خروجی این تابع یک tuple است که از loss و accuracy تشکیل شده و در واقع میزان loss و accuracy را در data های test نشان می دهد.

کد:

loss, acc = model.evaluate(x_test, y_test)

print(‘\nTesting loss: %.2f, acc: %.2f%%’%(loss, acc))

خروجی کد:

200/200 [==============================] – 0s 195us/step

Testing loss: 0.33, acc: 0.91%

پیش‌بینی داده‌های آموزشی: ( predicted class  )

از ابتدا تا اینجا یک مدل را به صورت sequential تعریف و معماری آن را مشخص کردیم، سپس روی آن بهینه سازی انجام دادیم و در آخر مدل را روی آن fit کردیم. حالا می توانیم روی همان مدل predicted class را صدا بزنیم.

data های test به عنوان پارامتر به predicted class داده می شود سپس predicted ها و true lable ها چاپ می شوند.

کد:

predicted_classes = model.predict_classes(x_test)

print(“predicted:”)

print(predicted_classes)

print(“True Label:”)

print(y_test_original)

خروجی کد:

predicted:

[7 2 3 8 5 5 4 7 3 2 0 8 8 0 2 9 3 6 7 4 0 3 6 3 9 2 7 5 2 9 2 5 5 8 9 2 5

1 4 8 8 4 2 2 1 2 7 9 0 3 7 2 7 5 2 9 8 2 9 8 8 6 6 6 7 6 2 4 2 4 4 5 9 1

8 4 0 5 6 2 4 3 2 7 7 7 7 1 8 1 7 8 7 7 8 9 7 2 3 1 0 2 9 6 3 5 5 0 0 9 6

7 9 3 9 9 8 7 9 2 5 2 5 5 9 6 9 2 0 3 7 9 5 2 9 0 4 1 8 2 2 3 5 2 9 3 8 2

7 0 9 9 0 7 6 7 4 0 9 3 7 0 7 4 9 4 7 3 4 1 5 6 7 9 1 3 5 4 5 7 4 1 3 3 1

1 4 3 8 9 6 7 7 2 3 0 1 4 9 5]

True Label:

[7 2 3 1 5 5 4 7 3 2 0 8 8 0 2 9 3 6 7 4 0 3 6 3 9 2 7 5 2 9 7 5 5 8 9 6 5

1 4 8 8 4 7 7 1 2 7 9 0 3 7 4 7 5 2 9 8 2 9 8 8 6 6 6 6 6 2 4 3 4 4 5 9 1

8 2 0 5 6 2 4 3 2 7 7 7 7 1 8 1 7 8 7 7 8 9 3 2 3 1 0 2 9 6 3 5 5 0 0 3 6

7 9 3 9 9 8 7 9 2 5 2 5 5 9 6 9 2 0 3 7 6 5 2 9 0 4 1 8 2 2 3 0 2 9 3 8 6

7 0 9 9 0 7 6 5 4 7 9 3 7 0 7 1 9 4 7 3 4 1 5 6 7 9 1 3 5 4 5 7 4 1 3 3 1

2 3 3 8 9 6 7 7 2 3 0 1 4 9 5]

نکته: یکی از روش های خوب machine learning این است که وقتی شبکه را train کردیم مشخص کنیم کدام data ها را اشتباه پیش بینی کرده است و سپس بر این اساس مدل را بهبود دهیم.

استفاده از مدل Train شده با Keras در پلتفرم های مختلف

سلام به دوستان عزیز، این آموزش تلاشی برای کاربردی کردن تمارین و مدل های ارائه شده در کلاس تحت پلتفرم های مختلف می باشد. در ادامه روند اجرای مدل تحت وب را با هم میبینیم و سپس شما هم با کمی تغییر در این پروسه می توانید یادگیری عمیق را به پلتفرم خودتان ببرید!

برای شروع، نیاز به ذخیره کردن مدل بعد از عملیات های compile و train می باشد، شما می توانید با استفاده از دستورات زیر به راحتی این کار را انجام دهید و یک فایل خروجی از مدل خود داشته باشید و یا از آن در برنامه ای دیگر استفاده کنید!

 

در مرحله بعد کافیست کمی در اینترنت جستجو کنید و کتابخانه مربوط به زبان برنامه نویسی خود و فریمورک کراس را بیابید، در ادامه ما از کتابخانه Keras.js استفاده خواهیم کرد.

آخرین لحظات در پایتون

لینک دانلود کتابخانه کراس جی اس در اینجا

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

جریان اجرایی پروژه

در مرحله اول، نیاز به رسم اعداد و دستخط افراد وجود دارد، اینکار به راحتی با قابلیت canvas در html صورت می پذیرد (توضیحات بیشتر در اینجا)

توابع رسم اعداد

 

توابع گرفتن خروجی عکس و ارسال آن به سرور

اما تصویر ارسال شده به سرور نیاز به کمی تغییرات در سایز (متناسب با مدل) و همچنین برش آن ها دارد. شما در ادامه تابع برش تصویر را میبینید.

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

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


منابع

KerasKeras.jsCanvasImageResizePhp

آشنایی با سرویس ابری Google Colab

محیط گوگل کولب امکان استفاده از GPU  را به صورت رایگان میدهد و امکان نصب و کار با پکیج های مختلف زبان پایتون و فریم ورکهای مطرح یادگیری عمیق همانند Tensorflow, Keras, Pytorch,Fast.ai را فراهم میکند.

مراحل ایجاد یک نوت بوک

ابتدا مطمئن شوید که به حساب کاربری gmail  خود متصل هستید . اگر حساب کاربری gmail ندارید اینجا را کلیک کنید.

* توجه :در تمام طول کار، باید  وی‌پی‌ان یا فیلترشکن روشن باشد.

از اینجا وارد محیط  google drive  شوید .

روش اول :

در محیط google drive   یک پوشه ایجاد کنید :

پوشه ای که ایجاد کرده ایم را انتخاب میکنیم

با کیلک راست بر روی  My drive فایل های نوت بوک وdataset.py    [Upload files] و

Data_hoda_full را آپلود میکنیم.

با کلیک راست بر روی نوت بوک مانند شکل زیر،نوت بوک را  با colaboratoryباز میکنیم :

بعد از باز شدن نوت بوک  GPU را فعال  میکنیم:

یک cell جدید ایجاد میکنیم :

کد زیر را در cell  وارد میکنیم :

بعد از run  شدن  cell دو مرحله تایید اعتبار داریم ، در هر مرحله بر رو لینک کلیک کنید و کد رو در تکست باکس وارد کنید :

کدهای زیر را به نوت بوک اضافه میکنیم تا فایل ها از گوگل درایو به محیط colab  اضافه شوند :

add cell+

add cell +

حالا  یک دایرکتوری برای دیتاست ایجاد میکنیم :

add cell+

دیتاست هدی را به پوشه ی دیتاست اضافه میکنیم :

add cell+

روش دوم ایجاد نوت بوک :

وارد سایت colab.research.google.com میشویم :

NEW NOTEBOOK >>> NEW PYTHON3 NOTEBOOK

سپس از منو file  نوت بوک جدید را آپلود میکنیم :

یک cell  جدید  ایجاد میکنیم سپس دستور زیر را وارد میکنیم  :

فایل و پوشه ی دیتاست را آپلود میکنیم :

add cell+

دیتاست هدی را به پوشه ی دیتاست اضافه میکنیم :

add cell+

روش سوم :

ابتدا ریپازیتوری خود را با دیتاست موردنظر و دلخواه روی گیت هاب ایجاد کنید

یا در صورت وجود ریپازیتوری آدرس آن را به صورت زیر یافته و با دستور زیر آن را در جوپیتر ران کنید

*توجه داشته باشید که فرمت دستورات لینوکسی میباشد.

مثال :

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

در ادامه مسیر جاری را پیدا کرده و فایل های دریافت شده از مخزن را در مسیر دلخواه ( بعنوان مثال /content ) منتقل کنید:

در نهایت کد های اجرایی مورد نظر را در یک سلول جدید وارد کرده و برنامه را اجرا کنید:

بروزرسانی : 1397/11/06