Deep reinforcement learning

Sanparith Marukatat
NECTEC
Published in
4 min readOct 1, 2017

หลังจากโพส 2 อันก่อนหน้านี้ (Reinforcement Learning และ Policy Learning) คราวนี้มาลองดูโค้ดด้วยดีกว่า

โค้ดข้างล่างนี้ก็ยังใช้ Keras เป็นหลักเพราะอ่านง่ายอยู่ ถ้าอ่านจบแล้วจะเห็นว่าสิ่งที่สำคัญไม่ใช่ tool ที่ใช้เท่าไร แต่เป็นว่าเราจะสร้าง NN หน้าตาอย่างไร และจะ train มันด้วย loss function อะไรมากกว่า

โจทย์ CartPole

ผมสนใจโจทย์ที่เราสามารถแบ่งเป็น episode ย่อย ๆ ได้ ตัวอย่างง่าย ๆ ก็คือ CartPole จาก gym.openai.com สำหรับโจทย์นี้เราต้องการ balance ไม้ให้ตั้งอยู่ได้นานที่สุด ถ้าเป็นสมัยก่อนเราอาจต้องมานั่งเขียนแบบจำลองฟิสิกส์ของการเคลื่อนที่สำหรับไม้นี้เอง แต่ตอนนี้เราสามารถโหลดมันมาใช้ได้อย่างง่ายๆ
สิ่งที่สำคัญสำหรับเราคือ

  • action มีได้ 2 อย่าง
  • state นั้นอยู่ในรูปเวคเตอร์ 4 มิติ

ข้อมูลทั้งสองนี้จำเป็นในการสร้าง NN สำหรับเรา

โครงสร้างของโปรแกรมคร่าวๆ คือ

ในโค้ดข้างบนนี้เราจะเล่นทั้งหมด 5000 ครั้ง โดยในแต่ละครั้งเราจะเก็บข้อมูล 1 episode ไว้ปรับ Agent ก่อน จากนั้นเราจึงทำการปรับ Agent และทดสอบดูว่ามันแก้โจทย์นี้ได้หรือยัง

สำหรับโจทย์นี้ถ้าเราเลี้ยงไม้อยู่ได้นานเกิน 195 รอบ ก็จะถือว่า episode นั้นสำเร็จ และถ้าเราทำสำเร็จติดต่อกัน 100 episodes ก็จะถือว่าปัญหานี้ solved แล้ว
นี่เป็น setting ที่เขาบอกไว้บนเว็บ ควรรู้ว่าปัญหาอื่น ๆ ของ gym.openai นั้นอาจไม่มี condition ของการ solve ก็ได้

สำหรับในโค้ดนี้เราแบ่งการเดินของ Agent ออกเป็น 2 แบบคือ 1) แบบ explore ที่อนุญาตให้สุ่มตาเดิน และ 2) แบบไม่ exploreที่เลือกตาเดินแบบ deterministic ตามแผนที่ถูก train มา

ในการเดินแบบ explore เราจะใช้การเลือก action แบบ epsilon-greedy นั่นคือถ้าเราสุ่มได้ค่าที่น้อยกว่า epsilon เราจะเลือก action แบบสุ่ม และถ้าเราได้มากกว่า epsilon เราจะเลือก action ตามแผน
เมื่อเวลาผ่านไปเราจะลดค่า epsilon นี้ลงเรื่อย ๆ เพื่อเปลี่ยนแนวทางจากการ explore action หลาย ๆ แบบเป็นการ exploit action ที่น่าจะดี

ข้างล่างนี้เป็นตัวอย่างของการเลือก action จาก DQN

DQN

เป็นการใช้ NN เพื่อ implement Q-learning โดย Q Network นี้มีลักษณะเด่นคือ

  • รับ state เป็น input
  • มีจำนวน output node เท่ากับจำนวน action ที่เป็นไปได้
  • เนื่องจากค่าของฟังก์ชัน Q นั้นไม่ได้มี range จำกัดดังนั้นเราจะใช้ activation ในชั้น output เป็น linear และใช้ mean squared error เป็น loss function
  • สำหรับ state s, action a, และ next state s’ ใน episode หนึ่ง ๆ เราตั้ง target target(s,a) จาก
  • จากนั้นสำหรับ input s ให้ desired output เป็นเวคเตอร์ที่มีค่า Q(s,a) เดิมหมด ยกเว้นที่โหนด a ให้ใส่ค่า target(s,a) แทน
  • เรากำหนดให้ Agent ของเรามี memory สำหรับจำตาเดินต่าง ๆ ไว้ ซึ่งเมื่อจบแต่ละ episode เราจะทำการสุ่มตาเดินเหล่านี้มาทำการปรับ โดยจำนวนที่สุ่มถูกกำหนดด้วย batch_size และเราทำการปรับแบบจำลองผ่านฟังก์ชัน train_on_batch

