سلااام! این مقاله خیلی خودمونیه با این حال هدف اینه با هم معماری معروف DQN ای که در مقاله "Playing Atari with Deep Reinforcement" شد رو یک بررسی بکنیم و ببینیم و نسخه بهبود یافتش یعنی Double DQN که بعضا بهش D2QN هم میگن (یا حداقل من میگم:دی ) چیه و در نهایت پیاده سازیش توی PyTorch رو ببینم. که خب انتظار میره اندکی پایتون و شبکه عصبی بلد باشید و البته سعی میکنیم درگیر فرمولها زیاد نشیم. قبل از شروع این داستان زیبا بیاید مطمئن شیم یسری چیزای پایه ای رو میدونیم:
action = np.argmax(q[state]) # q[state] = [1.2 50 23 -0] action == 1
اما احتمالا توی پاراگراف آخر متوجه شدید که برای یسری مسائل ممکنه این جدول اینقد بزرگ بشه که هرچی RAM توی دنیا هست رو هم جمع کنیم نتونیم ذخیرش کنیم. اما خب راهکار چیه؟ یه تقریب با دقت خوب راه حل بهتری نیست؟ هممم! وقتی اسم تقریب توی قرن 21 به گوشمون میخوره ناخواسته ذهنمون میره سمت یادگیری عمیق و شبکه های عصبی. از قضا حضرات هم همین تفکر رو پیش گرفتن و مقاله فوق رو دادن. به طور خلاصه شما یک شبکه عصبی دارید که با گرفتن یک موقعیت مقدارهای مختلف q رو به ازای هر action خروجی میده عکسی شبیه زیر:
اما به هرحال باید این شبکه عصبی تربیت بشه مگه نه؟ و صد البته supervised هم هست پس نیاز به یه یسری داده داریم و خروجی متناسبشون. در بالا ما 5 پارامتر اساسی رو معرفی کردیم. در مقاله ذکر شده اگر مقادیر فوق درون یک بافر ذخیره بشن میتونیم بعد ازشون برای تربیبت شبکه عصبمیون استفاده کنیم. لکن برای این مسئله نیاز است که که یک کلاسی طراحی بشه.
دلیل اصلی که از deque به جای list استفاده کردیم اینه که میتونیم بهش یه طول مشخصی رو اتلاق کنیم و بگیم در صورتی که پر شدی قدیمی ترین عضوت رو حذف کن و یه جای خالی فراهم کن.
و خب جالبه بدونید روند یادگیری در یادگیری عمیق به شدت کندتر از مسائل supervised مرسوم هست چون شما یه بار کل دادتون رو fit نمی کنید بلکه مثلا مجبورید هزاربار مدلتون رو fit کنید به همین جهت شما نمی تونید از کل داده ای که ذخیره کردید استفاده کنید بلکه باید از یک تعداد مشخصش استفاده کنید مگر اینکه این قدرت سخت افزاریش رو داشته باشد. یعنی شما مدل رو روی یک batch رندوم از تجربه های حاضر تربیت می کنید.
برای محاسبه مقادیر مطلوب ما یه کاری مشابه قبل رو میکنیم:
و خب داده ورودیمون یعنی x میشه state های فعلی و داده های خروجی رو هم بر حسب فرمول بالا محاسبه کنیم. اما صبر کنید بیاید وارد کد نشیم و همین اول کار همین رو بهبود بدیم. اگر از یک شبکه عصبی استفاده کنیم خیلی غیر stable میشه روند یادگیریمون! یعنی چی این؟
همونطور که مبینید اون نقطه optimal هر بار جاش تغییر پیدا میکنه و نمیشه بهش رسید. اما خب چیکار کنیم که هم شبکه عصبیمون یادبگیره هم این نقطه جاش ثابت بمونه؟ آها! یه شبکه عصبی دیگه بیاریم :دی
به شبکه عصبی اول که رفتار agent رو بهبود میده بهش میگیم online_model و شبکه عصبی که ازش برای محاسبه q(St+1) استفاده می کنیم میگیم target_model. این قضیه منجر به این میشه که اون نقطه optimal توی فضای بهینه سازیمون ثابت بمونه:
در زمانی که این دو شبکه عصبی رو تعریف میکنیم باید این نکته رو دقت داشته باشیم که وزناشون دقیقا یکسان باشن یعنی target_model وزنهای online_model رو داشته باشه. و همچنین بعد از هر episode یا fit شدن مجددا وزنهای online_model برابر target_model قرار داده میشن تا روند یادگیری بهتر بشه. معماری شبکه عصبمیمون چون روی محیط CartPole-v1 هست یک ANN سادس:
نکته: در صورتی که محیط پیچیده باشه یعنی مثلا state ها به صورت تصویر باشن باید از CNN استفاده بشه که در مقاله اصلی هم همینه.
اما اینجا برای محاسبه مقدار بهینه و استفاده از target_model یکم روندمون فرق میکنه که میتونیم خلاصش کنیم به مراحل زیر:
مقادیر St فعلی رو با استفاده از online_model محاسبه و میزان خطاش رو با مقدار مطلوب محاسبه میکنیم و در نهایت backprop میکنیم توی شبکه عصبی:
در نهایت باید با Hyper Parameters ها و اندکی صبر و حوصله این مغر سیلیکونی یاد میگیره چطوری بازی کنه.
نکتهای که خواستم همین اول کار بگم اینه که از episode های 400 به بعد Agent امون عملا دیگه explore ای انجام نمیده در نتیجه reward ای که میگیره کاملا کار خودشه
محیط CartPole-v1
محیط LunarLander-v2
امیدوارم مفید واقع شده باشه هر چند ضعف زیاد داره این مقاله چون خیلی مبحث مفصلیه من هم تازه کار :دی
ولی خودم سر پیاده سازیش خیلی بدبختی کشیدم گفتم شاید دفعه بعد گرهای از کسی باز کنه
با این حال کدها رو هم داخل گیتهاب قرار دادم و میتونید خودتون بررسی کنید و اگر جاییش سوالی بود خوشحال میشم کمکی کنم.
https://github.com/mhyrzt/D2QN