โจทย์
Gradient descent แบบ mini-batch คือวิธีที่ใช้ฝึกโครงข่ายประสาทเทียมแทบทุกตัว: แบ่งข้อมูลเป็น batch เล็ก ๆ แล้วอัปเดตน้ำหนักหลังแต่ละ batch
ฝึก y = w × x + b ด้วยค่าคลาดเคลื่อนกำลังสองเฉลี่ย เริ่มจาก w = 0 และ b = 0 ในแต่ละ epoch ให้แบ่งตัวอย่าง ตามลำดับ เป็น batch ละ batch_size ตัว (batch สุดท้ายอาจเล็กกว่า) สำหรับแต่ละ batch ขนาด n:
- errorᵢ = w × xᵢ + b - yᵢ สำหรับแต่ละตัวอย่างใน batch
- dw = (2 / n) × Σ errorᵢ × xᵢ และ db = (2 / n) × Σ errorᵢ
- w ← w - learning_rate × dw และ b ← b - learning_rate × db
จง implement train_mini_batch(xs, ys, batch_size, learning_rate, epochs)
อินพุต
xs, ys: จุดข้อมูล (ความยาวเท่ากัน)
batch_size: จำนวนตัวอย่างต่อ batch
learning_rate, epochs: ขนาดก้าวและจำนวนรอบที่วนผ่านข้อมูล
เอาต์พุต
คืนค่า [w, b] หลังการฝึก
เงื่อนไข
1 ≤ จำนวนจุด ≤ 1,000, 1 ≤ batch_size ≤ จำนวนจุด, 0 ≤ epochs ≤ 1,000
0 < learning_rate ≤ 1
-100 ≤ แต่ละค่า ≤ 100
ตัวอย่าง
อินพุต:
xs = [1.0, 2.0, 3.0]
ys = [2.0, 4.0, 6.0]
epochs = 1
batch_size = 2
learning_rate = 0.1
ผลลัพธ์ที่คาดหวัง:
expected = [2.44, 1.08]
อินพุต:
std::vector<double> xs = {1.0, 2.0, 3.0};
std::vector<double> ys = {2.0, 4.0, 6.0};
long long epochs = 1;
long long batch_size = 2;
double learning_rate = 0.1;
ผลลัพธ์ที่คาดหวัง:
std::vector<double> expected = {2.44, 1.08};
อินพุต:
double[] xs = new double[] {1.0, 2.0, 3.0};
double[] ys = new double[] {2.0, 4.0, 6.0};
long epochs = 1;
long batch_size = 2;
double learning_rate = 0.1;
ผลลัพธ์ที่คาดหวัง:
double[] expected = new double[] {2.44, 1.08};
คำอธิบาย
Batch 1 คือ x = [1, 2]: error -2 และ -4, dw = -10, db = -6 ดังนั้น w = 1 และ b = 0.6 Batch 2 คือ x = [3] เพียงตัวเดียว: error 1×3 + 0.6 - 6 = -2.4, dw = 2 × (-2.4) × 3 = -14.4 และ db = -4.8 ดังนั้น w = 2.44 และ b = 1.08 ผลลัพธ์: [2.44, 1.08]
อินพุต:
xs = [1.0, 2.0, 3.0, 4.0]
ys = [3.0, 5.0, 7.0, 9.0]
epochs = 1
batch_size = 4
learning_rate = 0.05
ผลลัพธ์ที่คาดหวัง:
expected = [1.75, 0.6]
อินพุต:
std::vector<double> xs = {1.0, 2.0, 3.0, 4.0};
std::vector<double> ys = {3.0, 5.0, 7.0, 9.0};
long long epochs = 1;
long long batch_size = 4;
double learning_rate = 0.05;
ผลลัพธ์ที่คาดหวัง:
std::vector<double> expected = {1.75, 0.6};
อินพุต:
double[] xs = new double[] {1.0, 2.0, 3.0, 4.0};
double[] ys = new double[] {3.0, 5.0, 7.0, 9.0};
long epochs = 1;
long batch_size = 4;
double learning_rate = 0.05;
ผลลัพธ์ที่คาดหวัง:
double[] expected = new double[] {1.75, 0.6};
คำอธิบาย
Batch ที่ใหญ่เท่าชุดข้อมูลก็คือ gradient descent แบบ batch ธรรมดา: อัปเดตหนึ่งครั้งต่อ epoch ผลลัพธ์: [1.75, 0.6]
แนวทางการแก้
ลองทำเองก่อน แล้วค่อยเปิดคำใบ้ทีละข้อ
คำใบ้ 1
ประมวลผล samples ตามลำดับที่กำหนด แล้วอัปเดต parameters ทุก batch แทนที่จะอัปเดตทุกจุด
คำใบ้ 2
สำหรับแต่ละ batch ให้คำนวณ prediction errors ก่อน แล้วใช้ค่าเฉลี่ยร่วมกับ x เพื่อหา gradient สองตัว
คำใบ้ 3
batch สุดท้ายอาจเล็กกว่ากลุ่มอื่น ดังนั้นการสเกล gradient ต้องใช้ขนาดของ batch นั้น
ความซับซ้อนที่คาดหวัง
เวลา O(epochs × n), หน่วยความจำเพิ่ม O(1)
แหล่งอ้างอิง
โจทย์นี้ปรับให้เหมาะกับ CodeUtility กรุณาทำตามคำชี้แจงและข้อจำกัดด้านบน