معرفی BERT، تحولی در NLP

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

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

این جا بود که استفاده از مدل های pre-trained به کمک افرادی آمد که از دیتا و قدرت پردازشی محدودی برخوردار بودند. شبکه هایی که با دیتای مسابقه Image Netآموزش داده شده اند، در اختیار همه قرار دارد و دیگر نیازی نیست که تمام مسیر را از اول طی کنیم. کافیست که یک شبکه را بر داریم و با استفاده از دو روش feature extraction و fine-tuning برای کار خودمان اختصاصی کنیم.

ولی اگر مسأله ما به تصویر مربوط نباشد چه؟ دیتای به این عظیمی برای متن را از کجا بیاوریم؟ چگونه شبکه را آموزش دهیم؟

برای استفاده از مدل های pre-trained در مسائلی که با متن سر و کار دارند، ابتدا به سراغ word embedding ها رفتیم. به ما کمک کردند و تغییر محسوسی در دقت شبکه ها ایجاد کردند. ولی اصلا عمیق نبودند و حاوی اطلاعات کمی بودند. کمک آن ها موثر ولی محدود بود.

در سال ۲۰۱۸ این مسیر برای مسأله های متنی یا به طور دقیق‌تر NLP نیز در دسترس قرار گرفت. شبکه بزرگی با دیتای زیاد (Wikipedia + BookCorpus) توسط مهندسان گوگل آموزش داده شد و در دسترس همه قرار گرفت. حالا یک شبکه بسیار قدرتمند برای بهره گیری در مسائل متنی در اختیار داریم. این شبکه Bidirectional Encoder Representations from Transformers یا BERT نام دارد. ادامه خواندن معرفی BERT، تحولی در NLP

آموزش مقدماتی تنسورفلو

آمار در github :

تا 30 سپتامبر سال 2018 تنسرفلو با 111k استار و 68k فورک در رده اول قرار داشته است و این نشان می دهد استقبال از این کتابخانه بسیار زیاد است. یکی از دلایل استفاده از آن، این است که تنسرفلو کتابخانه ای است که برای deployment بسیار مناسب است. همچنین export اندروید و ios در آن بسیار راحت است. تنسرفلو برای محصول عملی و pytorch برای تست و مقاله دادن به کار می رود.

 

 

 

 

آمار جست و جو در گوگل:

 

 

 

 

این نمودار نشان می دهد میزان سرچ تنسرفلو روز به روز در حال افزایش است. دو کتابخانه ای که در رده ی دوم و سوم قرار دارند کراس و pytorch است.

مبانی تنسرفلو:

تنسرفلو فریم ورک یادگیری ژرف گوگل است که در نوامبر سال 2015 به صورت متن باز منتشر شده است. تنسرفلو می تواند عملیات محاسباتی بهینه و مشتق گیری را حساب کند، همچنین گرادیان گراف را به صورت اتوماتیک محاسبه می کند.

تنسور:

یک آرایه ی n بعدی را به اصطلاح tensor می گویند.

 

 

 

 

 

گراف جریان داده:

تنسرفلو برای این که بتواند توزیع پذیری داشته باشد و performance را بالا ببرد مدل برنامه نویسی graph base را ارائه داده و محاسبات را از اجرا جدا کرده است.

مثال: با توجه به شکل زیر دو نود برای input ، یک نود برای mul و یک نود برای add داریم. خروجی نود mul و add می توانند به یک نود add دیگر بروند. حالا می توانیم به input ها عدد بدهیم و خروجی را ببینیم.

 

 

 

 

گام اول: تعریف یک گراف محاسباتی (در این گراف هیچ عددی وجود ندارد)

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

مثال:

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

 

 

 

نکته: اگر به صورت صریح رئوس گراف محاسباتی را نام‌گذاری نکنید، تنسورفلو به صورت خودکار به آن‌ها نام نسبت می‌دهد. برای مثال در این جا به نود ها نام های x و y داده شده است.

هر زمان که به آن session اختصاص داده شود به x عدد 2 و به y عدد 3 را می دهد و خروجی 5 تولید می شود.

برنامه ساده استفاده از numpy :

 

 

 

 

بازنویسی با tensorflow :

()Tf.InteractiveSession : برای ساخت session است. می توانیم به آن ورودی دهیم و مشخص کنیم از چه مقدار از gpu استفاده کند. در صورتی که ورودی به آن داده نشود از کل gpu موجود استفاده می کند.

InteractiveSession سشنی است که در محیط های jupyter notebook و محیط هایی که تعاملی است استفاده می شود ولی چون overhead آن زیاد است برای deployment استفاده نمی شود و در آنجا session معمولی کاربرد دارد.

به جای np.zeros و np.ones ، tf.zeros و tf.ones قرار گرفته ولی سینتکس آن تغییری نکرده است.

به جای sum از tf.reduce_sum استفاده شده است (تاکید می کند که dimention در حال کوچک شدن است) همچنین به جای axis از reduction_indices استفاده می شود.

Eval : معمولا وقتی interactivesession داریم از eval استفاده می شود. eval سشن فعالی که وجود دارد را پیدا کرده و آن را اجرا می کند. چون eval را صدا زدیم آرایه ی [2. , 2.] را برمی گرداند و مشخص می کند datatype آن float32 است.

()Get_shape : یک TensorShape برمی گرداند که مثل tupple ها در پایتون رفتار می کنند.

سپس reshape شده و eval دوباره صدا زده می شود تا گراف اجرا شود.

مقایسه استفاده از numpy و tensorflow :

 

 

 

 

 

 

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

با فرض این که یک session فعال ساخته شده باشد اگر eval صدا زده شود ta اجرا می شود.

یک شیء session  محیطی که در آن اشیاء تنسور ارزیابی می شوند را کپسوله‌سازی می‌کند. یعنی بعد از ساختن گراف یک session می سازیم که این session اجازه می دهد اشیا داخل آن اجرا و evaluate شوند.

مثال:

Tf.constant یک عدد constant تعریف می کند. در این مثال از with block برای ساخت session استفاده شده که اصطلاحا به آن contex manager گفته می شود. وقتی یک session ساخته می شود باید حتما آن را  close کنیم اما وقتی از contex manager استفاده می شود بعد از خارج شدن از tab ، session خود به خود بسته می شود. برای اجرا شدن session از دستور sess.run استفاده شده که همان کار eval را انجام می دهد.

گراف که ساخته می شود چیزی مانند شکل زیر است:

 

 

 

 

 

 

 

 

بعد از این که session به آن اختصاص داده شد سخت افزار را در اختیار می گیرد و بعد از آن اصطلاحا عمل feed و fetch انجام می شود. جایی که input را می دهیم اصطلاحا به شبکه feed می شود و هر خروجی که بخواهیم را fetch می کنیم.

هر session منابعی را در اختیار می گیرد که gpu ، cpu و ram از مهم ترین آن هاست. این منابع پس از استفاده باید حتما آزاد شوند. همچنین می توانیم مشخص کنیم که هر session چه مقدار از این منابع را می تواند استفاده کند.

 

 

 

 

یک سینتکس دیگر این است که می توان از contex manager استفاده کرد. به این صورت که دستورات داخل indent نوشته می شود و هر وقت تمام شد خودش session را می بندد.

 

 

 

 

همچنین می توان از InteractiveSession استفاده کرد که فقط برای notebook کاربرد دارد.

 

 

 

مثال:

هر عملیاتی که تعریف می کنیم یک نود در گراف ساخته می شود.

