Multi Label Classification

Multi Label Classification چیست ؟

می دانیم در  شبکه های کانولوشنی که دارای یک سری لایه ی میانی و لایه های ورودی و خروجی هستند ، در لایه های میانی اکثرا از Activation RELU  و در لایه ی خروجی از Activation  های Softmax  و Sigmoid   استفاده می شود.

Activation Sigmoid زمانی استفاده می شود که در لایه ی آخر 1 نورون داشته باشیم که نشان دهنده ی وجود دو کلاس است ، برای مثال زمانی که می خواهیم سگ را از گربه تشخیص دهیم از این تایع استفاده می کنیم که می توان 1 شدن آن را به منزله ی سگ بودن تصویر و 0 بودن آن را منزله ی گربه بودن تصویر در نظر گرفت .

Activation Softmax  زمانی استفاده می شود که بخواهیم بیش از 2 کلاس را تشخیص دهیم ، برای مثال وقتی میخواهیم 5 میوه را به شبکه آموزش دهیم در لایه ی آخر Activation Softmax را استفاده میکنیم که در واقع تبدیل Exponential عدد خروجی لایه ی آخر که مثلا میتواند به صورت اعداد 12- ، 10 ، 5 ، 2 و 6- باشد گرفته شده و با هم جمع میگردد و سپس هرکدام از این اعداد به این حاصل جمع تقسیم می شود ، که اعداد به دست آمده در بازه ی 0 تا 1 خواهند بود . عددی که بیشترین مقدار را داشته بیشترین مقدار را در این بازه خواهد داشت و عددی که کمترین مقدار را داشته کمترین مقدار را در این بازه خواهد داشت ، مثلا عدد 10 به معادل 0.95 میرسد و این نشان دهنده ی برنده بودن کلاس مربوط به این نورون خواهد بود .

اشکال توابع Sigmoid و RELU به این شکل می باشد :

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

برای مثال در صورت داشتن یک عکس ماهواره ای که قصد داریم در آن تصویر وجود دریا و جنگل و … را بدانیم باید به شکل دیگری عمل کنیم ، و در واقع باید در لایه ی آخر نورون های مربوط به Object های موجود در تصویر True شده و نورون های مربوط به تصاویر غیر موجود در تصویر False شوند . به این نوع مسایل Multi Label Classification می گویند به عبات دیگر لایه ی اخر میتواند بیشتر از یک برنده داشته باشد و یا هیچ برنده ای نداشته باشد.


پیاده سازی Multi Label Classification در Keras :

برای پیاده سازی Multi Label Classification در Keras ابتدا کلاس های مورد نظر را import و پوشه ی دیتا ست مورد نظر را معرفی می کنیم.

 

 

Dataset مورد استفاده برای مساله ی مورد بررسی دارای پوشه هایی بدین شکل است که داخل هر کدام فولدر های Test  و Train  وجود دارند .

  • پوشه ی Black_jeans
  • پوشه ی Blue_jeans
  • پوشه ی Blue_shirt
  • پوشه ی Red_shirt

بدین ترتیب شبکه ی ما باید به شکلی بتواند تشخیص دهد که آیا در تصویر ورودی Jeans یا shirt  ویا رنگ آبی یا قرمز و یا مشکی وجود دارد یا خیر و چون در لایه ی اخر میتوانیم وجود بیش از یک Object را تشخیص دهیم ( آبی ، قرمز ، مشکی ، shirt و jeans ) این مساله ، مساله ی Multi Label Classification است . در واقع نورون های لایه ی اخر که هر کدام برای یکی از object های مورد نظر می باشند ،  باید به یک Sigmoid متصل شوند تا در صورت تشخیص آن شی در تصویر Fire  کنند.

مثلا در تصویر مقابل هم رنگ قرمز را داریم هم وجود Shirt پس باید در لایه ی اخر نورون های مربوط به رنگ قرمز و Shirt  که هرکدام به یک  Sigmoid  متصل هستند True شده و بقیه False شوند .

و یا اگر تصویر مقابل را که هیچ کدام از Object های shirt و jeans و red و blue و black در آن نیست به شبکه بدهیم در لایه ی آخر هیچ کدام از Sigmoid ها نباید Fire کنند.