REINFORCE และ Actor-Critic

REINFORCE นั้นใช้ NN 1 ตัวเราจะเรียกมันว่า Policy Network ซึ่งมีลักษณะเด่นคือ

  • รับ state เป็น input
  • มีจำนวน output node เท่ากับจำนวน action ที่เป็นไปได้
  • ชั้น output ใช้ Softmax activation และเราจะ train โดย Categorical Cros-Entropy เป็น loss function
  • เราจะ train โดยใช้ค่าถ่วงน้ำหนัก (sample weight) ด้วย
    สำหรับ state s, action a, และ next state s’ ใน episode หนึ่ง ๆ เรากำหนด ค่าถ่วงน้ำหนักสำหรับตัวอย่าง (s,a) จากค่า discounted reward to go จาก s จนจบ episode

สังเกตว่านิยามของ reward to go นี้ก็เหมือนกับค่าประโยชน์ (utility) ของ state s (ที่อยู่ในโพสแรก) ดังนั้นแทนที่เราจะคำนวณ discounted reward to go จาก episode จริง ๆ เราอาจพิจารณาค่าประมาณของประโยชน์ของ state แทน โดยใช้ NN อีกอันหนึ่งก็ได้ เราจะเรียก NN นี้ว่า Value Network

Value Network นั้นลักษณะเด่นคือ

  • รับ state เป็น input
  • มี output 1 node
  • ชั้น output ใช้ linear activation และเราจะ train โดย mean squared error

เราเรียกการเรียนที่ใช้ Policy Network และ Value Network นี้ร่วมกันว่า Actor-Critic method
ถ้าเป็น REINFORCE ธรรมดาเราจะคำนวณ reward to go จาก episode ที่เก็บไว้โดยตรง

การสร้าง NN ทั้งสองนี้ก็ทำได้แบบตรงไปตรงมาคือ

สมมติให้ v_w เป็น Value Network นี้

สำหรับ state s, action a, และ next state s’ ใน episode หนึ่ง ๆ ให้ target สำหรับสอน Value Network คือ target(s) และค่าถ่วงน้ำหนักสำหรับ (s,a) คือ weight(s) นั้นคำนวณจาก

ขั้นตอนการ train NN ทั้งสองนั้นเป็นไปตาม

ส่งท้าย

สังเกตว่า target สำหรับ update Q Network นั้นอิงค่า output จากตัว Q Network เองด้วย เปรียบเสมือนกับ target ที่เรากำลังพยายามประมาณนั้นเปลี่ยนไปพร้อม ๆ กัน ซึ่งทำให้การ train นั้นสับสนอยู่
หนึ่งในวิธีเพิ่มความเสถียรในการเรียนคือใช้ค่า output จาก Q Network อันเก่า มาคำนวณ target แทน และทำการปรับ Q Network เก่านี้ นาน ๆ ครั้ง
แนวความคิดนี้ไม่ใหม่มากนักผมจำ reference ที่เคยเห็นไม่ได้แล้ว แต่ตอนนี้เราเรียกมันว่า Double DQN (D-DQN)

จริง ๆ แล้ว target ใน Value Network เองก็สามารถถูกปรับโดยวิธีเดียวกันด้วย อันนี้ไม่แน่ใจว่ามีใครทำหรือยัง

ตอนแรกที่ลองทำนี่ผมใช้ Q Network แทน Value Network โดยเลือก max ค่า output เอาตอนคำนวณ target แต่ดูแล้วผลไม่ค่อยเสถียรเท่าไร บางทีก็ fail ไปเลย อาจเป็นเพราะที่บอกในโพสก่อนนี้ว่าค่าจาก Value Network ที่เราเอามาเป็น baseline ที่ลบออกจาก target นั้นต้องไม่ขึ้นกับ action ซึ่งสำหรับ Q Network มันไม่จริง

โค้ดตัวอย่างโจทย์นี้ที่ใช้ DQN และ Actor-Critic หาดูได้จาก https://github.com/peune/CartPole
Have fun :)

--

--