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کنیم و عکس جدید میخواهد مفید نیست!

نگاهی به فرآیند بینایی در مغز

یکی از سخت ترین کارهایی که در مغز انجام می شود فرآیند بینایی است و به همین دلیل 50 درصد از مغز به بینایی و پردازش های مربوط به آن اختصاص یافته است.
همانطور که در تصویر زیر مشخص است فرآیند بینایی در مغز به صورت سلسله مراتبی از ناحیه ی v1 شروع میشود و با گذر از نواحی v2 و v4 به ناحیه ی IT می رسد.

که در ناحیه ی IT با کار گذاشتن الکترودها و گرفتن خروجی های مختلف بر اساس دیدن اشیاء مختلف می توان به صورت تجربی تشخیص داد که فرد چه چیزی را می بینید. در واقع با بررسی خروجی های ناحیه IT میتوان چیزی که فرد در لحظه دیده است را تشخیص داد. به عنوان مثال می توان فردی را که در حال خواب دیدن است زیر آزمایش قرار داد و با گرفتن خروجی های این ناحیه خواب او را ضبط کرد و بعد از بیدار شدن خوابش را به صورت یک فیلم به او نشان داد.
چرا فرآیند بینایی در مغز به صورت سلسله مراتبی است؟
با کار گذاشتن الکترود در بخشهای مختلف مغز یک موجود می توان فهمید که بر اساس چیزی که میبیند در قسمت های مختلف مغزش یک سری اکتیویشن های مختلفی اتفاق می افتد. به عنوان مثال در قسمت v2 در 60 میلی ثانیه اکتیویشن نشان داده می شود و در قسمت IT حدودا بعد از 100 میلی ثانیه اکتیویشن نشان داده می شود. بنابراین می توان نتیجه گرفت که این اتفاق ها بر اساس یک سلسله مراتب خاص هست که نشان داده می شود:

چرا مغز نیاز به تبدیل تصاویر از محیط پیکسل دارد؟ یا به عبارتی دیگر چرا مغز نیاز به داشتن این سلسله مراتب دارد؟ چون دیتاها در دنیای واقعی بی نهایت است لذا ما با مفهومی تحت عنوان Invariant object recognition (بازشناسی اشیا مستقل از تغییرات آنها) سروکار خواهیم داشت. به عنوان مثال ممکنه ما اتومبیل های مختلفی را داشته باشیم ولی تمام انواع اتومبیل ها در رنگها و اندازه های مختلف را تحت عنوان اتومبیل می شناسیم.

فضاهای نورونی خوب و بد

اگر یک شی  به صورت زیر روی فضای نورونی n-بعدی ترسیم کنیم هرکدام از نورون ها مقداری خواهند داشت و در نتیجه یک نقطه در این فضای نورونی مشخص می‌شود:

اگر این شئ تغییراتی کند، به عنوان مثال اگر سر شخص کمی بچرخد در همان فضا موقعیت سر شخص بر اساس مقادیر مختلف هرکدام از محورهای نورونی مقداردهی می شود و اگر تمام تغییرات یک فرد را در این فضای n بعدی رسم کنیم می‌توانیم  یک حجم در این فضا را به این شئ خاص در تمام تغییراتش نسبت داد.
اکنون یک فضای نورونی خوب را به صورت زیر می‌توان ترسم کرد:

و فضای نورونی یک شخص را با یک ابرصفحه (در فضای دو بعدی با خط، در سه بعدی با صفحه و در فضای n بعدی با ابرصفحه) تفکیک کنیم و به آن بفهمانیم که اگر بالای ابرصفحه را دیدی شخص A و اگر پایین صفحه را دیدی شخص B را دیده ایی.
مسئله ایی که در اینجا مطرح میشود این است که اگر مشخصه ها را به صورت پیکسلی و درهم تنیده به صورت زیر داشته باشیم ما نمیتوانیم با استفاده از ابر صفحه فضاها را از هم تفکیک کنیم:


در اینجا مغز در قالب ساختار سلسله مراتبی قابلیت تفکیک این فضای پیکسلی را دارد یعنی به صورت زیر میتواند فضای A و B را ازهم جدا کند:

بعد از این تجزیه می توان با یک طبقه‌بند ساده A و B را تشخیص داد. بر این اساس اگر به انسان یک شی با تغییرات خاصی نشان بدهند این شی در فضایی خاصی از این فضای نورونی قرار میگیرد و اگر یک شی دیگر را نشان بدهند باز در قسمت دیگری از این فضای نورونی قرار خواهد گرفت.