|
3 weeks ago | |
---|---|---|
.. | ||
solution | 3 weeks ago | |
README.md | 3 weeks ago | |
assignment.md | 3 weeks ago | |
notebook.ipynb | 3 weeks ago |
README.md
การแนะนำเกี่ยวกับ Reinforcement Learning และ Q-Learning
Sketchnote โดย Tomomi Imura
Reinforcement learning เกี่ยวข้องกับแนวคิดสำคัญสามประการ: ตัวแทน (agent), สถานะ (state) และชุดของการกระทำ (action) ต่อสถานะหนึ่งๆ โดยการดำเนินการกระทำในสถานะที่กำหนด ตัวแทนจะได้รับรางวัล ลองจินตนาการถึงเกมคอมพิวเตอร์ Super Mario คุณคือ Mario คุณอยู่ในด่านเกม ยืนอยู่ข้างหน้าผา ด้านบนคุณมีเหรียญ คุณในฐานะ Mario อยู่ในด่านเกม ณ ตำแหน่งที่เฉพาะเจาะจง ... นั่นคือสถานะของคุณ การก้าวไปทางขวาหนึ่งก้าว (การกระทำ) จะทำให้คุณตกหน้าผา และนั่นจะทำให้คุณได้คะแนนต่ำ อย่างไรก็ตาม การกดปุ่มกระโดดจะทำให้คุณได้คะแนนและยังมีชีวิตอยู่ นั่นคือผลลัพธ์ที่ดีและควรให้คะแนนเชิงบวกแก่คุณ
โดยการใช้ reinforcement learning และตัวจำลอง (simulator) เช่นเกม คุณสามารถเรียนรู้วิธีการเล่นเกมเพื่อเพิ่มรางวัลให้ได้มากที่สุด ซึ่งก็คือการมีชีวิตรอดและทำคะแนนให้ได้มากที่สุด
🎥 คลิกที่ภาพด้านบนเพื่อฟัง Dmitry อธิบายเกี่ยวกับ Reinforcement Learning
แบบทดสอบก่อนเรียน
ความต้องการเบื้องต้นและการตั้งค่า
ในบทเรียนนี้ เราจะทดลองกับโค้ดใน Python คุณควรสามารถรันโค้ดใน Jupyter Notebook จากบทเรียนนี้ได้ ไม่ว่าจะบนคอมพิวเตอร์ของคุณหรือในระบบคลาวด์
คุณสามารถเปิด สมุดบันทึกบทเรียน และทำตามบทเรียนนี้เพื่อสร้างโปรเจกต์
หมายเหตุ: หากคุณเปิดโค้ดนี้จากระบบคลาวด์ คุณจะต้องดึงไฟล์
rlboard.py
ซึ่งใช้ในโค้ดของสมุดบันทึกนี้ด้วย ให้วางไฟล์นี้ในไดเรกทอรีเดียวกับสมุดบันทึก
บทนำ
ในบทเรียนนี้ เราจะสำรวจโลกของ Peter and the Wolf ซึ่งได้รับแรงบันดาลใจจากนิทานดนตรีโดยนักประพันธ์ชาวรัสเซีย Sergei Prokofiev เราจะใช้ Reinforcement Learning เพื่อให้ Peter สำรวจสภาพแวดล้อม เก็บแอปเปิ้ลอร่อยๆ และหลีกเลี่ยงการพบกับหมาป่า
Reinforcement Learning (RL) เป็นเทคนิคการเรียนรู้ที่ช่วยให้เราสามารถเรียนรู้พฤติกรรมที่เหมาะสมที่สุดของ agent ใน environment โดยการทดลองหลายๆ ครั้ง ตัวแทนในสภาพแวดล้อมนี้ควรมี เป้าหมาย ซึ่งกำหนดโดย reward function
สภาพแวดล้อม
เพื่อความง่าย ลองพิจารณาโลกของ Peter เป็นกระดานสี่เหลี่ยมขนาด width
x height
ดังนี้:
แต่ละช่องในกระดานนี้สามารถเป็นได้:
- พื้นดิน ซึ่ง Peter และสิ่งมีชีวิตอื่นๆ สามารถเดินได้
- น้ำ ซึ่งแน่นอนว่าไม่สามารถเดินได้
- ต้นไม้ หรือ หญ้า ซึ่งเป็นที่ที่คุณสามารถพักผ่อนได้
- แอปเปิ้ล ซึ่งเป็นสิ่งที่ Peter ยินดีที่จะหาเพื่อเลี้ยงตัวเอง
- หมาป่า ซึ่งเป็นอันตรายและควรหลีกเลี่ยง
มีโมดูล Python แยกต่างหาก rlboard.py
ซึ่งมีโค้ดสำหรับทำงานกับสภาพแวดล้อมนี้ เนื่องจากโค้ดนี้ไม่สำคัญต่อการทำความเข้าใจแนวคิดของเรา เราจะนำเข้าโมดูลและใช้มันเพื่อสร้างกระดานตัวอย่าง (code block 1):
from rlboard import *
width, height = 8,8
m = Board(width,height)
m.randomize(seed=13)
m.plot()
โค้ดนี้ควรพิมพ์ภาพของสภาพแวดล้อมที่คล้ายกับภาพด้านบน
การกระทำและนโยบาย
ในตัวอย่างของเรา เป้าหมายของ Peter คือการหาแอปเปิ้ล ในขณะที่หลีกเลี่ยงหมาป่าและสิ่งกีดขวางอื่นๆ เพื่อทำเช่นนี้ เขาสามารถเดินไปรอบๆ ได้จนกว่าจะพบแอปเปิ้ล
ดังนั้น ในตำแหน่งใดๆ เขาสามารถเลือกหนึ่งในสี่การกระทำต่อไปนี้: ขึ้น, ลง, ซ้าย และขวา
เราจะกำหนดการกระทำเหล่านี้เป็นพจนานุกรม และจับคู่กับคู่ของการเปลี่ยนแปลงพิกัดที่สอดคล้องกัน ตัวอย่างเช่น การเคลื่อนไปทางขวา (R
) จะสอดคล้องกับคู่ (1,0)
(code block 2):
actions = { "U" : (0,-1), "D" : (0,1), "L" : (-1,0), "R" : (1,0) }
action_idx = { a : i for i,a in enumerate(actions.keys()) }
สรุปแล้ว กลยุทธ์และเป้าหมายของสถานการณ์นี้คือ:
-
กลยุทธ์ ของตัวแทนของเรา (Peter) ถูกกำหนดโดยสิ่งที่เรียกว่า policy นโยบายคือฟังก์ชันที่ส่งคืนการกระทำในสถานะที่กำหนด ในกรณีของเรา สถานะของปัญหาถูกแสดงโดยกระดาน รวมถึงตำแหน่งปัจจุบันของผู้เล่น
-
เป้าหมาย ของ reinforcement learning คือการเรียนรู้นโยบายที่ดีที่จะช่วยให้เราสามารถแก้ปัญหาได้อย่างมีประสิทธิภาพ อย่างไรก็ตาม ในฐานะพื้นฐาน ลองพิจารณานโยบายที่ง่ายที่สุดที่เรียกว่า random walk
Random walk
ลองแก้ปัญหาของเราด้วยการใช้กลยุทธ์ random walk ก่อน ด้วย random walk เราจะสุ่มเลือกการกระทำถัดไปจากการกระทำที่อนุญาต จนกว่าจะถึงแอปเปิ้ล (code block 3)
-
ใช้ random walk ด้วยโค้ดด้านล่าง:
def random_policy(m): return random.choice(list(actions)) def walk(m,policy,start_position=None): n = 0 # number of steps # set initial position if start_position: m.human = start_position else: m.random_start() while True: if m.at() == Board.Cell.apple: return n # success! if m.at() in [Board.Cell.wolf, Board.Cell.water]: return -1 # eaten by wolf or drowned while True: a = actions[policy(m)] new_pos = m.move_pos(m.human,a) if m.is_valid(new_pos) and m.at(new_pos)!=Board.Cell.water: m.move(a) # do the actual move break n+=1 walk(m,random_policy)
การเรียก
walk
ควรส่งคืนความยาวของเส้นทางที่สอดคล้องกัน ซึ่งอาจแตกต่างกันไปในแต่ละรอบ -
รันการทดลองเดินหลายครั้ง (เช่น 100 ครั้ง) และพิมพ์สถิติที่ได้ (code block 4):
def print_statistics(policy): s,w,n = 0,0,0 for _ in range(100): z = walk(m,policy) if z<0: w+=1 else: s += z n += 1 print(f"Average path length = {s/n}, eaten by wolf: {w} times") print_statistics(random_policy)
สังเกตว่าความยาวเฉลี่ยของเส้นทางอยู่ที่ประมาณ 30-40 ก้าว ซึ่งค่อนข้างมาก เมื่อพิจารณาจากระยะทางเฉลี่ยไปยังแอปเปิ้ลที่ใกล้ที่สุดซึ่งอยู่ที่ประมาณ 5-6 ก้าว
คุณยังสามารถดูการเคลื่อนไหวของ Peter ระหว่าง random walk ได้:
Reward function
เพื่อทำให้นโยบายของเราฉลาดขึ้น เราจำเป็นต้องเข้าใจว่าการเคลื่อนไหวใด "ดีกว่า" การเคลื่อนไหวอื่นๆ เพื่อทำเช่นนี้ เราจำเป็นต้องกำหนดเป้าหมายของเรา
เป้าหมายสามารถกำหนดในแง่ของ reward function ซึ่งจะส่งคืนค่าคะแนนสำหรับแต่ละสถานะ ยิ่งตัวเลขสูง ยิ่งได้รางวัลที่ดี (code block 5)
move_reward = -0.1
goal_reward = 10
end_reward = -10
def reward(m,pos=None):
pos = pos or m.human
if not m.is_valid(pos):
return end_reward
x = m.at(pos)
if x==Board.Cell.water or x == Board.Cell.wolf:
return end_reward
if x==Board.Cell.apple:
return goal_reward
return move_reward
สิ่งที่น่าสนใจเกี่ยวกับ reward function คือในกรณีส่วนใหญ่ เราจะได้รับรางวัลที่สำคัญเมื่อสิ้นสุดเกมเท่านั้น ซึ่งหมายความว่าอัลกอริทึมของเราควรจำ "ก้าวที่ดี" ที่นำไปสู่รางวัลเชิงบวกในตอนท้าย และเพิ่มความสำคัญของมัน ในทำนองเดียวกัน การเคลื่อนไหวทั้งหมดที่นำไปสู่ผลลัพธ์ที่ไม่ดีควรถูกลดความสำคัญลง
Q-Learning
อัลกอริทึมที่เราจะพูดถึงที่นี่เรียกว่า Q-Learning ในอัลกอริทึมนี้ นโยบายถูกกำหนดโดยฟังก์ชัน (หรือโครงสร้างข้อมูล) ที่เรียกว่า Q-Table ซึ่งบันทึก "ความดี" ของแต่ละการกระทำในสถานะที่กำหนด
มันถูกเรียกว่า Q-Table เพราะมักจะสะดวกที่จะแสดงมันเป็นตาราง หรืออาร์เรย์หลายมิติ เนื่องจากกระดานของเรามีมิติ width
x height
เราสามารถแสดง Q-Table โดยใช้อาร์เรย์ numpy ที่มีรูปร่าง width
x height
x len(actions)
: (code block 6)
Q = np.ones((width,height,len(actions)),dtype=np.float)*1.0/len(actions)
สังเกตว่าเราเริ่มต้นค่าทั้งหมดใน Q-Table ด้วยค่าที่เท่ากัน ในกรณีของเรา - 0.25 ซึ่งสอดคล้องกับนโยบาย "random walk" เพราะการเคลื่อนไหวทั้งหมดในแต่ละสถานะมีค่าเท่ากัน เราสามารถส่ง Q-Table ไปยังฟังก์ชัน plot
เพื่อแสดงภาพตารางบนกระดาน: m.plot(Q)
ในแต่ละช่องจะมี "ลูกศร" ที่ระบุทิศทางการเคลื่อนไหวที่ต้องการ เนื่องจากทุกทิศทางเท่ากัน จึงแสดงเป็นจุด
ตอนนี้เราจำเป็นต้องรันการจำลอง สำรวจสภาพแวดล้อมของเรา และเรียนรู้การแจกแจงค่าของ Q-Table ที่ดีกว่า ซึ่งจะช่วยให้เราหาเส้นทางไปยังแอปเปิ้ลได้เร็วขึ้นมาก
แก่นของ Q-Learning: สมการ Bellman
เมื่อเราเริ่มเคลื่อนไหว การกระทำแต่ละครั้งจะมีรางวัลที่สอดคล้องกัน กล่าวคือ เราสามารถเลือกการกระทำถัดไปตามรางวัลที่ได้รับทันที อย่างไรก็ตาม ในสถานะส่วนใหญ่ การเคลื่อนไหวจะไม่บรรลุเป้าหมายของเราในการไปถึงแอปเปิ้ล และดังนั้นเราจึงไม่สามารถตัดสินใจได้ทันทีว่าทิศทางใดดีกว่า
จำไว้ว่าสิ่งที่สำคัญไม่ใช่ผลลัพธ์ทันที แต่เป็นผลลัพธ์สุดท้ายที่เราจะได้รับเมื่อสิ้นสุดการจำลอง
เพื่อพิจารณารางวัลที่ล่าช้า เราจำเป็นต้องใช้หลักการของ dynamic programming ซึ่งช่วยให้เราคิดเกี่ยวกับปัญหาในเชิงเวียนกลับ
สมมติว่าเรากำลังอยู่ในสถานะ s และเราต้องการเคลื่อนไปยังสถานะถัดไป s' โดยการทำเช่นนี้ เราจะได้รับรางวัลทันที r(s,a) ซึ่งกำหนดโดย reward function บวกกับรางวัลในอนาคตบางส่วน หากเราสมมติว่า Q-Table ของเราสะท้อนถึง "ความน่าสนใจ" ของแต่ละการกระทำอย่างถูกต้องแล้ว ในสถานะ s' เราจะเลือกการกระทำ a' ที่สอดคล้องกับค่ามากที่สุดของ Q(s',a') ดังนั้น รางวัลในอนาคตที่ดีที่สุดที่เราสามารถได้รับในสถานะ s จะถูกกำหนดเป็น max
การตรวจสอบนโยบาย
เนื่องจาก Q-Table แสดง "ความน่าสนใจ" ของแต่ละการกระทำในแต่ละสถานะ การใช้งานเพื่อกำหนดการนำทางที่มีประสิทธิภาพในโลกของเราจึงค่อนข้างง่าย ในกรณีที่ง่ายที่สุด เราสามารถเลือกการกระทำที่มีค่าที่สูงที่สุดใน Q-Table: (code block 9)
def qpolicy_strict(m):
x,y = m.human
v = probs(Q[x,y])
a = list(actions)[np.argmax(v)]
return a
walk(m,qpolicy_strict)
หากคุณลองรันโค้ดด้านบนหลายครั้ง คุณอาจสังเกตเห็นว่าบางครั้งมัน "ค้าง" และคุณต้องกดปุ่ม STOP ในโน้ตบุ๊กเพื่อหยุดการทำงาน สาเหตุเกิดจากสถานการณ์ที่สองสถานะ "ชี้" ไปยังอีกสถานะหนึ่งในแง่ของค่าที่เหมาะสมที่สุดใน Q-Value ซึ่งทำให้ตัวแทนเคลื่อนที่วนเวียนระหว่างสถานะเหล่านั้นอย่างไม่สิ้นสุด
🚀ความท้าทาย
งานที่ 1: ปรับฟังก์ชัน
walk
เพื่อจำกัดความยาวสูงสุดของเส้นทางโดยจำนวนก้าวที่กำหนด (เช่น 100) และดูว่าโค้ดด้านบนคืนค่านี้เป็นครั้งคราว
งานที่ 2: ปรับฟังก์ชัน
walk
เพื่อไม่ให้กลับไปยังสถานที่ที่เคยไปมาก่อนแล้ว วิธีนี้จะป้องกันไม่ให้walk
วนซ้ำ อย่างไรก็ตาม ตัวแทนอาจยังคงติดอยู่ในตำแหน่งที่ไม่สามารถหลบหนีได้
การนำทาง
นโยบายการนำทางที่ดีกว่าคือแบบที่เราใช้ระหว่างการฝึก ซึ่งรวมการใช้ประโยชน์จากข้อมูลที่มีอยู่และการสำรวจ ในนโยบายนี้ เราจะเลือกแต่ละการกระทำด้วยความน่าจะเป็นที่สัมพันธ์กับค่าที่อยู่ใน Q-Table กลยุทธ์นี้อาจยังทำให้ตัวแทนกลับไปยังตำแหน่งที่เคยสำรวจแล้ว แต่ดังที่คุณเห็นจากโค้ดด้านล่าง มันส่งผลให้เส้นทางเฉลี่ยสั้นลงมากไปยังตำแหน่งที่ต้องการ (จำไว้ว่า print_statistics
รันการจำลอง 100 ครั้ง): (code block 10)
def qpolicy(m):
x,y = m.human
v = probs(Q[x,y])
a = random.choices(list(actions),weights=v)[0]
return a
print_statistics(qpolicy)
หลังจากรันโค้ดนี้ คุณควรได้ความยาวเส้นทางเฉลี่ยที่สั้นลงมากกว่าเดิม อยู่ในช่วงประมาณ 3-6
การตรวจสอบกระบวนการเรียนรู้
ดังที่เราได้กล่าวไว้ กระบวนการเรียนรู้เป็นการสร้างสมดุลระหว่างการสำรวจและการใช้ความรู้ที่ได้รับเกี่ยวกับโครงสร้างของพื้นที่ปัญหา เราได้เห็นว่าผลลัพธ์ของการเรียนรู้ (ความสามารถในการช่วยตัวแทนค้นหาเส้นทางสั้นไปยังเป้าหมาย) ดีขึ้น แต่สิ่งที่น่าสนใจคือการสังเกตว่าความยาวเส้นทางเฉลี่ยเปลี่ยนแปลงอย่างไรระหว่างกระบวนการเรียนรู้:
สรุปการเรียนรู้
-
ความยาวเส้นทางเฉลี่ยเพิ่มขึ้น: สิ่งที่เราเห็นคือในตอนแรก ความยาวเส้นทางเฉลี่ยเพิ่มขึ้น สาเหตุอาจเกิดจากเมื่อเราไม่รู้อะไรเกี่ยวกับสภาพแวดล้อม เรามักจะติดอยู่ในสถานะที่ไม่ดี เช่น น้ำหรือหมาป่า เมื่อเราเรียนรู้มากขึ้นและเริ่มใช้ความรู้นี้ เราสามารถสำรวจสภาพแวดล้อมได้นานขึ้น แต่เรายังไม่รู้ตำแหน่งของแอปเปิ้ลดีนัก
-
ความยาวเส้นทางลดลงเมื่อเรียนรู้มากขึ้น: เมื่อเราเรียนรู้มากพอ มันจะง่ายขึ้นสำหรับตัวแทนในการบรรลุเป้าหมาย และความยาวเส้นทางเริ่มลดลง อย่างไรก็ตาม เรายังเปิดโอกาสให้สำรวจ ดังนั้นเรามักจะเบี่ยงเบนออกจากเส้นทางที่ดีที่สุด และสำรวจตัวเลือกใหม่ ๆ ทำให้เส้นทางยาวกว่าที่ควรจะเป็น
-
ความยาวเพิ่มขึ้นอย่างฉับพลัน: สิ่งที่เราสังเกตเห็นในกราฟคือในบางจุด ความยาวเพิ่มขึ้นอย่างฉับพลัน สิ่งนี้บ่งชี้ถึงลักษณะสุ่มของกระบวนการ และในบางครั้งเราอาจ "ทำลาย" ค่าสัมประสิทธิ์ใน Q-Table โดยการเขียนทับด้วยค่าที่ใหม่ สิ่งนี้ควรลดลงโดยการลดอัตราการเรียนรู้ (เช่น ในช่วงท้ายของการฝึก เราปรับค่าของ Q-Table เพียงเล็กน้อย)
โดยรวมแล้ว สิ่งสำคัญคือต้องจำไว้ว่าความสำเร็จและคุณภาพของกระบวนการเรียนรู้ขึ้นอยู่กับพารามิเตอร์ เช่น อัตราการเรียนรู้ การลดอัตราการเรียนรู้ และตัวคูณลดค่า พารามิเตอร์เหล่านี้มักถูกเรียกว่า hyperparameters เพื่อแยกความแตกต่างจาก parameters ซึ่งเราปรับแต่งระหว่างการฝึก (เช่น ค่าสัมประสิทธิ์ใน Q-Table) กระบวนการค้นหาค่าที่ดีที่สุดสำหรับ hyperparameters เรียกว่า hyperparameter optimization และมันสมควรได้รับการพูดถึงในหัวข้อแยกต่างหาก
แบบทดสอบหลังการบรรยาย
งานที่ได้รับมอบหมาย
ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI Co-op Translator แม้ว่าเราจะพยายามให้การแปลมีความถูกต้องมากที่สุด แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดพลาดซึ่งเกิดจากการใช้การแปลนี้