مقدمه ای بر deep learning

مقدمه ای بر deep learning :

Image classification :

یکی از مبانی پایه در computer vision بحث classification اشیا و تصاویر است که تشخیص می دهد تصویری که به کامپیوتر داده شده چیست. (برای مثال  مشخص می کند تصویر گربه است یا نه)

چالش ها:

در واقع یک طیف پیوسته ای برای هر شی وجود دارد. برای مثال در گربه بین هر دو پیکسلی که ما می بینیم n پیکسل دیگر وجود دارد. همچنین رنگ ها هم طیف پیوسته ای دارند که برای کد کردن مجبوریم آن ها را در یک کانال( RGB (red, green, blue کد کنیم و عدد آن بسته به کامپیوتر و پیاده سازی ای که انجام می دهیم از 0 تا 255 متغیر است. بنابراین در این مرحله تعدادی از اطلاعات برای تبدیل از دنیای واقعی به محیط کامپیوتر که به آن semantic gap می گویند، از دست می رود.

 

چالش های دیگری هم وجود دارد. برای مثال الگوریتم (KNN (k-nearest neighbor  در دیتاست هدی performance خیلی خوبی داشت ولی در دنیای واقعی این گونه نیست و یک سری مشکلات ممکن است رخ دهد، مانند viewpoint validation ها به این معنی که اجسام را می توان از زاویه های مختلف دید و به همین دلیل الگوریتم KNN پاسخ گو  نیست.

Illumination :

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

Deformation :

انسان قادر است اجسام را در هر حالت که باشند تشخیص دهد اما هدف این است که در computer vision هم این تشخیص به درستی صورت گیرد.

Occlusion :

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

Background clutter :

اگر جسم در background محو شده باشد باز هم الگوریتم پیاده سازی شده باید بتواند آن را تشخیص دهد.

Intraclass variation :

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

Image classifier :

حالا باید مشخص کنیم چه الگوریتمی بهتر است تا این چالش ها برطرف شوند:

def predict(image):

     return class_label

ابتدا تابع predict تعریف می شود که یک عکس می گیرد و class_label ها را برمی گرداند.

بر خلاف sort کردن اعداد یا ماکزیمم گیری هیچ راه روشن و سریعی برای این گونه کلاس ها وجود ندارد و مجبوریم با راه حل های data-driven پیش برویم.

 

Data-driven approach :

ابتدا باید یک سری data و یک تابع train وجود داشته باشد که label ها به آن پاس داده می شوند. سپس بسته به نوع الگوریتم، طی یک فرآیند یادگیری یک مدل ساخته می شود که باید آن را ذخیره کنیم. بنابراین دفعه های بعد که عکس جدیدی به آن داده می شود می توان از یک تابع جدید به نام predict استفاده کرد که model و test_image به آن پاس داده می شود و دیگر نیازی به label نیست.

کد:

def train(train_images, train_labels):

    return model

def predict(model, test_images):

    return test_labels

K_Nearest Neighbor :

در دنیای واقعی این الگوریتم جواب نمی دهد، برای مثال اگر صورت فرد سانسور شده باشد یا در شرایط نوری متفاوت قرار بگیرد نمی توان از این الگوریتم استفاده کرد.

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

Neural network و deep learning

History :

از سال 2012 تا کنون deep learning روال رو به رشد چشمگیری داشته است.

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

 

 

 

 

دکتر Andrew ng ، استاد دانشگاه استنفورد، در 5 نوامبر 2017 در کنفرانس خود اعلام کرد تعداد مقالات در بحث deep learning بیش از حد زیاد شده اما با فقدان نیروی متخصص مواجه هستیم و طبق پیش بینی او یک انفجار در شغل های مربوط به deep learning و  neural networkایجاد می شود بنابراین وجود نیروی متخصص بیش از پیش ضروری است.

همچنین Andrej Karpathy ، مدیر هوش مصنوعی شرکت تسلا، در وبلاگ medium خود گفته است deep learning  و neural network نرم افزار ها را دچار تغییر و تحول زیادی می کند. (software2.0 )

 

Neural network کجا استفاده می شود؟

این شبکه ها در دیدن، شنیدن، خواندن متن و استنتاج آن (مانند dictionary translation ها) کاربرد دارند. همچنین برای کنترل کردن (برای مثال انجام بازی کامپیوتری) هم استفاده می شوند.

Neural network ها شبیه logo block یا building block هایی هستند که neural network practitioner (سازنده ی neural network ) می تواند از آن ها استفاده کند.

می توانیم هر شبکه ای که شناخته شده است را یک building block در نظر بگیریم و مشابه کار Andrej Karpathy این شبکه ها را به هم وصل کنیم. برای مثال یک شبکه داریم که image را به خوبی تشخیص می دهد و همچنین یک شبکه داریم که متن را خوب می فهمد. می توان این دو شبکه را پشت سر هم وصل کرد (اتصال یک شبکه CNN و یک سری شبکه RNN (این نوع شبکه برای dictionary ها استفاده می شود.))

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

ساده ترین neural network که در نظر گرفته شده neural network یک لایه است. (softmax )

برای مثال یک عکس 2 * 2 را در نظر بگیرید، اگر آن را starch کنیم 4 پیکسل به وجود می آید. فرض کنید سه کلاس خروجی داریم که به طور مثال مشخص می کند تصویر داده شده گربه، سگ و یا گوسفند است یعنی یک ماتریس 4 * 3 داریم. اگر این ماتریس 4 * 3 در یک ماتریس 1 * 4 ضرب شود 3 عدد برمی گرداندکه می تواند مشخص کند در آخر کدام کلاس انتخاب شده است. یک راه ساده تر این است که سطر اول را وزن های مربوط به کلاس cat ، سطر دوم را وزن های مربوط به کلاس dog و سطر سوم را وزن های مربوط به کلاس sheep در نظر بگیریم که به اضافه ی bios می شودد. Bios را می توان به حوزه ی 0 و 1 انتقال داد که این کار با softmax انجام می شود.

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

ارقام دست نویس هدی: (اعدادی که در کنکور سراسری بالای دفترچه به صورت دست نویس نوشته می شود.)

در واقع این ارقام ابتدا normalize شده، سپس background آن ها عوض و بعد از آن با روش های مناسب باینری شده است.

شبکه Dense :

شبکه ای است که در لایه ی اول خود 25 نورون دارد (چون عکس 5 * 5 است) و در لایه ی آخر چون 10 کلاس داریم 10 نورون

قرار می گیرد که از 0 تا 9 مشخص می شوند.

تعداد نورون های لایه ی وسط را باید خودمان مشخص کنیم که با چند نورون به performance بهتری می رسد.

در این نوع شبکه همه ی نورون ها به یکدیگر وصل می شوند که به آن fully connected یا همان dense می گویند.

روی هر کدام از این نورون ها یک تابع activation اعمال می شود که relu برای این کار مناسب است.

کد:

Model=Sequential()

Model.add(Dense(64, activation=’relu’, input_dim=25))

Model.add(Dense(10, activation=’softmax’))

نمودار  relu

فرمول softmax :

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

کد:

Model.compile(loss=’categorical_crossentropy’ , optimizer=’rmsprop’ , metrics= [‘accuracy’])

همانطور که پیش تر گفته شد با model.compile میزان loss مشخص می شود. معیار loss مقدار بد بودن شبکه را مشخصمی کند.

rmsprop  روش بهینه سازی است که نشان می دهد به ازای هر data چقدر با چیزی که می خواهیم شبکه predict کند فاصله داریم.

روش های دیگری نیز برای بهینه کردن وجود دارد مانند sgd ، momentum ، nag ، adagrad و … . در نهایت همه ی این روش ها شبکه را بهینه می کنند اما زمان بهینه کردن هم اهمیت زیادی دارد.

تطبیق و بازشناسی چهره(2)

رویکرد دیگر در سال 2014 به این صورت بود که تشخیص چهره را به صورت کلاس بندی باینری ببینیم اینگونه که دو عکس مورد بررسی را به شبکه بده و در انتها لایه 128 را وصل کن به یک binary classifier که اگه دو نفر یکسان بودند true و در غیر این صورت،  false برمیگرداند.

دیتا ست در این رویکرد به صورت زیر است که یه مجموعه مقایسه ایست که یکسان بودن و نبودن را بیان می کنند و batch هم ظریب 2 می شود.

باز میبینیم که تعدادحالت های ما بسیار زیاد می شود.

Center loss

برای تصویر تنها تفکیک پذیر(separable) بودن مهم نیست بلکه باید یک فاصله ایی هم در فضا از هم داشته باشند.( discriminative باشند)

فیچر های ماقبل لایه آخر (encoding) درهر mini_batch ، این 128 ها را میانگین بگیرد و  loss  را طوری تعریف می کنیم که علاوه بر softmax همه به سنترمشخص شده نزدیک تر بشن.

separable
separable
discriminative
discriminative

 

 

 

کانال عکس ابتدا وارد می شود.

 

یک شبکه را لود کردیم با پارامتر های تعداد کانال و سایز عکس ها که 96 * 96 است.

 

در کامپایل پارامتر loss را تابعی که خودمان برای loss triplet نوشتیه ایم میگذاریم.

وزن های قبلا train شده را در شبکه خودمون لود میکنیم.

عکس را داده و خروجی 128 تایی لایه آخر شبکه را در یک دیکشنری ذخیره میکنیم.

تابعی که عکس را گرفته و فاصله اقلیدسی آن را با عکس های موجود در دیتاست محاسبه کرده (threshold که براساس تست یافته ایم، cross validtion باید بزنیم تا بهترین کارایی برسیم.)و می گوید این عکس داده شده همان لیبل هست یا نه. true و false برگردان.

پارامتر ها:

  • عکس
  • لیبل عکس
  • دیتاست
  • مدل شبکه

تابعی که عکس را گرفته و recognation انجام می دهد، به این صورت که encoding عکس را از مدل گرفته و در تمام دیتاست موجود چک می شود اگر فاصله اقلیدسی آن از min_dist کوچکتر باشد نام آن را بر می گرداند.

 

تطبیق و بازشناسی چهره (1)

جلسه بیستم – Face

برای شروع این مبحث ابتدا لازم تا با مفاهیم Face Verification و Face Recognition آشنا شویم. در مسائل Face Verification ما با دو تصویر سر و کار داریم و باید شبکه ای داشته باشیم که بتواند تشخیص بدهد آیا این عکس ها متعلق به دو فرد مختلف هستند یا خیر. یعنی مسائل Face Verification نوعی از مسائل binary هستند. اما در مسائل Face Recognition دیتابیسی شامل تصاویری از افراد متفاوت داریم و مدل باید تشخیص دهد که عکس ورودی جدید متعلق به کدام یک از این افراد است. هر مساله Face Verification را می توان به n مساله Face Recognition شکست؛ به این صورت که عکس جدید را با تصویر هر کدام از افراد موجود در دیتابیس بررسی کنیم و ببینیم که آیا این دو تصویر متعلق به یک فرد هستند یا خیر.

مفهوم دیگری که در ابتدا لازم است با آن آشنا شویم One Shot Learning است. اگر می خواستیم مساله Face Recognition را با روش های قدیمی حل کنیم، باید تعداد زیادی تصویر از افراد مختلف (مثلا 20 نفر) جمع آوری کنیم و سپس شبکه ای train کنیم که لایه آخر آن یک softmax با 20 نورون باشد. اما این رویکرد در حل مسائل واقعی عملی نیست؛ چون برای اضافه کردن یک فرد جدید، نیاز است تا ساختار شبکه (لایه آخر) را تغییر دهیم و شبکه را مجددا train کنیم. هم چنین ممکن است گاهی نیاز به اضافه کردن فردی به دیتابیس داشته باشیم که تعداد زیادی عکس از او در دسترس نباشد. در این جا نیاز به One Shot Learning داریم. هدف One Shot Learning این است که تنها با یک عکس از هر گروه، بتوانیم شبکه را train کنیم.

(اخیرا مبحثی به نام Zero Shot Learning نیز مطرح شده که در آن برای اضافه کردن یک کلاس به شبکه می توان از عکس جدیدی استفاده نکرد و به جای آن کلاس جدید با توجه به کلاس های قبلی که شبکه یاد گرفته توصیف می شود. هم چنین مفهوم دیگری به نام Low Shot Learning هم مطرح است که در آن از هر کلاس تعداد کمی عکس – مثلا 2 یا 3 تصویر – داریم.)

در مبحث Feature Extraction دیدیم که شبکه های کانولوشنال می توانند از تصاویر Separable Features استخراج کنند که با یک خط از هم تفکیک شوند. اما اگر بخواهیم برای این feature ها یک classifier با KNN داشته باشیم ممکن است به نتیجه خوبی نرسیم. (در شکل زیر نزدیک ترین همسایه به نقطه قرمز درون مربع زرد، نقطه سبز است.) برای همین گاهی لازم است به Discriminative Features داریم؛ یعنی feature ها علاوه بر قابل تفکیک بودن با یک خط، باید از هم فاصله داشته باشند.

رویکرد ما در این مسائل این است که به جای یاد دادن هر فرد به مدل، یک تابع شباهت یا similarity function به مدل یاد بدهیم که به آن اصطلاحا parameter learning گفته می شود. در این نوع از learning از هر عکس یک encoding یا embedding استخراج می کنیم و سپس با تعریف معیار فاصله، سعی می کنیم تا به شرایطی برسیم که فاصله دو عکس متفاوت از دو فرد یکسان عدد کوچک و فاصله دو عکس از فرد متفاوت عدد بزرگی به ما بدهد. با شبکه هایی که تا کنون نوشته ایم هم می توانیم تا حدی به این هدف دست پیدا کنیم. به این صورت که لایه softmax را دور ریخته و فاصله لایه های قبل از آخر را با یکدیگر حساب کنیم. در این صورت احتمالا برای افراد درون training set به performance خوبی هم می رسیم؛ اما شبکه generalize نیست و برای افرادی که در training set نباشند نتیجه خوبی نخواهد داشت. (شبکه های Siamese)

پس به طور کلی در پارامتر لرنینگ هدف این است که از هر تصویر یک encoding استخراج کنیم؛ به طوری که داشته باشیم:

بنابراین نیاز است تا cost function ای پیدا کنیم که به ما برای رسیدن به این هدف کمک کند. از انواع cost function هایی که برای این منظور طراحی شده Triplet loss است که در سال ۲۰۱۵ و توسط گوگل معرفی شد. برای استفاده از این cost function لازم است تا batch size مضربی از ۳ باشد. سه عکسی که به شبکه داده می شوند Anchor، Positive (عکس دیگری از Anchor) و Negative (عکسی از فرد دیگری) نام دارند و می خواهیم داشته باشیم:

این فرمول یک ایراد دارد و آن این است که اگر f مستقل از ورودی رفتار کند و به ازای هر ورودی دقیقا یک خروجی یکسان بدهد (مثلا 0) این شرایط همیشه برقرار است. برای حل این مشکل و همچنین برای رسیدن به Discriminative Features به فرمول فوق margin اضافه می کنیم. در نتیجه با این فرمول فاصله دو فرد متفاوت حداقل باید به اندازه آلفا باشد.

اما از این نامساوی نمی توان برای محاسبه loss function استفاده کرد. برای این که این عبارت را به یک فرمول تبدیل کنیم داریم:

با توجه به این فرمول، اگر cost function برابر 0 باشد، به هدف رسیده ایم. اما اگر cost function بزرگ تر از صفر باشد لازم است تلاش کنیم تا آن را کوچک تر کنیم. (بهینه سازی)

نکته قابل تامل این است که این روش نیاز به تعداد تصاویر زیادی دارد؛ درنتیجه تعداد مجموعه عکس های سه تایی ای که می توانیم انتخاب کنیم خیلی زیاد است. اما برای درصد بالایی از آن ها loss function در همان ابتدا یا پس از اولین epoch صفر است. طی کردن کل پروسه train برای تصاویر با cost function برابر 0 هیچ تاثیری در وزن های شبکه ندارد و تنها زمان بر است. پس لازم است گزینه های چالشی تر برای train انتخاب شوند. استفاده از عکس های دوقلوها، گریم های سنگین و … می توانند باعث بهبود عملکرد شبکه شوند.

Transfer learning

ما برای کانولوشن ها (CNN) نیاز به میلیون ها دیتا داریم. البته براساس Transfer learning
ما می توانیم از مدل آموزش دیده ی شخص دیگری که مدلش را بر روی دیتاهای بسیار آموزش داده است استفاده کنیم به طوری که نیازی نباشد تا برای آموزش شبکه کانولوشن خودمان ملیون ها دیتا را بررسی و تحلیل کنیم. به عنوان مثال در تصویر زیر برای تشخیص گربه ایرانی از گربه ی خیابانی و یا هرچیز دیگری:

اگر یکی از مدل های آموزش دیده شده ایمیجنت را به صورت بالا انتخاب کنیم. این مدل لایه ایی قابلیت تشخیص اجزای مختلفی از اشیاء مختلفی را دارد به صورتی که هر لایه برای تشخیص جزئی از شی آموزش داده شده است و لایه آخر هم یک کلاسیفایر است که میتوانیم در کاربردهای مختلف آنرا حذف کنیم و یک softmax جدید بجای آن قرار دهیم. که در اینجا ما برای تشخیص گربه ایرانی از گربه ی خیابانی و یا هرچیزی غیر از گربه می توانیم لای آخر را حذف کنیم و یک softmax جدید سه کلاسه (برای تشخیص گربه ایرانی، خیابانی و هرچیز دیگری) بجای آن قرار دهیم.
و یا به صورت زیر:

در این حالت به جای اینکه به این فکر کنم که چه مشخصه هایی از تصویری که به مدل داده ام را استخراج کنم، عکس را به مدل آموزش دیده ی یک شخص دیگری می دهیم بعد مشخصه های لایه های ماقبل آخر را از مدل میگیرم به عنوان مثال لایه ماقبل آخر Alexnet ، 4096 تا است که به عنوان مشخصه های تصویر از مدل Alexnet میگیریم.
حال در مدل freeze شده لایه های سمت چپ لبه ها را تشخیص می دهند و هرچه از سمت چپ به سمت راست حرکت میکنیم لایه های مشهودتری مثل گوش گربه را به خوبی تشخیص می دهد.
اگر با مسئله جدیدی برخوردیم مثلا دو آبجکت را در نظر بگیریم که در دیتاست ما، دیتاهای کمی از آنها وجود دارد. برای بهینه تر کردن مدل ما به صورت زیر:

نه تنها softmax بلکه چندین لایه ی اضافه ی دیگری را از سمت راست حذف میکنیم. تعداد لایه هایی که می توانیم در مدل حذف کنیم بستگی به مقدار دیتایی دارد که از آن آبجکت داریم هرچه دیتای بیشتری داشته باشیم میتوانیم لاهای بیشتری را حذف کنیم، همانطور که در تصویر زیر مشخص است:

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

اکنون در قالب یک مثال عملی میخواهیم چند عکس از یک گربه بگیریم و این تصاویر را به یک کلاسیفایر معرفی کنیم و برنامه ایی بنویسیم که تمام کامپیوتر را بگردد و آدرس تصاویر مربوط به گربه ی مشخص شده را برگرداند:

از کراس مدل ذخیره شده مان را لود میکنیم البته قبل از این باید با دستور pipe h5 py را نصب کنیم. بعد از این باید یک سری پرپروسسینگ به صورت زیر روی تصویر انجام بدهیم. کتابخانه های مورد نیاز را ایمپورت میکنیم:

نکته : عبارت %matplotlib inline یک کلمه ی کلیدی در jupyter notebook است(یعنی در محیط برنامه نویسی پایتون نمی توان از آن استفاده کرد) که اگر از نوشتن آن صرف نظر کنیم تا ۹۰ درصد امکان عدم نمایش خروجی در نوتبوک را دارد لذا بهتر است از آن استفاده کنیم.
در ادامه تصویر مورد نظر را وارد میکنیم تصویر را از testset ایمپورت میکنیم testset جایی است که در فرآیند training شرکت نداشته است.

پارامتر target_size را به اندازه شبکه ایی که قبلا تعریف کرده یم قرار میدهیم که در اینجا چون اندازه شبکه را قبلا ۱۵۰ در ۱۵۰ تعریف کرده ایم لذا از همین اندازه استفاده میکنیم.
بعد از نمایش تصویر آنرا بر ۲۵۵ تقسیم میکنیم تا نرمال شود.
بعد از اجرا خروجی به صورت زیر خواهد بود:

که مقدار model.predict و model.predict_classes در بالای تصویر هست. که مقدار model.predict_classes خروجی sigmoid در شبکه کانوشوال است.
نکته: خروجی Sigmid مقداری بین صفر و یک را برمیگرداند که هرچه به صفر نزدیکتر باشد با احتمال قوی تری می گوید که تصویر گربه است و هرچه به یک نزدیک باشد بلعکس خواهد بود و اگر مدل نتواند تصوری را تشخیص دهد مقداری در حدود نیم خواهد داد.

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

و فضای نورونی جدیدی را به صورت زیر داریم:

در بخش اول کد با include_top=false همه ی fully connectedها را دور میریزم. با input_shape=(150, 150, 3) ابعاد عکس را تعیین میکنیم که به ترتیب طول و عرض و convolutionاست . در این جا وزن ها را روی چالش ‘imagenet’ تنظیم کردیم .

conv_base.summary():(VGG)summary هست ولی با (150, 150, 3) تنظیم شده است و با pollingهم به اتمام رسیده است. در توضیح Non-trainable هم وقتی freeze نکرده باشیم قاعدتا Non-trainable هم نداریم . بیشتر بودن وزن include_top نیز به خاطر fully connected میباشد.

base_dirمسیری هست که دیتای تمیز شده در آن موجود میباشد. extract_features هم عکس ها را Fitمیکند به شبکه وبعد featureها را برمیدارد و در numpy arrayذخیره میکند . featuresخود به این معنی است که تعدادی عکس با این dimensional میخواهیم و موقتا با صفر پرشده است . در generatorچون بحث در کلاس است به صورت binaryمیباشد .

inputs_batch در این جا 20 تا (3* 150* 150)داریم و features_batch20تا 512*4*4است. آرایه های labelsو featuresقرار است تا ماتریس های 2000تایی رو پر بکند. Featuresدر این جا لایه آخر convolutionاست. این جا خروجی قرار است با train_features, train_labelsباشد که در train_labels خروجی 1*2000 داریم.

در قطعه کد بالا reshapeها کار floatکردن را مثل دیتاست هدی انجام میدهد.ما در این جا برای trainکردن یک classifierداریم . در این جا ayers.Dropout(0.5) برای overfitنشدن هست(به این منظور که یکسان زیاد میبینیم)که راه دیگر data augmentation هست . activation=’sigmoid’ است چون کلا در این جا دو کلاسه هستیم . ما به جای generator،model.fit داریم چون از دایرکتوری چیزی را نمیخواند . حال این سوال مطرح میشود که چرا data augmentation مفید نمیباشد؟
باید بگوییم این جا 30 تا epoch 2000 تایی داریم وبا numpy array یک بار این 2000 تا عکس را trainمیکنیم نه 30 بار! ولی در augmentation چون نمیتوانیم reuseکنیم و عکس جدید میخواهد مفید نیست!

مشکل بیش برازش داده‌ها و معرفی 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