GAN به زبان ساده

شبکه خصمانه مولد (Generative Adversarial Networks) یا به اختصار GAN یکی از موفق ترین مدل‌ها برای تولید داده است. موضوع GAN یکی از داغ ترین موضوعات حوزه یادگیری ماشین (Machine Learning) است و طبعا مقالات آموزشی فراوان به زبان فارسی و انگلیسی برای این نوع شبکه موجود است. اما اکثر این مقالات بر پیاده‌سازی این شبکه‌ها و یا تشریح آنها به واسط ریاضیات پیچیده متمرکز هستند. ما در این مقاله می‌خواهیم بیشتر به ایده اصلی GAN‌ها بپردازیم واین کار را بدون استفاده از کد یا ریاضیات پیچیده انجام بدهیم. برای این کار در قدم اول باید مسئله اصلی و سوال بنیادی مدل‌های مولد (Generative Models) را یاد بگیریم. سپس بررسی کنیم که نیازمندی‌های این مسئله چگونه پایه‌های ایده GAN را بنا می‌کنند و نهایتا GAN را شکل می‌دهند.به شهربازی خوش آمدیدفرض کنید که ما صاحب یک شهربازی هستیم. در این شهربازی دستگاهی وجود دارد که از کاربر یک اسکناس ده هزار تومانی دریافت می‌کند و یک جایزه به کاربر می‌دهد. ارزش این جایزه می‌تواند بین هزار تا صدهزار تومان باشد. این ماشین بین بازدیدکنندگان شهربازی بسیار پرطرفدار است چون هر از چند گاهی بازدیدکنندگان جایزه‌های خوبی از ماشین دریافت می‌کنند. در نتیجه می‌بینند که کلکی در کار نیست و احتمال بردن جایزه‌های خوب وجود دارد. از سوی دیگر ما هم این دستگاه را خیلی دوست داریم چون برای ما هم بسیار سودآور است. در نتیجه، الگوریتم انتخاب جایزه این ماشین بسیار خوب عمل می‌کند چون هم رضایت بازدیدکنندگان و هم رضایت ما را تامین می‌کند.در نتیجه، برای افزایش سود می‌خواهیم نمونه‌های بیشتری از این ماشین را به شهربازی‌مان اضافه کنیم. ولی یک مشکل سر راههمان است. این ماشین‌ها خیلی خیلی گران هستند و خرید و انتقال آن‌ها کار ساده‌ای نیست. بنابراین تصمیم می‌گیریم که خودمان چنین ماشینی را بسازیم. اما ما به الگوریتم انتخاب جایزه‌ی این ماشین - که مهم‌ترین بخش آن است - دسترسی نداریم. طراحی این بخش نیز بسیار مهم و کاری باظرافت است. اگر احتمال دادن جایزه‌های گرانقیمت را خیلی پایین بیاوریم، رضایت بازدیدکنندگان را از دست می‌دهیم و اگر این احتمال را خیلی بالا ببریم، ماشین دیگر سودآور نخواهد بود. پیدا کردن این تناسب حساس، بخش اصلی مسئله است.داده‌ای که برای شروع کار به آن دسترسی داریم، سابقه عملکرد ماشین است. در اولین قدم می‌توانیم توزیع (Distribution) ارزش جایزه‌هایی که ماشین در گذشته داده است را رسم کنیم. اگر شکل این توزیع، شبیه یکی از توزیع‌های احتمالی (Probability Distribution) شناخته شده باشد، راه‌حل مسئله را پیدا کرده‌ایم. ما می‌توانیم از آن توزیع احتمالی به عنوان هسته اصلی راه‌حل‌مان استفاده کنیم و از آن نمونه (Sample) بگیریم. نمونه‌ها برای ما مشخص می‌کند که جایزه‌ی بعدی باید چه ارزشی داشته باشد.اما اگر توزیع ارزش جایزه‌ها پیچیده باشد و شبیه توزیع‌های احتمالی شناخته شده نباشد، کار سخت می‌شود. در اینجا ما نیاز داریم تا روشی را بسازیم که تنها با دیدن نمونه‌های یک توزیع احتمالی ناشناخته بتواند آن توزیع را یاد بگیرد. به عبارت ساده‌تر، ما می‌خواهیم به الگوریتمی‌برسیم که بتواند قیمت جایزه‌های گذشته را نگاه کند ، منطق روشی که آنها را تولید کرده است را یاد بگیرد و نهایتا به ما براساس آن منطق بگوید که چگونه باید جایزه بدهیم. در نتیجه، «مسله اصلی در زمینه تولید داده یادگیری هر چه دقیق تر توزیع احتمالی داده‌ها است».تولید داده با دگردیسیبرای شروع، ما یک مجموعه داده داریم که به آن داده‌های واقعی (Real Data) می‌گوییم. برای حل مسله تولید، ما به مدلی نیاز داریم که داده‌های واقعی را دریافت کند و به ما داده‌هایی ساختگی مشابه داده‌های واقعی بدهد. به داده‌های ساختگی تولید شده توسط مدل، داده‌های جعلی (Fake Data) گفته می‌شود. حالا که ما هدف‌مان را به روشنی بیان کردیم باید اولین قدم‌های‌مان را به سمت پیاده‌سازی برداریم. برای این کار بهتراست با روشی که با آن آشنا هستیم، شروع کنیم. در نگاه اول به نظر می‌رسد روشی آشنا که دقیقا در راستای هدفمان باشد، وجود ندارد. اما اگردیدمان را به مسئله کمی‌تغییر دهیم می‌توانیم به راهکار هوشمندانه‌ای برسیم. برای شرح این راهکار، باید در ابتدا با مفهوم تابع انتقال (Transform Function) آشنا شویم.فرض کنید که یک مجموعه نمونه از یک توزیع احتمالی در دسترس داریم. با اعمال یک تابع انتقال بر روی این مجموعه می‌توانیم این مجموعه نمونه‌ها را از توزیع احتمالی اصلی (توزیع مبدا) به توزیع احتمال دلخواه دیگری (توزیع مقصد) منتقل کنیم. از لحاظ تئوری می‌توانیم نمونه‌های هر توزیعی را از توزیع مبدا به توزیع مقصد منتقل کنیم. اما تعریف تحلیلی تابع انتقال برای هر انتقالی ممکن نیست.حالا به سوال اصلی‌مان برگردیم. ما می‌توانیم مسئله تولید داده‌ را در قالب تعریف یک تابع انتقال تعریف کنیم. ما با یک توزیع احتمالی آشنا شروع می‌کنیم. معمولا توزیع احتمالی نرمال به میانگین صفر و انحراف از معیار یک را انتخاب می‌کنیم. به این توزیع احتمالی فضای نهفته (Latent Space) گفته می‌شود. حالا می‌خواهیم یک تابع انتقال تعریف کنیم که بتواند نمونه‌هایی از فضای نهفته را به فضای داده‌ها منتقل کند. به بیان ساده‌تر، تابع انتقال موردنظر ما یک نمونه از فضای نهفته دریافت می‌کند و یک نمونه داده در فضای داده به ما تحویل می‌دهد. یعنی ما بالاخره موفق به تولید داده شدیم! اما همچنان مشکلی بر سر راه‌مان است. تعریف این تابع انتقال به صورت تحلیلی ممکن نیست چون ما اطلاعی از فضای داده‌ها یا همان توزیع مقصد نداریم. پس راه چاره چیست؟ استفاده از شبکه‌های عصبی! چطور؟ ما همیشه از شبکه‌های عصبی برای تخمین توابعی که به صورت تحلیلی قابل تعریف نیستند استفاده می‌کنید. در اینجا هم دقیقا شرایط مشابهی با تابع انتقال داریم. با اینکه می‌توانیم ورودی، خروجی و عملکرد موردنظرمان را تعریف کنیم، قادر به تعریف تحلیلی این تابع نیستیم. این شبکه عصبی ، Generator یا شبکه مولد نامیده می‌شود.حال که می‌خواهیم از شبکه عصبی استفاده کنیم باید یک تابع زیان (Loss Function) متناسب با هدف‌مان تعریف کنیم تا بتوانیم شبکه مولد را آموزش دهیم (Train).آموزش با انتقاد سازندهبه صورت کلی، یک تابع زیان عملکرد یک شبکه عصبی را نسبت به هدف آن ارزیابی می‌کند و برای بهبود عملکرد آن بازخوردی در قالب گرادیان ارائه می‌کند. در اینجا ما به تابع زیانی نیاز داریم که پیروی داده‌های ساختگی از توزیع احتمالی داده‌های واقعی را ارزیابی کند. به بیان دیگر، ما به داده‌ی زیانی نیاز داریم که به ما بگوید داده‌های ساختگی ما چقدر واقعی به نظر می‌رسند. اما ما همچنان اطلاعی از توزیع احتمالی داده‌های واقعی نداریم. در حقیقت این مشکل اولیه ما بود که در حال حل آن هستیم. ولی ما می‌توانیم با مقایسه داده‌های واقعی و ساختگی به نتیجه مشابهی برسیم.فرض کنید که تابع زیان ما بتواند بین داده ساختگی و داده واقعی تمیز قائل شود.پس ما می‌توانیم داده‌های ساختگی را به این تابع بدهیم.داده‌هایی که توسط این تابع زیان به عنوان داده واقعی تشخیص داده شوند، بازخوردی لازم ندارند. اما برای آن دسته از داده‌ها ساختگی که توسط این تابع زیان به عنوان داده جعلی شناسایی شوند، تابع زیان به شبکه مولد بازخوردی ارائه می‌دهد تا به وسیله ی آن خودش را در راستای تولید داده‌های مشابه واقعی بهبود دهد.به عبارت دقیق‌تر، ما می‌توانیم از یک تابع دسته بند (classifier) به عنوان تابع زیان استفاده کنیم که قادر است داده‌های ورودی را در دسته‌های واقعی یا جعلی دسته بندی کند. هدف شبکه مولد این است که داده‌هایی که تولید می‌کند توسط این تابع به عنوان داده واقعی تشخیص داده شوند. برای داده‌های ساختگی که در دسته داده جعلی قرار بگیرد، شبکه مولد از تابع زیان می‌پرسد که چه تغییراتی را لازم دارد تا این داده‌ها هم واقعی به نظر برسند. تابع زیان جواب را در قالب گرادیان به ما برمی‌گرداند تا وزن‌های شبکه مولد را تغییر دهیم.به نظر می‌رسید مسئله را تقریبا حل کرده‌ باشیم. اما همچنان یک مشکل دیگر بین ما و جواب نهایی قرار دارد. هرچند که تابع زیانی که پیشنهاد دادیم، نیازمندی‌های مسله را ارضا می‌کند اما در عمل پیاده‌سازی این تابع زیان ممکن نیست. بنابراین ما به تابعی رسیدیم که می‌توانیم ورودی، خروجی و مشخصه‌های آن را تعریف کنیم اما نمی‌توانیم آن را به صورت مستقیم پیاده‌سازی کنیم. این شرایط دقیقا شبیه شرایطی است که در مورد تابع انتقال با آن برخورد کرده بودیم. بنابراین از راه حل مشابه می‌توانیم استفاده کنیم. یعنی استفاده از یک شبکه عصبی دسته‌بند به عنوان تابع زیان. ما این شبکه عصبی را Discriminator یا شبکه ممیز می‌نامیم.بهتر از همه، ما با شبکه‌های دسته بند به صورت کامل آشنایی داریم. می‌دانیم از چه ساختاری استفاده کنیم، چطور آن‌ها را آموزش دهیم و از چه تابع زیانی استفاده کنیم. اما آموزش دو شبکه عصبی در کنار هم کار ساده‌ای نیست. پس در آخرین قدم باید روشی برای آموزش آن‌ها پیدا کنیم.یادگیری با چاشنی دعوا!اگر در شروع روند آموزش، یک شبکه دسته‌بند بی نقص به عنوان شبکه ممیز داشتیم، کارمان بسیار ساده می‌شد. اما متاسفانه در ابتدای روند آموزش GAN، شبکه ممیز‌مانند شبکه مولد نیاز به آموزش دارد. به علاوه ما نمی‌توانیم قبل از شروع روند آموزش شبکه مولد، شبکه ممیز را آموزش دهیم چون برای آموزش شبکه ممیز به نمونه‌های ساختگی شبکه مولد نیاز داریم. همانطور که می‌بینید، این دو شبکه برای آموزش به یک دیگر وابسته هستند. شبکه مولد برای بهبود نیاز به بازخورد شبکه ممیز دارد و همچنین باید شبکه ممیز را با توجه به تغییرات شبکه مولد به وسیله نمونه‌های ساختگی همواره به روز نگه داریم. پس این دو شبکه را باید در کنار هم آموزش دهیم. در این راستا، هر قدم (Step) در روند آموزش، به دو مرحله تقسیم می‌شود. در مرحله اول شبکه ممیز را با داده‌های واقعی از مجموعه و داده‌های ساختگی از شبکه مولد آموزش دهیم تا دسته بندی این داده‌ها را یاد بگیرد. در مرحله دوم، شبکه مولد را به وسیله شبکه ممیز برای تولید داده‌های ساختگی شبیه واقعیت آموزش می‌دهیم. این روش، آموزش خصمانه (Adversarial Training) نامیده می‌شود. زمانی که از آموزش خصمانه برای تولید داده استفاده کنیم، به شبکه خصمانه مولد (Generative Adversarial Network) یا به اختصار GAN می‌رسیم.در اینجا سوالی ممکن است پیش بیاید: اگر دوباره به روند آموزش شبکه نگاه کنیم، اثری از خصومت دیده نمی‌شود پس دلیل این نامگذاری چیست؟ برای اینکه به پاسخ این سوال برسیم، باید به هدف این دو شبکه توجه کنیم. هدف شبکه ممیز این است که به بهترین شکل ممکن داده‌های ساختگی را شناسایی کند و هدف شبکه مولد این است که داده‌هایی شبیه واقعیت تولید کند، به طوریکه شبکه ممیز نتواند آن‌ها از داده‌های واقعی تشخیص دهد. به عبارت دیگر، شبکه مولد تلاش می‌کند تا شبکه ممیز را گول بزند و شبکه ممیز تلاش می‌کند تا گول نخورد. این اهداف متناقض اساس روند آموزش ما را تشکیل می‌دهند.در طول روند آموزش، هر دو شبکه با توجه به هدف خودش پیش می‌روند. در نهایتا، داده‌های ساختگی شبکه مولد به میزانی به داده‌های واقعی نزدیک می‌شوند که شبکه ممیز قادر به شناسایی آن‌ها نیست. و اینجا نقطه‌ای است که روند آموزش به پایان می‌رسد.که GAN آسان نمود اول ولی افتاد مشکل‌هایک راه حل جالب و پیچیده برای یک مسئله سخت است. محققین مدت‌هاست برای یافتن یک راه حل سریع، بهینه و دقیق برای مسئله تولید داده تلاش می‌کنند و با GAN، ما این راه حل را یافته ایم. این شبکه راه را برای کاربردهای هیجان انگیزهموار می‌کند. اما قبل از اینکه در مورد این فرصت‌ها صحبت کنیم، باید مشکلات معمول GAN را مرور کنیم. اول اینکه شبکه مولد یک شبکه عصبی است و این بدان معناست که این شبکه ذاتا یک جعبه سیاه (Black Box) است. در پایان روند آموزش، شبکه مولد توزیع احتمالی داده را یاد گرفته است اما این اطلاعات در وزن‌های داخل شبکه کد شده‌اند و ما به طور مستقیم به آن دسترسی نداریم. زمانی که ما با داده‌های با ابعاد کوچک (Low Dimensionality) -‌ مانند داده‌های یک بعدی - کارمی‌کنیم، می‌توانیم با روش نمونه گیری (Sampling) به این اطلاعات دسترسی داشته باشیم. اما وقتی با داده‌های با ابعاد بالا (High Dimensionality) -‌ مانند عکس‌ها - کار می‌کنیم، نمی‌توانیم به اطلاعات مربوط به توزیع احتمالی داده‌ها دست پیدا کنیم و تنها به نمونه‌ها دسترسی داریم.علاوه بر این، تابع زیان در GAN برخلاف شبکه‌های عصبی دیگر، اطلاعاتی در مورد روند آموزش به ما نمی‌دهد. در نتیجه، در طول روند آموزش باید نمونه‌ها را به صورت دستی بررسی کنیم تا از پیشرفت شبکه مولد آگاه شویم.در نهایت، همانطور که پیش‌تر ذکر کردیم، روند آموزش GAN از طریق رقابت دو شبکه صورت می‌گیرد. پس اگراین دو شبکه از رقابت دست بکشند، روند آموزش متوقف می‌شود و متاسفانه این رویداد به طور معمول اتفاق میفتد. به عبارت دیگر، فراهم کردن شرایطی که این دو شبکه رقابت را برای مدت طولانی ادامه بدهند، ساده نیست. توقف رقابت به دلایل مختلفی روی می‌دهد. برای مثال اگر یکی از شبکه‌ها ساختار بهتری داشته باشد وسریع تر از شبکه دیگر پیشرفت کند، ممکن است در راستای هدفش آنقدر قوی بشود که رقابت متوقف شود. پس ساختار شبکه‌ها به نسبت یکدیگر باید در تعادل باشد. اما در اینجا ساختار متعادل چگونه باید تعیین شود؟ متاسفانه پاسخ سرراستی به این سوال وجود ندارد و این ساختارها باید از طریق آزمون و خطا مشخص شوند.به این دلایل، روند آموزش GAN بسیار ناپایداراست. راه حل‌های فراوانی برای این مشکل ارائه شده است اما این راه حل‌ها معمولا شرایط خاصی را می‌طلبند و یا قسمتی از مشکل را برطرف می‌کنند اما مشکلاتی را در بخش‌های دیگه اضافه می‌کنند. به طور خلاصه، ناپایداری روند آموزش GAN هنوز یک مشکل حل نشده است و محققان زیادی در حال حاضر بر روی این مسئله کار می‌کنند.هزار راه نرفتهماشین گرانقیمتی که مقاله را با آن آغاز کردیم نماد پروسه‌های زمان بر و طاقت فرسای تولید داده است. فرض کنید که ما یک مجموعه داده متوسط از چهره افراد داریم و برای مسئله‌ای نیاز به مجموعه داده بزرگتری داریم. یک روش برای افزایش اندازه این مجموعه داده این است که دوربین عکاسی‌مان را برداریم و از چهره مردم عکس بگیریم و به مجموعه داده‌مان اضافه کنیم. اما همانطور که به سادگی قابل تشخیص است این روش بسیار زمان‌بر است. حال اگر یک GAN را بر روی این مجموعه آموزش دهیم در نهایت یک مدل مولد خواهیم داشت که می‌تواند تصویر چهره به تعدادی که می‌خواهیم و در مدت کوتاهی تولید کند. در نتیجه یکی از اصلی ترین کاربردهای GAN تقویت مجموعه داده‌ها (Data Augmentation) است.اما کمبود داده تنها دلیل استفاده از GAN نیست. بیایید دوباره به مجموعه داده چهره‌ها برگردیم. فرض کنیم که می‌خواهیم از این داده‌ها در یک پروژه استفاده کنیم. در اینجا احتمالا به مشکل حریم خصوصی برمی‌خوریم. اما اگر از چهره افرادی که وجود ندارند استفاده کنیم ، کسی اعتراض نخواهد کرد. بنابراین، GAN یک راه حل هوشمندانه برای مسئله حریم خصوصی حول محور داده‌ها در اختیار ما می‌گذارد.در حال حاضر، تحقیقات فراوانی در مورد GAN در حال انجام است و هر روز یک روش بهبود یا یک کاربرد نوین برای GAN ارائه می‌شود. با این حال هنوز مسائل فراوانی برای تحقیق وجود دارند و ما همچنان در ابتدای راه هستیم.