همانطور که در کد زیر مشاهده مینمایید بعد از تنظیم مقدار Epochs  ، Learning Rate و Batch Size با استفاده از

میتوانیم تمام تصاویر موجود در دیتاست را در یک لیست به نام imagePaths  نگه  داریم . سپس آن را shuffle میکنیم تا عکس هایی که در یک پوشه بودند پشت هم قرار نگیرند.( دلیل اینکه از DataGenerator استفاده نمیکنیم این است که در Keras هر پوشه به منزله ی یک کلاس میباشد ولی در Multi Label Classification اینگونه نیست )

در مرحله ی بعد تمام عکس ها را خوانده و به سایز 96 در 96 ریسایز کرده و تابع mg_to_array را برایشان فراخانی می  کنیم، سپس آن ها را در لیست Data  میریزیم.

با استفاده از :

از کل آدرس پوشه ی در دیتا ست قسمت نام آن را برمی داریم ، سپس دو کلمه ی آن را از محل “_” جدا می کنیم و در یک لیست به نام Labels میریزیم.

در مرحبه بعد دیتا ها را نرمال می کنیم.

اگر لیست Labels را چاپ کنیم خواهیم دید که لیستی از دوتایی ها خواهد بود که این دوتایی ها نام پوشه هایی هستند که از محل “_” جدا کردیم .

بلاک کد بالا نتیجه ای بدین شکل خواهد داشت :

 

 

 

 

در قسمت بعد از کتابخانه ی scikit-learn استفاده کردیم و با استفاده از MultiLabelBinarizer هر کدام از دوتایی های لیست Labels را به حالت 0 , 1 درآوردیم تا بجای هر کلاسی که در آن بود مقدار 1 و به جای هر کلاسی که آن را وجود نداشت مقدار 0 را قرار دهیم ، به علاوه نام کلاس ها را چاپ کردیم:

اگر لیست Labels را بعد از این عملیات چاپ کنیم آن را به این شکل مشاهده میکنیم :

 

 

 

 

سپس کلاس های موجود را چاپ میکنیم:

 

با استفاده از قطعه کد زیر از کل دیتا های موجود 80 درصد آن را برای Train و 20 درصد آن را برای Test برمیداریم :

سپس عملیات Augmentation را روی دیتا های خوانده شده انجام میدهیم :

شبکه ای با معماری زیر میسازیم :

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

سپس Optimizer Adam را با تنظیم کردن Learning Rate و کم کردن آن در هر epoch ( با تقسیم کردن بر شماره  epoch ) ایجاد میکنیم :

در مرحله آخر مدل را Compile و نمودار های مربوط به Accuracy و Loss در Train Data و Test Dataرا رسم میکنیم میکنیم :

در آخر مدل را با پسوند h5 و Label ها را به صورت Pickle File  ذخیره میکنیم .( اگر با فرمت Pickle.dumps در فایل بنویسیم یک آبجکت پایتونی را مستقیما در یک فایل میریزد و اگر Load آن را صدا بزنیم همان آبجکت پایتونی را Load  میکند .)

 


استفاده از مدل Save شده :

در ابتدا کتابخانه های مورد نیاز را Import میکنیم :

سپس عکسی را از ورودی خوانده ، آن را resize  میکنیم و نمایش میدهیم :

سپس عکس را به سایز 96 در 96 resize و با تقسیم بر 255 آن را نرمال میکنیم ، به علاوه تابع img_to_array را فراخانی کرده و بعد با exapnd_dim یک dimension به آن اضافه میکنیم ( چون به صورت دیفالت با batch کار می کند و با اضافه کردن یک dimension ، انگار به آن یک batch میدهیم که در واقع در آن یک عکس بیشتر نداریم )

آدرس مدل و Label ها را که به صورت Pickle File ذخیره کرده بودیم  ، مشخص میکنیم .

سپس مدل و Label ها را Load میکنیم :

عکس مورد نظر را به مدل می دهیم و از بالاترین احتمالات دوتای اول آن را روی عکس چاپ میکنیم .

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

که خروجی مطابق زیر خواهد داشت :

 

 

 

همانطور که مشاهده میکنید کلاس های red و shirt با بیشترین احتمالات درست تشخیص داده شده اند.