(x=tf.constant(2 و y=3 از لحاظ سینتکس هیچ فرقی باهم ندارند.

 

 

 

مثال:

چون خروجی خواسته شده op3 است که برابر با op2 به توان op1 است، نودی که به اسم useless نامگذاری شده در اجرا در نظر گرفته نمی شود و ارزیابی نمی شود بنابراین سربار اجرایی ندارد.

 

 

 

 

اگر به session.run یک لیست داده شود یک tupple برگردانده می شود.

بنابراین در این مثال نود useless هم نیاز به ارزیابی دارد.

Variable ها در تنسورفلو:

برای چیزی که معمولا قرار است train شود از variable ها استفاده می شود. هنگامی که مدل را آموزش می دهیم برای نگه داری پارامتر ها نیاز به تعریف متغیر داریم.  یعنی معمولا trainable هستند.

در ساختن شبکه عصبی و شبکه کانولوشنی نیاز به variable داریم که بتوان مقادیر آن را عوض کرد.

نکته: Weight و bios ها variable در نظر گرفته می شوند.

Varaiable ها در مواردی به کار می روند که نیاز به به روز رسانی متغیر باشد.

استفاده از کراس در تنسرفلو:

با دستور tf.keras میتوان بدون نصب کردن keras ، در محیط تنسورفلو به آن دسترسی داشت. کراس در محیط تنسورفلو function های بیشتری نیز دارد. برای مثال اگر بخواهیم چند ورودی و چند خروجی داشته باشیم یا از چند سرور ورودی بگیریم یا بخواهیم شبکه را به صورت multi gpu فیت کنیم می توانیم از api تنسورفلو به نام dataset استفاده کنیم.

مثال:

W1 یک contant است.

W2 یک variable است. (یک ماتریس 2 در 2 که از صفر پر شده)

اگر بخواهیم از variable ها استفاده کنیم حتما باید ابتدا آن ها را initialize کنیم. با دستور tf.initialize_all_variables() تمام variable هایی که تعریف کردیم initialize می شوند.

مقایسه variable و constant :

variable را می توان با ثابت ها (“name=”weights) یا مقادیر تصادفی (“name=”random_weights) مقداردهی اولیه کرد.

با نوشتن tf.global_variables_initializer تمام متغیر ها با مقادیر از قبل مشخص شده مقداردهی اولیه می شوند.

به روز رسانی یک متغیر:

در ابتدا یک state تعریف شده که مقدار اولیه آن صفر است.

یک متغیر به نام new_value تعریف شده که مجموع یک تنسور که داخل آن یک قرار دارد و تغییر نمی کند با state است. این متغیر معادل  new_value = state + 1 است.

در داخل update یک tf.assign تعریف شده که مقدار تنسور new_value را داخل state می ریزد و معادل state = new_value است.

سپس برای اجرا شدن operation های ساخته شده یک session ایجاد می شود.

با اجرای قطعه کد sess.run(tf.global_variables_initializer())  یک state با مقدار صفر ساخته می شود.

داخل فور update اجرا می شود که یک واحد به state اضافه می کند بنابراین خروجی این قطعه کد …,0,1,2,3 است.

پیاده سازی تنسرفلو (نت بوک 35: intro to tensorflow):

تعریف کتابخانه:

نمایش ورژن تنسرفلو:

ابتدا یک tf.constant سپس یک session ساخته شده است. خروجی این قطعه کد b’Hello, Tensorflow’ است. ( b نشان دهنده ی byte literal است.)

سپس دو constant دیگر با مقادیر3.0  و 4.0 ساخته شده. در داخل constant ها می توان نوع آن ها را مشخص کرد. datatype آن ها به صورت پیش فرض float32 است.

معمولا در فرایندtraining  از float های بزرگی استفاده می شود زیرا در عملیات به روز رسانی به ما کمک می کند. اما معمولا در inference وقتی کار با گراف تمام شد و فقط می خواهیم عکس را بگیریم و خروجی را ببینیم نیاز به دقت بالایی ندارد.

یکی از بهینه سازی هایی که در تنسورفلو انجام می شود این است که در گرافی که train شده float64 ها را برمی دارد و با یک int یا float کوچک تر جایگزین می کند تا حجم گراف پایین بیاید.

سپس session ایجاد شده را با دستور sess.close() می بندیم.

نمایش node1 و node2 قبل از ساختن session :

نمایش node1 و node2 بعد از ساختن session :

نکته: چون session جاری مشخص است هم می توانیم هم از eval و هم از sess.run استفاده کنیم.

مثال:

در ابتدا یک نود add تعریف شده است. با اجرای دستور (print(node3 اسم تنسور برگردانده می شود.

اما با اجرای دستور ((print(sess.run(node3 یک session ساخته شده و مقادیر node1 و node2 با هم جمع می شوند.

 

 

Fetch کردن (واکشی):

به قطعه کد ([result = sess.run([mul, intermed اصطلاحا fetch کردن می گویند. در واقع فراخوانی (sess.run(var در یک نشست مقدار آن متغیر را می دهد. می توان چندین متغیر را همزمان fetch کرد.

مثال:

در این کد نیز همانند قبل یک گراف ساخته شده است. دو constant به نام های input2 و input3 ، intermediate را ساختند. همچنین tf.mul یک نود است و با اجرای (sess.run(mul,intermed کل گراف ارزیابی می شود.

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

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

1. constant

2. variable

نحوه ورودی دادن بیرون از تنسرفلو:

یک راه ساده استفاده از numpy است. می توان numpy را تبدیل به تنسور کرد و تنسور را به شبکه feed کرد. مشکل این روش این است که برای داده های زیاد جواب نمی دهد زیرا نمی توان همه ی داده ها را در ram لود و آن ها را به تنسور تبدیل کرد. به عبارت دیگر ورودی با استفاده از numpy امکان پذیر و راحت است اما مقیاس پذیر نیست.

مثال (ورودی با استفاده از numpy ):

روش دیگر استفاده از placeholder و feed dictionary است.

Placeholder : یک نوع تنسور هستند که منتظر ورودی اند.

در ابتدای ساخت گراف placeholder ها بر خلاف variable ها و constant ها هیچ مقداری ندارند و منتظر کاربر می مانند که آن ها را مقدار دهی کند.

دو placeholder با نام های input1 و input2 تعریف شده که نوع آن ها floate32 است.

ورودی های این گراف در حال حاضر مشخص نیستند. اگر بعد از ساختن session فقط sess.run() نوشته شود (عملیات fetch کردن)، متوجه نمی شود با چه مقداری باید مقداردهی اولیه را انجام دهد. در این جا باید از feed dictionary استفاده شود.

Feed dict مشخص می کند نود ساخته شده به چه placeholder هایی نیاز دارد و سپس این placeholder ها را به آن پاس می دهد.

 

 

این قطعه کد خروجی کد قبلی را در 3 ضرب کرده است.

 

 

 

 

ابتدا دو variable و یک placeholder تعریف شده است. Variable ها (w و b ) می توانند بعدا به روز شوند و placeholder ها (x ) باید از کاربر گرفته شوند.

سپس global_variables_initializer برای مقدار دهی متغیر ها صدا زده شده و بعد از آن linear_model با 1,2,3,4 فراخوانی شده است.

در این کد با اجرای sess.run(update) ابتدا خروجی یک است و هر بار که اجرا می شود یک واحد به آن اضافه می شود.

assign_add یک واحد به متغیر x اضافه می کند.

 

میانگین گیری (tf.reduce_mean):

 

ضرب ماتریسی (tf.reduce_mean):

matmul برای ضرب ماتریسی استفاده می شود.

 

بیشینه گیری (tf.argmax):

 

آموزش تنسربرد:

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

نصب و راه اندازی تنسربرد:

ابتدا باید پکیج تنسرفلو را با دستور pip install tensorflow روی پایتون نصب کنیم. سپس برای اجرا در در محل ذخیره کتابخانه تنسرفلو، دستور tensorboard –logdir asset را در ترمینال وارد می کنیم. این دستور نشان می دهد تنسربرد بر روی local host قابل دسترسی است.

 

 

 

 

 

 

نمایش گراف در تنسربرد:

 

 

 

 

 

مراحل:

ابتدا برنامه خود را تعریف کرده و متغیر ها را مقدار دهی می کنیم:

 

 

 

 

 

 

سپس یک summary برای ذخیره نتایج تعریف می کنیم:

 

 

 

 

در مرحله بعد یک session ساخته و برنامه نوشته شده را در تنسربرد نمایش می دهیم:

 

 

 

 

 

داشبورد های تنسربرد:

 

 

 

scalar:

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

 

 

 

 

histogram:

این داشبورد در تنسربرد نشان می دهد چگونه توزیع آماری تنسور در طول زمان متغیر است. این داده ها از طریق tf.summary.histogram نمایش داده می شوند.

 

 

 

 

 

 

distribution:

در این داشبورد از tf.summary.histogram استفاده می شود که درصد توزیع روی داده ها را نمایش می دهد.

 

 

 

 

 

 

graph:

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

 

 

 

 

 

image:

این داشبورد عکس هایی که با دستور tf.summary.image و در فرمت png ذخیره شده است را نمایش می دهد.

audio:

این داشبورد یک ابزار قوی برای تعبیه ویجت های صوتی برای مخاطبان است که از طریق tf.summary.audio نمایش داده می شود.

projector:

اساسا پروژکتور تعبیه شده در تنسربرد برای داده های چند بعدی استفاده می شوند.

text:

این داشبورد متن را از طریق tf.summary.text ذخیره می کند و شامل مواردی مانند پیوند ها، فهرست ها و جداول می باشد.

چگونه یک مدل برای شناسایی مکان‌ها آموزش دادیم؟

نویسندگان ‌: محیا مهدیان و محمد حسن ستاریان

مقدمه

deeplearning

در هر مسئله دسته‌بندی (Classification)، پیاده‌سازی یک مدل مناسب -از جهت صحت پیش‌بینی- به مولفه‌های متفاوتی وابسته است؛ داشتن ورودی‌های -با ویژگی‌های- گوناگون و به تعداد زیاد یکی از مولفه‌های مهم برای آموزش مدلی که دقیق (Accurate) بوده و قادر به عمومیت بخشی (Generalization) به دانش خود و راستی آزمایی آن در محیط واقعی است می‌باشد. با این حال جمع آوری داده زیاد کاری سخت و نیازمند زمان و هزینه زیاد، بسته به شرایط و نوع داده مورد نیاز خواهد بود. در این شرایط و با توجه به اینکه کار‌های پیشین زیادی انجام شده اند، استفاده از روش‌های یادگیری انتقال (Transfer learning)، درواقع استفاده از یک مدل از پیش آموزش دیده و استفاده از آن به عنوان استخراج کننده ویژگی (Feature Extractor) یا به عنوان شبکه Fine Tuning کمک بسیار زیادی در ساخت مدلی دقیق و مناسب خواهد داشت. همچنین استفاده از روش‌های افزایش داده (Data augmentation) باعث افزایش چشم‌گیر داده شده و در آموزش بهتر مدل موثر خواهد بود؛ با این‌حال در استفاده از این روش باید توجه داشت از روش‌هایی برای تغییر عکس استفاده کرد که عکس خروجی خارج از فضای حالت مسئله نبوده و در شرایط واقعی مسئله وجود داشته باشد. به علاوه در جمع‌آوری داده باید داده‌های جمع آوری شده بررسی و در صورت نیاز پاکسازی‌هایی نیز انجام شود، تا داده‌های نامناسب، نامربوط و بی‌تاثیر حذف شوند اما از عمومیت داده‌ها کم نشده و داده‌های مختلفی در شرایط مختلف آزمون مسئله وجود داشته باشد؛ چرا که هرچه داده‌ها متفاوت‌تر باشند مدل قابلیت عمومیت بخشی بیشتری خواهد داشت. استفاده از پارامترهای (Hyperparameter)‌ مناسب در آموزش مدل، انتخاب دقیق و بسته به شرایط -و داده‌- پارامترها نیز از اهمیت زیادی برخوردار است و شاید نیاز باشد تغییر دقت مدل با تغییر این پارامترها بررسی شود که در این‌صورت نیاز است مدل چندین دفعه آموزش داده شود.

مراحل پیاده‌سازی مدل

هدف ما آموزش مدلی بود تا بتواند مکان‌های دانشگاه را تشخیص بدهد؛ برای پیاده‌سازی مدل خود از فریم‌ورک کراس (Keras) و زبان پایتون استفاده کردیم. از آنجایی که تعداد کلاس‌ها کم بوده و امکان جمع‌آوری داده زیادی که بتواند مدل را خوب آموزش بدهد نبود، مدلی برای استفاده به عنوان مدل پایه (Base Model)‌ برای Fine Tuning انتخاب شد. سپس داده‌های مورد نیاز جمع‌آوری شده، تمیز شده و آماده آموزش شدند. مدل روی گوگل کولب (Google Colab) به همراه استفاده از روش‌های افزایش داده آموزش داده شده و ذخیره شد. برای استفاده از مدل برنامه‌ای برای اجرای آن روی سرور و گرفتن خروجی با میکروفریم‌ورک فلسک نوشته شده و اپلیکیشن اندرویدی نیز برای گرفتن عکس و پیش‌بینی آن در لحظه ساخته شد. هر مرحله به تفضیل توضیح داده خواهد شد:

کد تمامی مراحل در ریپوزتوری «SRU-Place-Recognizer» قابل دسترسی است.

پیدا کردن مدل پایه

VGG16 + places365

همانطور که گفته شد از آنجایی که تعداد کلاس‌ها کم بوده و امکان جمع‌آوری داده زیادی که بتواند مدل را خوب آموزش بدهد نبود، از روش یادگیری انتقال (Transfer learning) استفاده کرده و مدل VGG16 Places365  برای استفاده به عنوان مدل پایه (Base Model)‌ برای Fine Tuning انتخاب شد. این مدل یک شبکه VGG16 است که از پیش با داده‌های دیتاست Places365 که شامل بیش از ۱۰ میلیون عکس در بیش از ۴۰۰ موضوع است آموزش داده شده است؛ پس نه تنها ویژگی‌های اولیه مورد نیاز مسئله در لایه‌های ابتدایی شناسایی شده‌اند بلکه در لایه‌های جلوتر نیز ویژگی‌های بصری عمیقی شناسایی شده اند و مدلی بسیار مناسب برای این مسئله خواهد بود. بنابراین ما از این مدل به عنوان مدل پایه آموزش خود استفاده کردیم به صورتی که تنها لایه‌های کانولوشنی استفاده شده و از میان‌ آن‌ها ۵ لایه آخر را نیز از حالت فریز (freeze) خارج کردیم. در قسمت ساخت مدل بیشتر بخوانید.

جمع‌آوری داده

برای مسئله شش کلاس -شش مکان برای آموزش مدل- در نظر گرفته شد: دانشکده کامپیوتر، دانشکده معماری، سلف، بوفه، ساختمان امور فرهنگی و زمین ورزشی؛ برای جمع‌آوری داده از این مکان‌ها عکس و فیلم از تمامی زوایای ساختمان‌ها گرفته شد. همچنین سعی شد در زمان‌های متفاوتی عکس‌برداری انجام شود تا تصاویر از تنوع قابل قبولی در نور محیط برخوردار باشند. فریم‌های فیلم‌ها بعدا با استفاده از اسکریپت پایتونی زیر جدا شد تا نهایتا در هر کلاس (از هر مکان) ۸۰۰ عکس شامل ۵۰۰ عکس برای آموزش و ۳۰۰ عکس برای تست و مجموعا ۴۸۰۰ عکس تولید شود.

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

آماده‌سازی داده‌ها

از آنجایی که روش جمع‌آوری داده ما، جدا کردن فریم‌ از فیلم‌های گرفته شده بود، تصاویر نامربوط، برای نمونه از محیط اطراف ساختمان و یا تصاویر تار شده نیز در میان عکس‌ها وجود داشت. همچنین تصاویر با کیفیت ۲۱۶۰*۳۸۴۰ گرفته شده بودند و هر کدام تقریبا حجمی بیش از ۳ مگابایت داشتند که برای آموزش شبکه بسیار سنگین بوده و ویژگی‌های (features) بسیار زیادی تولید می‌کردند که برای برنامه خود تا این حد نیاز به جزئیات نداشتیم؛ همچنین عکس‌ها به صورت landscape جدا شده بودند و نیاز به چرخواندن (rotate) داشتند. برای همین، با استفاده از برنامه ImageMagick تصاویر را ۹۰ درجه چرخوانده و سپس همگی را به سایز ۱۹۲*۱۰۸ تبدیل کردیم تا مدل در حین سبک شدن از ویژگی‌های کافی برای آموزش برخوردار باشد.

برای آشنایی با Image Magick و نحوه انجام کار پست «کار با تصاویر توسط ImageMagick» را بخوانید.

در نهایت تصاویر در فولدرهای مربوطه Train و تست و زیرفولدرهایی با اسامی کلاس‌ها قرار داده شدند. این اسم فولدرها بعدا در آموزش مدل و استفاده از دیتا جنریتور (Data Generator) به عنوان اسامی کلاس‌های مدل تعریف می‌شوند. ساختار فولدربندی داده‌ها به صورت زیر شد:

 

ساخت مدل

همانطور که قبلا اشاره شد برای مسئله از Fine Tuning استفاده شد. مدل نهایی تشکیل شده است از لایه‌های کانولوشنی شبکه VGG16 Places365 که به عنوان مدل پایه استفاده شده است و ۵ لایه آخر آن از حالت حالت فریز (freeze) خارج شده و به دو لایه تماما متصل (Fully connected) با ۲۵۶ نود و ۲ نود که به ترتیب از Activation function های Relu (برای شناسایی nonlinearities) و Softmax (برای کد کردن نتیجه در ۶ کلاس) استفاده می‌کنند متصل شدند.

آموزش مدل

google colab

برای آموزش سریعتر مدل و استفاده از GPU که امکان استفاده آن در سیستم خودمان فعلا وجود نداشت، از سرویس گوگل کولب (Google Colab)‌ استفاده کردیم. برای همین منظور فایل‌های لازم برای آموزش مدل به گوگل درایو منتقل شدند -فایل‌ها آپلود شده و از طریق سرویس SavetoDrive به گوگل درایو منتقل شدند- سپس فایل‌ها را در نوت‌بوکی که در گوگل کولب ساخته بودیم وارد کردیم تا مدل را آموزش دهیم.

آموزش نحوه انتقال فایل از گوگل کولب به گوگل درایو را در پست «اتصال مستقیم سرویس کولب (Google Colab) به درایو (Google Drive) از طریق فایل سیستم FUSE» بخوانید.

برای آموزش مدل پس از تعریف ساختار مدل (که در قسمت ساخت مدل توضیح داده شد)، چون که تعداد داده‌ها زیاد بود از دیتا جنریتور (Data Generator) هایی برای خواندن تصاویر از فولدر‌های مربوطه استفاده شده و برای داده‌های آموزش (Train) از روش‌های افزایش داده (Data augmentation) استفاده شد. تصاویر در گروه‌های ۲۰ تایی به شبکه تغذیه (Feed) شده ( batch_size = 20 )، مقادیر steps_per_epoch  و validation_steps  با توجه به تعداد داده‌های Train و Test و تعداد عکس‌های هر گروه ( batch_size) محاسبه شده و با ۱۰ بار تکرار ( epochs = 10 ) شبکه آموزش دید.

بررسی مدل

برای بررسی مدل نمودارهای روند تغییر accuracy و loss در هر epoch چاپ شد تا از نبود over-fitting مطمئن شویم.

accuracy and loss Plots

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

تصویر با استفاده از تابع load_img در سایز مورد استفاده مدل خوانده شده و سپس به آرایه تبدیل شده، آرایه تبدیل به آرایه تک بعدی شده و پیش پردازشی رو آن توسط تابع  preprocess_input انجام شده است. این تابع در فایل  places_utils که مدل پایه (VGG16 Places365در اختیار گذاشته موجود است.

ذخیره مدل

در نهایت برای استفاده‌های آتی، مدل را ذخیره کردیم.

 

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

استفاده از مدل در عمل

اسکریپت پیش‌بینی

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

اسکریپت در ریپازیتوری در دسترس است.

سرور پیش‌بینی

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

برای آشنایی با فلسک و نحوه ایجاد یک برنامه سرور پست «آموزش مقدماتی فلسک (Flask)»‌ را بخوانید.

سه endpoint برای کار با مدل تعریف شدند؛  upload/  برای آپلود عکس (عکس را به صورت base64 دریافت کرده و آن را ذخیره می‌کند)، imagetopredict/  دریافت آخرین عکسی که برای پیش‌بینی فرستاده شده و  predictagain/  برای پیش‌بینی دوباره آخرین عکس آپلود شده. سپس، این برنامه روی سرور دپلوی شده و مدل آماده استفاده عملی شد.

کد برنامه سرور در ریپازیتوری در دسترس است.

برای آشنایی با نحوه دپلوی مدل پست «دپلوی کردن و استفاده از مدل در عمل (Model deployment)» را بخوانید (ما از روش سوم استفاده کردیم).

اپلیکیشن اندروید

حال که سروری داشتیم که با فرستادن عکس می‌توانستیم نتیجه پیش‌بینی را دریافت کنیم، میخواستیم از هر جایی امکان فرستادن عکس را داشته باشیم؛ برای این منظور با استفاده از فریم‌ورک Nativescript-Vue که ترکیب فریم‌ورک‌های Nativescript که برای ساخت اپلیکیشن‌های اندروید و ios با استفاده از زبان جاوااسکریپت (javascript) است و Vue که یک فریم‌ورک جاوااسکریپتی برای ساخت Progressive Web App هاست، اپلیکیشن اندرویدی برای پیش‌بینی تصاویر توسط مدل و با اتصال به سرور تولید شد.

کد اپلیکیشن در ریپازیتوری در دسترس است.

دپلوی کردن و استفاده از مدل در عمل (Model deployment)

10نویسندگان ‌: محیا مهدیان و محمد حسن ستاریان

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

برای اینکار چندین راه وجود دارد؛ در این پست ما روش‌‌های اجرای لوکال، دپلوی با Heroku و اجرا از سرور ریموت را بررسی می‌کنیم.

 

اجرای لوکال


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

ابزار‌ها

ngrok – ابزاری رایگان برای ایجاد تونل از اینترنت به یک پورت در سیستم لوکال است. ngrok یک آدرس قابل دسترس از اینترنت به پورت مشخص شده می‌دهد تا بتوان ترافیک پورت را از خارج سیستم از طریق اینترنت دریافت کرد.

Flask – فلسک یک میکروفریم‌ورک سبک برای راه‌اندازی سریع و راحت وب‌سرور است. آموزش مقدماتی فلسک را بخوانید.

قبل از شروع، طبق این مراحل ngrok را نصب کرده و آن‌را به PATH سیستم خود اضافه کنید.

طبق آموزش مقدماتی فلسک، کدی مانند نمونه کد زیر برای سروری که قادر به گرفتن عکس (upload)، لود مدل آموزش داده‌شده (Load model)، پیش‌بینی عکس (Predict)‌ و برگرداندن خروجی است، بنویسید.

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

پس از اجرا، سرور در آدرس http://localhost:5000 در دسترس می‌شود.

حال با استفاده از ngrok به این سرور یک آدرس قابل دسترس در اینترنت اختصاص می‌دهیم؛ برای اینکار یک ترمینال جدید باز کرده و دستور زیر را وارد می‌کنیم:

در این دستور با فراخوانی ngrok گفته ایم به برنامه درحال اجرا در پورت ۵۰۰۰ میخواهیم دسترسی از طریق پروتکل http بدهیم. پس از اجرای دستور بالا مطابق شکل زیر آدرسی که می‌توان برای دسترسی به سرور استفاده کرد به همراه آدرس مدیریت سرویس ngrok به نمایش در‌می‌آید:

ngrok output

پس از آن می‌توانید از طریق این آدرس و endpoint های تعریف شده از مدل خود استفاده کنید.

 

دپلوی با Heroku


شاید سخت‌ترین روش بین دو روش دیگر این روش و استفاده از Heroku است و مفاهیمی که این روش به عنوان پیش‌نیاز لازم دارد تا آشنا باشید کم نیستند. اما شاید از روش‌های دیگر سخت‌تر باشد اما می‌تواند جذاب‌تر و حتی پرکاربرد تر باشد. همچنین لازم به ذکر است این سرویس فعلا برای استفاده مسدود بوده و نیاز به اتصال غیر مستقیم است و در استفاده رایگان حجم پروژه نباید از ۵۰۰ مگابایت بیشتر باشد.

ابزار‌ها

Heroku – سرویس (PaaS (Platform as a service ای و درواقع بستری به عنوان سرویس ابری است که از زبان‌های برنامه نویسی زیادی پشتیبانی می‌کند که برنامه نویس را از کارهای DevOps لازم برای راه‌اندازی یک سرور بی‌نیاز می‌کند.

Flask – فلسک یک میکروفریم‌ورک سبک برای راه‌اندازی سریع و راحت وب‌سرور است. آموزش مقدماتی فلسک را بخوانید.

Github – گیت‌هاب سرویس میزبانی و کنترل نسخه تحت وب قدرت گرفته از گیت (git) است.

GitLFS – سیستم مدیریت فایل‌های حجیم گیت.

GitLFS سرویس ارائه شده توسط GitHub برای کنترل نسخه فایل‌های حجیم (حجیم تر از ۵۰ مگابایت) است و چون ما در پروژه خود فایل‌های نظیر فایل مدل آموزش داده شده و شاید فایل‌های دیگر داشته باشیم به این برنامه احتیاج داریم.

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

ورود

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

پس از نصب موارد فوق، ترمیتال را باز کرده و با استفاده از دستور زیر در Heroku لاگین می‌کنیم:

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

آماده‌سازی

اگر برنامه شما توسط git مدیریت نمی‌شود با استفاده از دستور git init  آن‌را فعال کنید. همچنین فایل‌های حجیم خود را مشخص کنید تا GitLFS آن‌ها را مدیریت کند:

در این مثال فایل model.h5  را که فایل مدل ذخیره شده است و حجم بیشتر از ۵۰ مگابایت دارد را با استفاده از GitLFS مدیریت می‌کنیم.

سپس، با استفاده از دستور زیر یک اپلیکیشن در Heroku درست می‌کنید که آماده دریافت سورس و اجرای آن‌ است:

با اجرای این دستور یک git remote  به نام heroku مرتبط با ریپوزیتوری گیت لوکال شما اضافه خواهد شد. همچنین، یک نام تصادفی (در این مثال lit-bastion-5032 ) به این برنامه تخصیص داده می‌شود. همچنین می‌توان با وارد کردن یک نام دلخواه نام مورد نظر خود را به اپلیکیشن اختصاص داد.

هروکو با استفاده از چند فایل تنظیم، تصمیم می‌گیرد برنامه را به چه صورت و با استفاده از چه سرویسی اجرا کند. برای آن‌که مشخص کنیم برنامه چگونه باید اجرا شود به سه کانفیگ فایل runtime.txt و requirements.txt به همراه فایل Procfile نیاز داریم.

runtime.txt

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

ما این فایل را با محتوی زیر ایجاد می‌کنیم:

requirements.txt

این فایل، پیش‌نیازهای اجرای برنامه را مشخص می‌کند.

ما این فایل را با خروجی دستور pip freeze  که پکیج‌های نصب شده برای پروژه را چاپ می‌کند به صورت زیر ایجاد می‌کنیم:

Procfile

این فایل، شامل توضیحات نحوه اجرای برنامه است.

ما ابن فایل را با دستور زیر ایجاد خواهیم کرد:

این دستور بیان می‌کند که برنامه ما یک برنامه از نوع web بوده و لازم است با استفاده از برنامه سرور gunicorn اجرا شود و فایل اجرایی اپلیکیشنی به نام server است.

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

نکته مهم استفاده از gunicorn این است که این برنامه ابتدا یک سرور اجرا کرده سپس برنامه ما را در آن import می‌کند. از آنجایی که برنامه ما خود سرو خواهد شد نیازی به دستور ()app.run  نخواهد بود و اگر در کد خود از این دستور استفاده کرده ایم باید آن را مانند مثال زیر در شرط بررسی import شدن یا نشدن ماژول قرار دهیم:

با اعمال تغییرات فوق و اضافه کردن کانیفگ فایل‌ها، این تغییرات را با استفاده از گیت کنترل می‌کنیم:

قبل از ادامه دپلوی با استفاده از دستور heroku local web  می‌توانیم سرور خود را به صورت لوکال تست کنیم، اما از آنجایی که برنامه gunicorn در ویندوز قابل اجرا نیست اگر از ویندوز استفاده می‌کنید این امکان وجود نخواهد داشت.

حال اگر برنامه ما نیاز به تغییر نداشته و آماده push  کردن هستیم، با دستور زیر برنامه را در ریپوزیتوری ریموتی که هروکو در اختیارمان گذاشته بود push  می‌کنیم:

readme_assets/images/heroku-git-push.gif

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

با استفاده از دستور زیر می‌توانیم آدرس اختصاص داده شده به برنامه را در مرورگر باز کنیم:

برنامه آماده استفاده است!

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

heroku deploy options

اجرا از سرور ریموت


مراحل این روش تا حدود زیادی شبیه روش اول است، چراکه باز نیز با استفاده از flask یک برنامه سرور اجرا می‌کنیم. برای این روش لازم است از یکی از سرویس‌های ارائه دهنده سرور‌های ابری (Cloud servers) و یا سرور‌های اختصاصی (VPS)، سروری تهیه کنید. پس از تهیه سرور IP ای برای دسترسی به سرور به شما داده می‌شود. با استفاده از این سرور و از آنجایی که این IP یک IP عمومی (Public IP)‌ است، تنها کافی است با استفاده از فلسک سروری در سیستم اجرا کرده و host آن را برابر ‘0.0.0.0’ قرار دهیم تا از طریق اینترنت قابل دسترس باشد.

ابزار‌ها

Flask – فلسک یک میکروفریم‌ورک سبک برای راه‌اندازی سریع و راحت وب‌سرور است. آموزش مقدماتی فلسک را بخوانید.

SSH – پروتکل شبکه‌ای برای اتصال امن که یکی از کاربرد‌های آن ورود به یک سیستم ریموت است.

برای اتصال به سرور از SSH استفاده می‌کنیم. برای همین اگر از ویندوز استفاده می‌کنید از نرم‌افزار PuTTY استفاده کرده و اگر از لینوکس استفاده می‌کنید و یا در سیستم ویندوز خود کرنل لینوکس را فعال کرده‌اید (WSL) -از طریق کرنل لینوکس موجود در سیستم- به آی‌پی سرور از طریق SSH متصل شوید.

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

پس از آن تنها کار لازم اجرای اسکریپت سرور فلسک است. توجه کنیم که برای اجرای سرور فلسک host آن‌را برابر ‘0.0.0.0’ و پورت دلخواه (پیش فرض ۵۰۰۰) تنظیم می‌کنیم:

برنامه در آدرس سرور و پورت تعیین شده اجرا شده و از طریق endpointها در دسترس خواهد بود.

 

منابع

مقاله‌های «پلوی کردن مدل کراس» و «دپلوی مدل‌های کراس» در مدیوم

رپوزیتوری گیت «مثال دپلوی اپلیکیشن پایتون در هروکو»، tl;dr

اتصال مستقیم سرویس کولب (Google Colab) به درایو (Google Drive) از طریق فایل سیستم FUSE

نویسندگان ‌: محیا مهدیان و محمد حسن ستاریان

google colab

اگر با گوگل کولب (Google Colab) کار کرده باشید می‌دانید که فایل سیستم آن از فایل سیستم گوگل درایو (Google Drive) جدا بوده و برای استفاده از فایل‌های خود باید پس از اتصال کولب به درایو فایل‌های مورد نیاز را دانلود کرده و پس از اعمال تغییرات برای جلوگیری از پاک شدن فایل‌ها -فایل‌های موجود در کولب پس از ۱۲ ساعت پاک می‌شوند- آن‌ها را در درایو دانلود کنید.

روش دیگر اینکار اتصال گوگل درایو به صورت یک فایل سیستم FUSE به گوگل کولب است، که در واقع گوگل درایو را در کولب mount می‌کنیم. از مزیت‌های آن این است که فایل‌ها در طرفین همگام و یکسان (sync) بوده و برای استفاده از فایل‌ها نیازی به دانلود و آپلود آن‌ها نیست.

روش اتصال

نصب پیش‌نیازها

ابتدا با استفاده از دستورات زیر،‌ پکیج‌های مورد نیاز را دانلود و نصب می‌کنیم:

تائید هویت

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

همچنین، با دستورات زیر همانند مراحل بالا اجازه دسترسی فایل سیستم FUSE را به گوگل درایو می‌دهیم:

اتصال

حال فولدری در فایل سیستم گوگل کولب به نام drive  ساخته و گوگل درایو را در آن mount می‌کنیم:

پس از اجرا لیست فایل‌های دایرکتوری  drive  چاپ می‌شود که درواقع تمامی فایل‌های گوگل درایو شما هستند.

 

منبع

این نوت‌بوک در گوگل کولب

مقدمه‌ای بر شبکه‌های عصبی و چارچوب Keras (کراس)

برای اجرای این مبحث نیاز به نصب کتابخانه کراس (Keras) دارید. برای نصب این کتابخانه میتوانید لینک زیر را مطالعه کنید.

http://blog.class.vision/1396/12/installing-keras-with-tensorflow-backend/

در صورتی که تمام کتابخانه‌های مورد نیاز شما نصب باشد سلول زیر باید بدون مشکل اجرا شود.
 برای اینکه موقع اجرای کدها دقیقا نتایج سر کلاس را بتوانید مشاهده کنید لازم است از تابع seed برای گرفتن اعداد رندم استفاده کنید:

لود مجموعه داده (dataset)

پیش‌پردازش داده‌ها برای Keras

ابتدا تابعی ساده تعریف کرده ایم که ابعاد، نوع داده ای و اطلاعات دیتاست لود شده را چاپ کند.
این اطلاعات را قبل و بعد از پیش‌پردازش داده ها چاپ خواهیم کرد تا متوجه تغییرات بشویم!

حال برای تبدیل فورمت دیتاها به فورمت کتابخانه ی کرا س باید یک سری پیش پردازش انجام بدهیم:

x_train و x_test به فرمت لیست ساده است به همین دلیل ما ان ها را به کمک np.array به  فرمت  آرایه‌های نامپای یا ndarray  تبدیل کردیم و  y_train و y_test نیزبه فرمت لیست ساده هستند که ما باتابع keras.utils.to_categorical به شکل  یک وکتور در نظر میگیریم  که درهرخانه اش یک برچسپ 10تایی است که بسته به مقدار  y_train و y_test ان لیبل یک وبقیه خانه ها صفر هستند به اصطلاح   one-hot-encoding می گویند.

با فراخوانی تابع ساده ای که قبلاتعریف کردیم میتوانیم ابعاد، نوع داده ای و اطلاعات دیتاست لود شده  قبل وبعد از processرا چاپ کنیم

میبینیم که [y_train [0پیش از پردازش مقدار 6را داشته وبعداز پردازش به یک وکتور که برجسپ خانه ی 6 ام ان یک است تبدیل شده است.

 

آخرین گام پیش‌پردازش تبدیل داده‌ها به float32 و چون دیتا ها بین مقادیر 0تا255هستند با تقسیم x_train و x_testمقادیر را به مقدار بین 0 و  1نرمال سازی  میکنیم.

تعریف معماری مدل (model architecture)

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

خط اول کد : نوع modelخود را ()Sequential  قرار میدهیم چون میخواهیم شبکه های عصبی مان به ترتیب پشت هم قرار بگیرند و غیر بازگشتی باشند(یعنی امکان بازگشت ازیک لایه نورون جلوتر به لایه نورون پیشین نباشد).

خط دوم کد:حال به  modelتعریف شده یک لایه با تابع add  اضافه میکنیم چون لایه اول را میخواهیم تعریف کنیم باید تعدادنورون ورودی وخروجی را مشخص کنیم.تابع داخلی که Denseهست میگوید این لایه هارا به هم بچسبان و64 که پارامتر اول تابع است  تعداد نورون های خروجی رامشخص میکند پارامتر دوم رادر یادداشت های قبلی توضیح داده شده است و  activation=’relu’قراردادیم و درنهایت  input_dim نیز تعداد نورون های ورودی رامشخص میکند.

خط سوم کد:لایه دیگری تعریف کردیم که به لایه قبلی چسبیده وتعدادنورون های خروجی 10است وبرای نرمال سازی خروجی activation=’softmax’قراردادیم وشبکه عصبی را با سه لایه جمع  کردیم.

Compile model

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

‘ loss= ‘ categorical_crossentropy:تابع هزینه ومعیار بد بودن شبکه را تعیین میکندو بهترین loss را انتخاب کردیم.

optimizer=’rmsprop’برای بهینه کردن تابع loss از optimizerاستفاده میکنیم.

metrics=[‘accuracy’]گزارشی که میدهیم را برمبنای accuracyقرارمیدهیم(قبلا metricرا دریادداشت های قبلی دوستان توضیح داده اند

 

 

 

 

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

در این قسمت می خواهیم به معرفی تعدادی از شبکه های نورونی کانولوشنالی (CNN) معروف بپردازیم. این شبکه ها از آن جهت معروفند که امروزه بسیاری از افراد در مقالات یا پروژه های خود از آن ها استفاده می کنند و هم چنین در زمان معرفی شدنشان توانستند جایزه ی ImageNet که یکی از معتبر ترین جوایز در این زمینه است را برنده شوند.

ImageNet

این مسابقه از سال 2010 هر ساله برگزار می‌شود. هدف آن دسته تشخیص و دسته بندی تصاویر در مقیاس وسیع است. شبکه های شرکت کننده، باید تصاویری با 1000 کلاس متفاوت را از هم تمیز دهند. معیار اندازه گیری دقت شبکه ها، خطای 5 کلاس برتر است. به صورتی که شبکه با دیدن تصویر، ۵ کلاس معرفی می‌کند. در صورتی که کلاس مورد نظر در میان آن ها بود، جواب شبکه پذیرفته می‌شود.

۱- LeNet-5

اولین شبکه ی کانولوشنالی که بسیار مطرح شد شبکه ی LeNet-5 بود که در مقاله ی”Gradient-based learning applied to document recognition ” نوشته شده توسط LeCun, Bottou, Bengio, Haffner و در سال 1998 ارائه شد. نام شبکه نیز از نام Yann Lecun یکی از نویسندگان این مقاله برداشته شده است. این شبکه را می توان به عنوان اولین شبکه که فیلتر های کانولوشنالی در آن استفاده شده است نام برد. هدف این شبکه، خواندن کد پستی از پشت بسته های پستی بود.

شکل بالا شبکه ی Lenet را نمایش می دهد. این شبکه در ابتدا یک ورودی 32*32 دریافت می کند و سپس از 6 فیلتر کانولوشنالی 5*5 که گام(stride) آن برابر 1 است عبور می کند. حاصل یک تنسر 6*28*28 است. سپس از فیلتر subsampling که در این جا فیلتر AveragePool 2*2 با گام 2 است عبور می کند. این فیلتر موجب می شود که طول و عرض آرایه نصف شود اما عمق آن تغییری نمی کند در نتیجه به آرایه ی 6*14*14 می رسیم. این بار از 16 فیلتر کانولوشنالی 5*5 با گام 1 عبور می دهیم که حاصل 16*10*10 است. دوباره از یک AveragePool مانند قبل عبور می دهیم که حاصل 16*5*5 میشود. و در انتها نیز از دو لایه ی Fully connected عبور داده می شوند.

۲- AlexNet

دومین شبکه ی نورونی کانولوشنالی مهمی که می توان نام برد شبکه ی AlexNet است که توسط Alex Krizhevsky و حدود چهارده سال بعد از LeNet یعنی در سال 2012 معرفی شد. این شبکه دارای 8 لایه (پنج لایه ی کانولوشنالی و سه لایه fully connected) است که موجب شده در دسته ی شبکه های کم عمق (Shallow) قرار گیرد.

شکل بالا شبکه ی AlexNet را نمایش می دهد.(دلیل این که لایه ها دوطبقه ای هستند، استفادهاز دو GPU برای پردازش آن است) درشکل ورودی شبکه یک عکس 3*224*224 است اما ورودی درست 3*227*227 است! در ابتدا 96 فیلتر کانولوشنالی 11*11 همراه با 4 گام و padding=0 اعمال می شود. خروجی آرایه ی 96*55*55 است.(تعداد پارامتر های هر لایه ی کانولوشنالی برابر است با : طول لایه * عرض لایه * عمق ورودی * تعداد فیلتر ها (به طور مثال در اینجا برابر است با 11*11*3*96))در مرحله ی بعد از لایه ی maxpool 3*3 با اندازه ی گام 2 عبور داده می شود که خروجی 96*27*27 می شود.(تعداد پارامتر های قابل یادگیری در maxpool صفراست.) در مرحله بعد از 256 فیلتر کانولوشنالی 5*5 با گام یک و padding=2 عبور می دهیم که خروجی 256*27*27 است. در مرحله ی بعد نیز دوباره از فیلتر maxpool 3*3 با گام 2 عبور می دهیم که خروجی 13*13*96 است. در سه مرحله ی بعد از فیلتر های کانولوشنالی با گام و padding یک استفاده می کنیم که تعداد آن ها به ترتیب 384 ، 384 ، 256 است که خروجی نهایتا 256*13*13 می شود. سپس از یک لایه ی maxpool 3*3 با گام یک عبور می دهیم و خروجی آن 256*6*6 می شود. در آخر نیز سه لایه ی fullyconected قرار دارد. دو لایه 4096 تایی و یک لایه 1000 تایی با اکتیویشن softmax برای تعیین کلاس های موجود در مساله. (به طور مثال اگر قصد انتخاب بین سه کلاس سگ، گربه، موش را داشته باشیم اندازه لایه ی آخر را سه در نظر می گیریم.)

ورودی

نوع فیلتر

تعداد

اندازه

گام

حاشیه

خروجی

3*227*227

Conv

96

11*11

4

0

96*55*55

96*55*55

maxpool

1

3*3

2

96*27*27

96*27*27

conv

256

5*5

1

2

256*27*27

256*27*27

Maxpool

1

3*3

2

256*13*13

256*13*13

Conv

384

3*3

1

1

384*13*13

384*13*13

Conv

384

3*3

1

1

384*13*13

384*13*13

Conv

256

3*3

1

1

256*13*13

256*13*13

Maxpool

1

3*3

2

256*6*6

9216

Fullyconected

4096

4096

Fullyconected

4096

4096

Fullyconected

1000

نکات مهم :

• تابع relu برای اولین بار معرفی و استفاده شد.
• بعد از دو لایه ی maxpool اول از نرمال ساز استفاده شده بود که دیگر مورد استفاده قرار نمی‌گیرد.
• برای اولین بار از dropout استفاده شده.
• اندازه ی batch در آن 128 است.
• میزان خطای آن در مسابقه ی imagenet برای خطای 5 کلاس برتر ، مقدار 15.4% بود که حدود سه درصد نسبت به سال گذشته بهبود داشت.

۳- ZFNet

نویسنده های این شبکه، Matthew Zeiler و Rob Fergus بودند که نام شبکه نیز از آن ها گرفته شده.این شبکه از ایده زیادی برخوردار نیست و مهم ترین ایده آن ، قسمت Visualization آن است. ابزاری که با استفاده از آن، کاربرد هر نورون در شبکه تا حدی مشخص می‌شود و به درک شبکه های کانولوشنالی کمک بزرگی کرد. در این ابزار می‌توان دید که در لایه های نخست، شبکه خطوط و لبه های ساده را تشخیص می‌دهد و در لایه های بعد نورون ها مفاهیم پیچیده تری مانند صورت انسان یا نوشته را تشخیص می‌دهند. بعضی از نورون ها برای ما قابل فهم نیستند. ولی معلوم شده حذف آن ها هم تاثیری مانند حذف دیگر نورون ها در عملکرد نهایی شبکه دارد.
این شبکه همان شبکه AlexNet است با این تفاوت که در لایه اول، به جای (11*11 stride4)، از (7*7 stride2) استفاده شده است(چون سایز فیلتر در AlexNet بزرگ گرفته شده بود و stride آن زیاد بود.) و در لایه های 3، 4 و 5 به ترتیب به جای 384 ، 384 و 256 فیلتر، از 1024، 512 و512 فیلتر استفاده شده است.

نکات مهم:

• ZFNet، در مسابقه ImageNet خطای ۵ کلاس برتر را به 14.8% کاهش داد و همین باعث شد تا برنده Challenge ImageNet سال 2013 شود.
• ارائه ابزار Visualization

۴- VGG

این شبکه، به دلیل این که تعداد HyperParameter ها را کاهش داده، پیچیدگی کمتری نسبت به AlexNet و ZFNet دارد و به دلیل همین سادگی، از محبوبیت بالایی برخوردار است.
در VGG در هر جا:
CONV به معنی فیلتر 3*3 با stride 3 و same است.
و POOL به معنی پولینگ 2*2، با stride 2 است.
سایز تصویر ورودی 3*224*224 است. سپس دو بار CONV با عمق 64 روی آن اعمال می شود.(با CONV اول، تصویر 64*224*224 می شود و با CONV دوم دوباره 64*224*224 می شود.) سپس POOL روی آن اعمال می شود وتصویر 64*112*112 می شود.(پولینگ روی عمق تاثیر نمی گذارد.) بقیه مراحل در شکل زیر قابل مشاهده هستند:

در مقاله VGG، که در سال 2015 ارائه شد، چند مدل مختلف تست شده اند و مدلی دارای 16 لایه تحت عنوان VGG-16 بیش ترین کارایی را داشته است.

نکات مهم:

• در این معماری، به ازای هر تصویر، 93MB حافظه اشغال می شود.
• 138 میلیون پارامتر قابل یادگیری دارد.
• در سال 2014، خطای ۵ کلاس برتر مسابقه ImageNet را به 7.3% بهبود بخشیده است. با این حال این شبکه برنده نشد.

۵- GoogLeNet (Inception)

این شبکه توسط Google در سال 2014 ارائه شد. نام آن ادای احترامی به Yann Lecun، سازنده LeNet، اولین شبکه کانولوشنالی، است. این شبکه با ایده عمیق تر کردن شبکه های کانولوشنالی که طبق گفته سازنده، برگرفته از دیالوگی در فیلم Inception است! برای همین به این نام نیز شناخته می‌شود.

در این شبکه با این رویکرد که هایپر پارامتر های شبکه را هم به گونه ای به پارامتر قابل یادگیری تبدیل کنند، ماژولی به نام Inception module طراحی شد.

در این ماژول، ۳ فیلتر کانولوشنالی با اندازه های متفاوت و یک فیلتر پولینگ روی لایه قبلی اجرا شده و نتایج را به صورت یک تنسر واحد کنار هم می‌گذارد. در این صورت شبکه می‌تواند در لایه بعدی تصمیم بگیرد که از نتیجه کدام فیلتر و به چه اندازه می‌خواهد استفاده کند. سایز فیلتر های کانولوشنالی به صورتی که در تصویر مشخص است، 1*1, 3*3 و 5*5 است و فیلتر پولینگ با سایز 3*3 روی آن اجرا شده.


در این شبکه با قرار دادن دو لایه ی پولینگ در ابتدای کار، پارامتر های قابل یادگیری مساله را بسیار کاهش داده اند. در ادامه از ۹ لایه یInception module استفاده شده. جزئیات بیشتر در تصویر زیر مشخص است.
در تصویر بالا بلاک های آبی نشان دهنده لایه کانولوشنالی، قرمز نشان دهنده پولینگ، زرد سافت مکس و سبز کنار هم گذاشتن خروجی های قبلی است.

نکات مهم:

• معرفی ایده جدید Inception module
• داشتن تنها ۵ میلیون پارامتر قابل یادگیری. این تعداد نسبت به شبکه های AlexNet و VGG به ترتیب ۱۲ و ۳۶ برابر کمتر است.
• این شبکه در سال2014 با کاهش میزان خطای ۵ کلاس برتر در مسابقه ImageNet به 6.7% برنده شد.

۶- Microsoft ResNet

این شبکه توسط Microsoft ارائه شد که نام آن مخفف Residual Network است. در این شبکه ارتباطاتی خارج از ساختار کانولوشنالی در کنار آن بین لایه ها در نظر گرفته شده تا ورودی های لایه قبلی را بدون واسطه به لایه بعدی منتقل کند و در مرحله back propagation یا اصلاح شبکه، ارور هر لایه را به لایه قبلی انتقال دهد تا بتوان شبکه را عمیق تر کرد و آن را سریع تر آموزش داد. به این ارتباطات skip connections و به ساختار حاصل از آن Residual block می‌گویند.

با این ترفند توانستند شبکه ای با عمق ۱۵۲ لایه را آموزش دهند که اختلاف زیادی با شبکه های قبلی داشت.

نکات مهم:

• معرفی مفهوم جدید skip connections و residual block.
• عمیق کردن قابل توجه شبکه.
• این شبکه در سال 2015 در مسابقه ImageNet میزان خطای ۵ کلاس برتر را به 3.6% کاهش داد.

خلاصه

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

برای مطالعه بیشتر

LeNet

AlexNet

ZF Net

VGG Net

GoogLeNet

Microsoft ResNet

منابع

ImageNet

CNNs Architectures: LeNet, AlexNet, VGG, GoogLeNet, ResNet and more …

We Need to Go Deeper: A Practical Guide to Tensorflow and Inception

An Overview of ResNet and its Variants

آموزش یک شبکه عصبی کانولوشنالی از ابتدا در Kears

مجموعه داده

مجموعه داده گربه در مقابل سگ برای این مثال استفاده شده است. این مجموعه داده در چالش بینایی کامپیوتر اواخر سال ۲۰۱۳ توسط سایت Kaggle.com در دسترس عموم قرار گرفت. مجموعه داده اصلی دارای ۲۵۰۰۰ تصویر (۱۲۵۰۰ از هر کلاس) است که می‌توانید آن را از اینجا دریافت کنید.

ما بعد از دانلود تصاویر، آن ها را در ساختار جدیدی مرتب کردیم. ۱۰۰۰ عکس برای آموزش، ۵۰۰ عکس برای ارزیابی و ۵۰۰ عکس برای آزمون از هر کلاس (گربه و سگ) جدا کردیم. این فرایند توسط کد زیر انجام شده و تصاویر مرتب شده از اینجا در دسترس است.

برای بررسی صحت انجام کار، تعداد تصاویر آموزشی، ارزیابی و آزمون را بررسی میکنیم.

تعریف معماری مدل (model architecture)

ما از یک مدل کانولوشنالی برای حل این مساله استفاده می‌کنیم. از قبل از سال ۲۰۱۳ استفاده از شبکه های کانولوشنالی خیلی رایج نبود ولی بعد از آن تقریبا در همه مدل های بینایی ماشین با روش یادگیری عمیق، از این شبکه ها استفاده می‌شود.شبکه ما از ۴ لایه ی کانولوشنالی و پولینگ بعد از هر کدام، یک لایه متراکم (Dense) پنهان و یک لایه متراکم برای لایه خروجی که دارای یک نورون است استفاده می‌کنیم.تابع فعال سازی لایه آخر sigmoid است. در پیاده سازی مدل برای تشخیص اعداد دست نویس دیتاست هدی، ما در لایه آخر از تابع softmax استفاده کردیم. با تابع softmax خروجی نورون های لایه آخر به صورتی می‌شود که مقدار هر کدام عددی بین ۰ و ۱ است و مجموع همه برابر یک خواهد بود. این تابع برای لایه آخر مسائل طبقه بندی به کار می‌رود.در این مسال مابه جای استفاده از دو نورون با تابع softmax از یک نورون با تابع sigmoid استفاده می‌کنیم. این تابع عددی بین ۰ و ۱ برمی‌گرداند. چون تنها دو کلاس داریم، مقدار یکی از نورون ها برابر اختلاف دیگری با عدد ۱ است. پس می‌توانیم عدد ۰ را متناظر با یکی از کلاس ها (مثلا گربه)‌ و عدد ۱ را متناظر با کلاس دیگر (سگ) قرار دهیم. در این صورت به جای دو نورون در لایه خروجی، با یک نورون همان کار را انجام می‌دهیم.

نگاهی به ابعاد و تعداد اطلاعات در هر یک از لایه های شبکه می‌اندازیم.نگاهی به ابعاد و تعداد اطلاعات در هر یک از لایه های شبکه می‌اندازیم.

چون این مساله تنها دو کلاس داریم، از تابع binary_crossentropy برای محاسبه میزان خطا استفاده می‌کنیم. با توجه به اینکه تعداد تصاویر یکسانی از سگ و گربه برداشته ایم معیار Accuracy معیارمناسبی برای ارزیابی خواهد بود.

پیش پردازش داده (Data preprocessing)

مراحل آماده سازی تصاویر برای شروع عملیات یادگیری:

  1. خواندن تصویر
  2. تبدیل فرمت jpeg به پیکسل های RGB
  3. تبدیل آن به tensor (آرایه چند بعدی) از اعداد حقیقی
  4. نرمال کردن اعداد (تبدیل بازه ۰ تا ۲۵۵ به بازه ۰ تا ۱)

به لطف ابزار های کتابخانه کراس، تمام این مراحل به راحتی انجام می‌شود. کافی است کلاس ImageDataGenerator را از keras.preprocessing.image ایمپورت کرده، آدرس فولدر ها، ابعاد تصاویر ورودی، نوع طبقه بندی و اندازه batch را مشخص کنیم و از کلاس های ایجاد شده برای یادگیری و ارزیابی مدل استفاده کنیم.

اطلاعات بیشتر در مستندات Keras :

https://keras.io/preprocessing/image/

اگر بخواهیم نگاهی به خروجی کلاس های generator بیاندازیم خواهیم دید در هر گام پیمایش، آن ها یک دسته(batch) از تصاویر رنگی ۱۵۰ در ۱۵۰ پیکسل (3, 150, 150, 20) و به تعداد تصاویر، عنوان آن ها را (۰ برای گربه و ۱ برای سگ) برمی‌گرداند. با ادامه پیمایش این روند به تعداد نامحدود تکرار می‌شود.

 

آموزش مدل (fitting model)

حالا نوبت آموزش مدل می‌شود. برای این کار به جای تابع fit از تابع fit_generator استفاده می‌کنیم که همان  کار را انجام می‌دهد ولی با generator ها کار می‌کند. این تابع برای اولی ورودی یک generator مانند آنچه  ساختیم می‌گیرد و با آن مدل را تغذیه می‌کند. چون generator ها بدون اطلاع از تعداد تصاویر، مدام  خروجی ها را برمی‌گردانند، باید به گونه ای تعداد گام های پیمایش را به ازای هر دوره(epoch) مشخص کنیم. پس علاوه بر generator باید مقدار ورودی steps_per_epoch را هم به تابع بدهیم. چون تعداد تصاویر ۲۰۰۰ تا و اندازه هر تکه ۲۰ است، ما برای هر دوره به ۱۰۰۰ گام برای پیمایش نیاز داریم.

مقدار validation_steps با توجه به نسبت تصاویر آموزشی و ارزیابی مشخص می‌شود. چون در این مساله  ما ۱۰۰۰ عکس آموزشی و ۵۰۰ عکس برای ارزیابی داریم، به ازای هر دو گام آموزش، یک بار ارزیابی مدل  صورت می‌گیرد. پس تعداد گام های ارزیابی در هر دوره، نصف گام های آموزش است. پس این مقدار را برابر  ۵۰ قرار می‌دهیم.

حالا نمودار میزان خطا و میزان دقت را در طول آموزش رسم می‌کنیم.

این تصاویر نشان دهنده وقوع overfitting است. دقت اطلاعات آموزشی ما به نزدیک ۱۰۰٪ رسیده ولی دقت  اطلاعات ارزیابی بعد از ۵ دوره به حدود ۷۰٪ رسیده و بعد از آن تغییری نکرده. چون تعداد تصاویر ما کم است  و شبکه اطلاعات را حفظ کرده و قدرت عمومیت بخشی ندارد.

شبکه با Dropout

برای جلوگیری از این اتفاق روش Dropout را امتحان می‌کنیم.

حالا دوباره نمودار های دقت و خطا را بررسی می‌کنیم.

همان طور که تصاویر مشخص است این روش تاثیر اندکی روی سیستم گذاشته و شبکه را کمی بهبود داده  ولی هنوز هم مشکل overfitting برطرف نشده. برای مقابله با این مشکل باید از روش data augmentation  استفاده کنیم که در آینده با آن آشنا خواهیم شد.

در آخر مدل را برای استفاده های بعدی ذخیره می‌کنیم.

 

کدها برگرفته از فصل دو کتاب Deep Learning with Python و گیت هاب نویسنده کتاب و توسعه دهنده  کراس François Chollet است.

آشنایی با سرویس ابری 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

مقدمه‌ای بر شبکه‌های عصبی(2)

تا اینجا به دو مبحث درباره شبکه های عصبی پرداختیم. Activation function  برای تعیین عملکرد تابع خروجی و cost function  برای تعیین عملکرد بد شبکه. و برای بهبود عملکرد تابع مسائل بهینه سازی مطرح شد (مشتقات جزئی). اکنون به مسئله یادگیری(learning) شبکه میپردازیم.

Gradient Descent and Back-propagation

Gradient Descent

Gradient descent  یک الگوریتم بهینه سازی برای پیدا کردن مینیمم یک تابع است.

مثال : در این مسئله یک متغیر(w) داریم. و C  ، cost function  است.

یک وزن رندوم انتخاب میکنیم و مشتق c را نسبت به w محاسبه میکنیم. در نتیجه شیب به دست می آید. که جهت آن از روی علامتش مشخص می شود.

w را به سمت جهتی که به دست آوردیم، حرکت می دهیم. که در اینجا سمت راست است. یعنی باید w را بیشتر کنیم.

که با تکرار این کار در نهایت مقدار cost ، مینیمم می شود. در این نقطه مشتق یا شیب برابر با 0 است. با رسیدن به این مرحله نقطه بهینه پیدا می شود.

همان طور که دیدیم، پیدا کردن مینیمم برای فضای دو بعدی ساده بود. اما در فضاهای n بعدی این کار ساده نخواهد بود. و با شکل های پیچیده تری مواجه خواهیم شد.

پس با استفاده از gradient descent  میتوانیم بهترین پارامتر برای مینیمم کردن cost را به دست آوریم. برای مثال پیدا کردن بهترین مقادیر برای انتخاب وزن نورون های ورودی.

 

Backpropagation 

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

تابع cross entropy

one hot encoded

قبلا دیدیم که در شبکه تعدادی label  داشتیم. برای نشان دادن داده ی مربوط به آن label  به جای نشان دادن داده ، آن را به صورت one hot encoded  نمایش می دهیم. یعنی به تعداد کلاس های موجود 0 میگذاریم و عدد مربوط به کلاس را 1 میکنیم. یعنی به این شکل:

 

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

اما بهتر است برای بهتر شدن شبکه و بالا رفتن قطعیت آن همان گونه که بالاتر گفته شد، بهتر است یکی از خانه ها 1 شده و بقیه 0 باشند.

Cross entropy 

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

Tensorflow playground

Tensorflow playground یک visualization  برای آزمایش شبکه های عصبی است که از طرف سایت tensorflow  اراائه شده است. که میتوان در آن با data های مختلف شبکه را train کرد. میتوان برای شبکه به تعداد دلخواه hidden layer و نورون اضافه کرد. وزن ها نیز به صورت رندوم تعیین شده اند که قابل مشاهده و تغییر اند.

در قسمت بالای صفحه چند آیتم وجود دارد.

1.epoch: تعداد به روز رسانی های شبکه به ازای بررسی همه ی data ها را مشخص میکند.

2.learning rate

3.activation: نوع activation function را مشخص میکند که میتواند linear، sigmoid،tanh  یا relu باشد.

4.regularization: برای مینیمم کردن تابع cost، مجموع توان 2 تمام وزن ها و بایاس ها را محاسبه میکند و مقادیر آنها را محدود میکند تا خیلی بزرگ نباشند تا یک وزن زیاد نتواند تاثیر زیادی روی شبکه داشته باشد و قدرت بین شبکه تقسیم شود و داده را حفظ نکند. میتواند مقادیر none، L1 یا L2 را داشته باشد.

5.regularization rate

6.problem type: نوع الگوریتم را مشخص میکند که classification باشد یا regression.

در قسمت چپ صفحه نیز چند آیتم وجود دارد.

1.data: از این قسمت میتوان از بین انواع dataset های موجود یکی را انتخاب کرد که میزان سختی آن ها متفاوت است.

2.ratio of training to test data: نسبت دیتاهای test و train را مشخص میکند.

3.noise: میزان noise موجود در دیتا را مشخص میکند. که هرچه بالاتر باشد، نشان دهنده ی در هم آمیختن بیشتر data ها است.

4.batch size: تعداد داده هایی را مشخص میکند که شبکه بعد از بررسی آنها، عملیات optimization  را اجرا میکند.