ตัวปรับค่าของโครงข่ายประสาทเทียม: SGD, Momentum และ Adam ใน Python
ตัวปรับค่า (optimizer) คือกฎที่เปลี่ยนเกรเดียนต์ให้เป็นการอัปเดตน้ำหนัก gradient descent ธรรมดาใช้แค่เกรเดียนต์ปัจจุบัน momentum จำทิศทางที่ผ่านมา ส่วน Adam ยังปรับขนาดก้าวให้น้ำหนักแต่ละตัวด้วย
แนวคิดแบบเข้าใจง่าย
ตัวปรับค่า (optimizer) คือกฎที่เปลี่ยนเกรเดียนต์ให้เป็นการอัปเดตน้ำหนัก gradient descent ธรรมดาใช้แค่เกรเดียนต์ปัจจุบัน momentum จำทิศทางที่ผ่านมา ส่วน Adam ยังปรับขนาดก้าวให้น้ำหนักแต่ละตัวด้วย
เปรียบเทียบ gradient descent ธรรมดา, momentum และ Adam โดยหาค่าต่ำสุดของฟังก์ชันเดียวกันทีละขั้น
ประเด็นสำคัญ
- momentum เก็บความเร็วไว้ จึงกลิ้งผ่านบริเวณที่ราบและหลุมเล็ก ๆ ได้
- Adam เก็บค่าเฉลี่ยเคลื่อนที่ของเกรเดียนต์และของเกรเดียนต์กำลังสอง
- การแก้ไขไบแอส (หารด้วย 1 − βᵗ) ช่วยปรับค่าเฉลี่ยเหล่านั้นในช่วงก้าวแรก ๆ
- การกำหนดน้ำหนักเริ่มต้นที่ดีและ mini-batch ก็ช่วยให้การฝึกเร็วและเสถียรขึ้น
ควรใช้เมื่อใด?
- เข้าใจสิ่งที่เกิดขึ้นภายในโครงข่ายประสาทเทียมและไลบรารี AI
- เข้าใจแนวคิดก่อนลงมือเขียนเองในโจทย์ที่เกี่ยวข้อง
- เตรียมตัวสำหรับคอร์สแมชชีนเลิร์นนิง การสัมภาษณ์งาน และโปรเจกต์
ลองดูการทำงานจริง
กด เล่น เพื่อให้ตัวปรับค่าสามแบบแข่งกันลงหุบเขาขรุขระเดียวกัน ลองเพิ่ม learning rate เพื่อดู momentum วิ่งเลยเป้า
โค้ดตัวอย่าง
import math
# Minimise f(x) = (x - 3)² with three optimizers. The gradient is 2(x - 3).
grad = lambda x: 2 * (x - 3)
def sgd(steps, lr=0.1):
x = 0.0
for _ in range(steps):
x -= lr * grad(x)
return x
def momentum(steps, lr=0.1, beta=0.9):
x, v = 0.0, 0.0
for _ in range(steps):
v = beta * v + grad(x) # remember the direction we were going
x -= lr * v
return x
def adam(steps, lr=0.3, b1=0.9, b2=0.999, eps=1e-8):
x, m, v = 0.0, 0.0, 0.0
for t in range(1, steps + 1):
g = grad(x)
m = b1 * m + (1 - b1) * g # running mean of gradients
v = b2 * v + (1 - b2) * g * g # running mean of squared gradients
m_hat, v_hat = m / (1 - b1 ** t), v / (1 - b2 ** t)
x -= lr * m_hat / (math.sqrt(v_hat) + eps)
return x
for steps in (5, 20, 50):
print(f"{steps:>2} steps sgd={sgd(steps):.3f} momentum={momentum(steps):.3f} adam={adam(steps):.3f}")
ผลลัพธ์ที่คาดหวัง
5 steps sgd=2.017 momentum=4.741 adam=1.476
20 steps sgd=2.965 momentum=4.048 adam=3.813
50 steps sgd=3.000 momentum=3.091 adam=3.014
หลักการทำงาน
ทั้งสามหาค่าต่ำสุดของ (x − 3)² ซึ่งต่ำสุดที่ x = 3 SGD เคลื่อนที่อย่างสม่ำเสมอ momentum เร่งความเร็วจนเลยเป้าก่อนจะนิ่ง และ Adam ปรับแต่ละก้าวด้วยค่าเฉลี่ยเคลื่อนที่ของเกรเดียนต์และกำลังสองของมัน หลัง 50 ก้าว ทั้งสามเข้าใกล้ 3
เปลี่ยนค่าและรันโปรแกรมด้วย คอมไพเลอร์ Python ออนไลน์ของ CodeUtility โดยไม่ต้องติดตั้ง Python
แบบฝึกหัด
ลองเปลี่ยน input และทดสอบกรณีขอบก่อนใช้ชุดข้อมูลที่ใหญ่ขึ้น
- เปลี่ยนอินพุตหรือน้ำหนัก แล้วลองทายผลลัพธ์ก่อนรัน
- พิมพ์ค่าระหว่างทางออกมาเพื่อดูการคำนวณทีละขั้น
- แก้โจทย์ที่ลิงก์ไว้ด้านล่างเพื่อเขียนแนวคิดนี้ด้วยตัวเอง
ฝึกด้วยโจทย์
ใช้สิ่งที่เรียนในบทนี้แก้ปัญหาจริง ทุกโจทย์รันในเบราว์เซอร์ พร้อมการทดสอบทันทีและรีวิวจาก AI
- การกำหนดน้ำหนักเริ่มต้นแบบ Xavier และ He คำนวณช่วงหรือส่วนเบี่ยงเบนมาตรฐานที่ใช้กำหนดน้ำหนักเริ่มต้นของเลเยอร์ ง่าย
- Gradient descent แบบ mini-batch ฝึกโมเดลเชิงเส้นโดยอัปเดตน้ำหนักหลังแต่ละ batch เล็ก ๆ แทนที่จะรอจนครบทั้งชุดข้อมูล ปานกลาง
- Gradient descent พร้อม momentum ใช้การอัปเดตแบบ momentum ที่เก็บส่วนหนึ่งของก้าวก่อนหน้าไว้ เพื่อให้การฝึกเร่งความเร็วในทิศทางที่คงที่ ง่าย
- ตัวปรับค่า Adam Implement Adam ตัวปรับค่ามาตรฐานของ deep learning ที่ใช้ค่าเฉลี่ยเคลื่อนที่และการแก้ความเอนเอียง ปานกลาง