แนวคิด AI ด้วย Python

ตัวปรับค่าของโครงข่ายประสาทเทียม: 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 วิ่งเลยเป้า

โค้ดตัวอย่าง

รันโค้ด →
main.py
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 และทดสอบกรณีขอบก่อนใช้ชุดข้อมูลที่ใหญ่ขึ้น

  1. เปลี่ยนอินพุตหรือน้ำหนัก แล้วลองทายผลลัพธ์ก่อนรัน
  2. พิมพ์ค่าระหว่างทางออกมาเพื่อดูการคำนวณทีละขั้น
  3. แก้โจทย์ที่ลิงก์ไว้ด้านล่างเพื่อเขียนแนวคิดนี้ด้วยตัวเอง
รันใน Python IDE →

ฝึกด้วยโจทย์

ใช้สิ่งที่เรียนในบทนี้แก้ปัญหาจริง ทุกโจทย์รันในเบราว์เซอร์ พร้อมการทดสอบทันทีและรีวิวจาก AI

โจทย์ทั้งหมด