กลับไปยังโจทย์
ปานกลาง 0 ข้อที่แก้แล้ว อัตราผ่าน 0%

การอัปเดต Q-learning

ใช้การอัปเดต Q-learning กับลำดับประสบการณ์ และดูรางวัลไหลย้อนกลับไปยังสถานะก่อนหน้า

สิ่งที่คุณจะได้เรียนรู้

  • อัปเดตค่าของการกระทำจากประสบการณ์
  • ใช้ตัวประกอบส่วนลดและสถานะสิ้นสุด
  • ดูรางวัลไหลย้อนกลับไปยังสถานะก่อนหน้า

โจทย์

Q-learning เรียนรู้ว่าแต่ละการกระทำดีแค่ไหนในแต่ละสถานะ หรือ Q(s, a) จากประสบการณ์เพียงอย่างเดียว หลังจากทำการกระทำ a ในสถานะ s ได้รับ reward และไปถึงสถานะ s':

  • target = reward ถ้า episode จบแล้ว (done = 1)
  • target = reward + gamma × ค่าสูงสุดเหนือ a' ของ Q(s', a') ในกรณีอื่น
  • Q(s, a) ← Q(s, a) + alpha × (target - Q(s, a))

เริ่มด้วยค่า Q ทุกตัวเป็น 0 แล้วใช้การเปลี่ยนสถานะตามลำดับ

จง implement q_learning(num_states, num_actions, transitions, alpha, gamma)

อินพุต

num_states, num_actions: ขนาดของตาราง

transitions: หนึ่งแถว [state, action, reward, next_state, done] ต่อหนึ่งก้าว

alpha: อัตราการเรียนรู้

gamma: ตัวประกอบส่วนลด

เอาต์พุต

คืนตาราง Q เป็นเมทริกซ์ที่มีหนึ่งแถวต่อสถานะและหนึ่งคอลัมน์ต่อการกระทำ

เงื่อนไข

1 ≤ num_states, num_actions ≤ 100, 0 ≤ จำนวนการเปลี่ยนสถานะ ≤ 10,000

-100 ≤ reward ≤ 100, done เป็น 0 หรือ 1

0 < alpha ≤ 1, 0 ≤ gamma ≤ 1

ตัวอย่าง

ตัวอย่างที่ 1
อินพุต:
alpha = 0.5
gamma = 0.9
num_states = 2
num_actions = 2
transitions = [
    [0, 1, 0, 1, 0],
    [1, 0, 10, 0, 1]
]

ผลลัพธ์ที่คาดหวัง:
expected = [
    [0.0, 0.0],
    [5.0, 0.0]
]
อินพุต:
double alpha = 0.5;
double gamma = 0.9;
long long num_states = 2;
long long num_actions = 2;
std::vector<std::vector<long long>> transitions = {
    {0, 1, 0, 1, 0},
    {1, 0, 10, 0, 1}
};

ผลลัพธ์ที่คาดหวัง:
std::vector<std::vector<double>> expected = {
    {0.0, 0.0},
    {5.0, 0.0}
};
อินพุต:
double alpha = 0.5;
double gamma = 0.9;
long num_states = 2;
long num_actions = 2;
long[][] transitions = new long[][] {
    new long[] {0, 1, 0, 1, 0},
    new long[] {1, 0, 10, 0, 1}
};

ผลลัพธ์ที่คาดหวัง:
double[][] expected = new double[][] {
    new double[] {0.0, 0.0},
    new double[] {5.0, 0.0}
};

คำอธิบาย

ก้าวแรกยังไม่พบรางวัล: target = 0 + 0.9 × max(Q[1]) = 0 ดังนั้น Q[0][1] ยังเป็น 0 ก้าวที่สองจบ episode ด้วยรางวัล 10: Q[1][0] = 0 + 0.5 × (10 - 0) = 5

ตัวอย่างที่ 2
อินพุต:
alpha = 0.5
gamma = 0.9
num_states = 2
num_actions = 2
transitions = [
    [1, 0, 10, 0, 1],
    [0, 1, 0, 1, 0]
]

ผลลัพธ์ที่คาดหวัง:
expected = [
    [0.0, 2.25],
    [5.0, 0.0]
]
อินพุต:
double alpha = 0.5;
double gamma = 0.9;
long long num_states = 2;
long long num_actions = 2;
std::vector<std::vector<long long>> transitions = {
    {1, 0, 10, 0, 1},
    {0, 1, 0, 1, 0}
};

ผลลัพธ์ที่คาดหวัง:
std::vector<std::vector<double>> expected = {
    {0.0, 2.25},
    {5.0, 0.0}
};
อินพุต:
double alpha = 0.5;
double gamma = 0.9;
long num_states = 2;
long num_actions = 2;
long[][] transitions = new long[][] {
    new long[] {1, 0, 10, 0, 1},
    new long[] {0, 1, 0, 1, 0}
};

ผลลัพธ์ที่คาดหวัง:
double[][] expected = new double[][] {
    new double[] {0.0, 2.25},
    new double[] {5.0, 0.0}
};

คำอธิบาย

ก้าวเดิมแต่สลับลำดับ Q[1][0] กลายเป็น 5 ก่อน ก้าวจากสถานะ 0 จึงเห็นค่านี้: target = 0 + 0.9 × 5 = 4.5 และ Q[0][1] = 0.5 × 4.5 = 2.25 รางวัลไหลย้อนกลับไปหนึ่งสถานะ

แนวทางการแก้

ลองทำเองก่อน แล้วค่อยเปิดคำใบ้ทีละข้อ

คำใบ้ 1

แต่ละ transition อัปเดต table entry เดียว โดยใช้แค่ค่าปัจจุบันกับ best estimate จาก state ถัดไป

คำใบ้ 2

ตั้งค่า Q table เริ่มต้นเป็นศูนย์ แล้วประมวลผล transitions ตามลำดับและอัปเดตทันทีหลังแต่ละครั้ง

คำใบ้ 3

ถ้า episode จบลง จะไม่มี future value ให้บวก และไม่ควรใช้ next-state maximum

ความซับซ้อนที่คาดหวัง

เวลา O(T * A), หน่วยความจำเพิ่ม O(S * A)

แหล่งอ้างอิง

โจทย์นี้ปรับให้เหมาะกับ CodeUtility กรุณาทำตามคำชี้แจงและข้อจำกัดด้านบน

เรียนรู้จากคนอื่น

แนวทางจากชุมชน

ยังไม่มีวิธีทำที่เผยแพร่ ลองแก้โจทย์นี้เพื่อแชร์วิธีแรก