Lecture3.pdf (49 หน้า — เนื้อหาเดียวกับ Lecture2.pdf หน้า 50-98) · 2603520 Deep Learning

Cost Function & Backpropagation: สอนเครือข่ายให้เรียนรู้ด้วย Chain Rule

นี่คือหัวใจของข้อสอบวิชานี้ และเป็นบทที่ยาวที่สุด. เรื่องราวทั้งบทมีเส้นเดียว: เรามีเครือข่ายที่ทำนายผิด → ต้องมีตัวเลขบอกว่า "ผิดแค่ไหน" (cost function) → ต้องรู้ว่าจะขยับ weight แต่ละตัวไปทางไหน (อนุพันธ์ย่อย) → เครือข่ายลึกทำให้หาอนุพันธ์ตรงๆ ยาก (chain rule ยาว) → backpropagation คือวิธีคำนวณมันอย่างประหยัด. ทุกอย่างที่เหลือในบทนี้ (activation function, regularization, การแบ่งข้อมูล, hyperparameter) คือรายละเอียดที่ห้อยอยู่กับเส้นนี้.

สไลด์ของบทนี้ตั้งใจเว้น "คำตอบตัวเลข" ของตัวอย่างไว้ให้กรอกในคาบ — บทเรียนนี้จะคำนวณให้ครบทุกตัวเลขทุกหน้า (ตรวจด้วย numpy ทุกค่า) พร้อมพิสูจน์ที่มาของสูตร \(\delta\) ทีละขั้น และอธิบายคณิตศาสตร์พื้นฐานทุกตัวตั้งแต่ศูนย์.

อ่านเพิ่มก่อนเริ่ม (แนะนำ)
3Blue1Brown — "Backpropagation calculus" (Essence of Neural Networks ep.4) — อธิบาย chain rule expansion แบบเดียวกับสไลด์นี้ทุกขั้นตอนด้วยภาพเคลื่อนไหว 10 นาที.
ภาพรวมก่อนลงรายละเอียด — Backprop คือการตอบคำถามเดียว

หลังทำ forward ได้ค่าทำนาย \(h(x)\) เทียบกับคำตอบจริง \(y\) แล้ว เราต้องรู้ว่า weight แต่ละตัวควรขยับไปทางไหนและมากแค่ไหน เพื่อให้ cost ลดลง. นั่นคือค่า \(\partial J/\partial\theta\) ของทุก \(\theta\) ในโครงข่าย. Backprop คือวิธีคำนวณอนุพันธ์ทั้งหมดนี้อย่างประหยัด โดยเริ่มจาก error ที่ output แล้วส่ง "ส่วนแบ่งความผิด" (\(\delta\)) ย้อนกลับทีละ layer.

ลำดับงานเสมอ: ① forward (ได้ \(z, a\) ทุก layer) → ② \(\delta\) ที่ output → ③ ส่ง \(\delta\) ย้อนกลับทีละ layer → ④ \(\partial J/\partial\theta = \delta\times a\) → ⑤ อัปเดต \(\theta\).

0. Cost Function และ Parameter Learning: ปัญหาตั้งต้นของทั้งบท

ก่อนพูดถึง backpropagation เลยแม้แต่คำเดียว ต้องตอบคำถามที่ง่ายกว่านั้นมากก่อน: "เครือข่ายของเรารู้ได้อย่างไรว่ามันทำนายผิด?" ลองนึกภาพว่าคุณสอนเด็กทายราคาบ้าน เด็กทายว่า 2 ล้าน ราคาจริง 3 ล้าน. ถ้าคุณบอกแค่ "ผิด" เด็กไม่รู้ว่าต้องปรับมากแค่ไหน. แต่ถ้าคุณบอก "ผิดไป 1 ล้าน" เด็กรู้ทั้งขนาดและทิศทาง. Cost function คือเครื่องมือที่แปลง "ความผิด" ให้เป็นตัวเลขตัวเดียว ที่เอาไปคำนวณต่อได้.

ต้องรู้ก่อน — อนุพันธ์ (derivative) คือ "อัตราการเปลี่ยนแปลง" ไม่ใช่เวทมนตร์

ถ้าคุณไม่เคยเรียนแคลคูลัส อ่านย่อหน้านี้ก่อน เพราะทั้งบทวางอยู่บนมันตัวเดียว.

นิยามแบบภาษาคน: \(\dfrac{dy}{dx}\) แปลว่า "ถ้าขยับ \(x\) ไปนิดเดียว \(y\) จะขยับไปกี่เท่าของนิดนั้น". ลองกับฟังก์ชันจริง \(y = x^2\) ที่ \(x=3\):

สูตรสำเร็จบอกว่า \(\frac{d}{dx}x^2 = 2x = 2(3) = 6\) — ตรงกับที่ลองขยับจริง. ความหมายของเครื่องหมาย: ถ้าอนุพันธ์เป็นบวก แปลว่าเพิ่ม \(x\) แล้ว \(y\) เพิ่ม; ถ้าเป็นลบ แปลว่าเพิ่ม \(x\) แล้ว \(y\) ลด. gradient descent ใช้ข้อนี้ตรงๆ: อยากให้ \(J\) ลด ก็ขยับ \(\theta\) ไปทิศตรงข้ามกับเครื่องหมายของอนุพันธ์.

สูตรที่ใช้บ่อยในบทนี้มีแค่ 4 ตัว: \(\frac{d}{dx}x^n = nx^{n-1}\), \(\frac{d}{dx}e^{x} = e^{x}\), \(\frac{d}{dx}\ln x = \frac{1}{x}\), และ \(\frac{d}{dx}(\text{ค่าคงที่}) = 0\).

ต้องรู้ก่อน — อนุพันธ์ย่อย (partial derivative) \(\partial\) คืออะไร

สัญลักษณ์ \(\partial\) (อ่านว่า "พาร์เชียล") ใช้เมื่อฟังก์ชันมีตัวแปรมากกว่าหนึ่งตัว. \(\dfrac{\partial f}{\partial x}\) แปลว่า "ขยับ \(x\) อย่างเดียว โดยแช่แข็งตัวแปรอื่นไว้ แล้ว \(f\) เปลี่ยนไปเท่าไร".

ตัวอย่างจิ๋ว: \(f(x,y) = x^2y\) ที่จุด \(x=3, y=2\) ⇒ \(f = 9\times2 = 18\).

ทำไมเรื่องนี้สำคัญ: เครือข่ายที่มี weight 1,000 ตัวคือฟังก์ชันที่มีตัวแปร 1,000 ตัว. \(\dfrac{\partial J}{\partial\theta_{ij}^{[l]}}\) คือคำถาม "ถ้าขยับ weight ตัวนี้ตัวเดียว (weight อื่นค้างไว้หมด) cost จะเปลี่ยนไปเท่าไร" — และ backpropagation คือเครื่องจักรที่ตอบคำถามนี้พร้อมกันทั้ง 1,000 ตัวในการไล่ย้อนกลับรอบเดียว.

Cost function slide: cost function measures the accuracy of the hypothesis function, with the regression cost J(theta) = (1/m) sum of (h(x)-y) squared, and the classification cost J(theta) = -(1/m) sum of y log h(x) + (1-y) log(1-h(x)) for one output node
Slide: Cost Function (Lecture3.pdf, p.1)

อาจารย์เปิดบทด้วยประโยคเดียวที่ทำสีไว้: cost function คือฟังก์ชันที่ใช้measure the accuracy of the hypothesis function — วัดว่า hypothesis function (ฟังก์ชันทำนายของเรา \(h_\theta(x)\)) แม่นแค่ไหน. และแยกเป็นสองแบบตามชนิดของปัญหา: Regression Problem · Classification Problem (กรณีหลังในสไลด์คือแบบ 1 output node).

แบบที่ 1 — Regression (ทำนายตัวเลขต่อเนื่อง เช่น ราคาบ้าน):

$$J(\theta) = \frac{1}{m}\sum_{i=1}^{m}\left(h_\theta(x^{(i)}) - y^{(i)}\right)^2$$

เอาผลต่าง (ทำนาย − จริง) ของทุกตัวอย่างมายกกำลังสอง แล้วเฉลี่ย

ทำไมต้องยกกำลังสอง? เพราะ (1) กำจัดเครื่องหมาย — ทำนายเกิน 1 กับทำนายขาด 1 ผิดพอกัน ถ้าไม่ยกกำลังสองมันจะหักล้างกันจนดูเหมือนไม่ผิดเลย และ (2) ลงโทษความผิดใหญ่หนักกว่าความผิดเล็กแบบทวีคูณ (ผิด 2 หน่วยโดนปรับ 4 ส่วนผิด 1 หน่วยโดนปรับแค่ 1). ลองกับตัวเลขจริง บ้าน 3 หลัง ทำนาย \(h = [2, 4, 5]\) ล้าน ราคาจริง \(y = [3, 4, 7]\) ล้าน: ผลต่าง \([-1, 0, -2]\) ⇒ ยกกำลังสอง \([1, 0, 4]\) ⇒ ผลรวม 5 ⇒ \(J = 5/3 = 1.667\). สังเกตว่าบ้านหลังที่ 3 (ผิด 2 ล้าน) ออกแรงในค่า cost มากถึง 4 ใน 5 ส่วน — cost function ชนิดนี้จึงบีบให้โมเดลแก้ความผิดก้อนใหญ่ก่อน.

แบบที่ 2 — Classification (ทำนายคลาส 0/1, output 1 node) ใช้ cross-entropy:

$$J(\theta) = -\frac{1}{m}\sum_{i=1}^{m}\Big[y^{(i)}\log h_\theta(x^{(i)}) + (1-y^{(i)})\log\big(1 - h_\theta(x^{(i)})\big)\Big]$$

ถ้าคำตอบจริงคือ 1 ให้ค่าปรับ \(-\log h\); ถ้าคำตอบจริงคือ 0 ให้ค่าปรับ \(-\log(1-h)\) — มีแค่เทอมเดียวทำงานเสมอ

กลไกของ "สวิตช์" นี้: ถ้า \(y=1\) ตัวคูณ \((1-y)=0\) ทำให้เทอมหลังหายไปทั้งก้อน เหลือ \(-\log h\); ถ้า \(y=0\) ตัวคูณ \(y=0\) ทำให้เทอมหน้าหายไป เหลือ \(-\log(1-h)\). ลองตัวเลข (กรณี \(y=1\)): ทำนาย \(h=0.9\) ⇒ ค่าปรับ \(-\ln 0.9 = 0.105\) (เกือบถูก ปรับน้อย); \(h=0.5\) ⇒ \(0.693\); \(h=0.1\) ⇒ \(2.303\) (มั่นใจผิดทาง ปรับหนักกว่า 20 เท่าของกรณีแรก). นี่คือเหตุผลที่ classification ไม่ใช้ MSE: cross-entropy ลงโทษ "มั่นใจแต่ผิด" อย่างรุนแรง ส่วน MSE จะปรับแค่ \((0.1-1)^2 = 0.81\) ซึ่งไม่ต่างจาก \((0.5-1)^2=0.25\) มากพอจะผลักโมเดลออกจากความมั่นใจผิดๆ.

บรรทัดสุดท้ายของหน้านี้คือคำถามที่เหลือทั้งบท: "How to choose a set of parameter → \(\theta_{ij}^{[l]}\) to fit a model" — จะเลือกค่า weight ทุกตัวอย่างไรให้ cost ต่ำที่สุด.

Parameter learning slide: gradient descent algorithm repeat until convergence with theta_ij^[l] := theta_ij^[l] - alpha times partial J / partial theta_ij^[l], simultaneously updating parameters, plus a 3D loss surface picture and a 1D curve showing a local minimum separate from the global minimum labelled nonconvex - local optima problems
Slide: Parameter Learning — Gradient Descent + nonconvex/local optima (Lecture3.pdf, p.2)

คำตอบคือ gradient descent สูตรเดียวกับ Lesson 1 แต่เขียนด้วย index ของเครือข่าย:

$$\theta_{ij}^{[l]} := \theta_{ij}^{[l]} - \alpha\,\frac{\partial J(\theta)}{\partial\theta_{ij}^{[l]}}$$

อ่านทีละสัญลักษณ์: \(l\) = เลเยอร์, \(i\) = node ปลายทางในเลเยอร์ \(l\), \(j\) = node ต้นทางในเลเยอร์ \(l-1\), \(\alpha\) = learning rate (ก้าวยาวแค่ไหน), \(:=\) = "กำหนดค่าใหม่ให้" (ไม่ใช่สมการเท่ากับ). สไลด์ยกตัวอย่างสองตัวแรกให้เห็นว่ามันทำกับ weight ทุกตัว: \(\theta_{1,0} := \theta_{1,0} - \alpha\frac{\partial J}{\partial\theta_{1,0}}\), \(\theta_{1,1} := \theta_{1,1} - \alpha\frac{\partial J}{\partial\theta_{1,1}}\), …

คำว่า "simultaneously update" ในสไลด์คือกับดักข้อสอบ: ต้องคำนวณอนุพันธ์ทุกตัวจาก \(\theta\) ชุดเดิมให้เสร็จก่อน แล้วค่อยเขียนทับพร้อมกัน. ถ้าอัปเดต \(\theta_{1,0}\) ก่อนแล้วเอาค่าใหม่ไปคำนวณอนุพันธ์ของ \(\theta_{1,1}\) นั่นไม่ใช่ gradient descent แล้ว (เป็นคนละอัลกอริทึม และอาจไม่ลู่เข้า).

ด้านขวาของหน้ามีคำเตือนที่ทำสีไว้: nonconvex – Local Optima Problems. ความหมาย: พื้นผิวของ cost function ของเครือข่ายประสาทเทียมไม่ใช่ชามใบเดียว (convex) แบบ linear/logistic regression แต่เป็นภูมิประเทศที่มีหุบเขาหลายลูก. gradient descent เดินลงเขาได้อย่างเดียว ถ้ามันตกลงไปในหุบเล็ก (local minimum) มันจะติดอยู่ตรงนั้นแม้จะมีหุบที่ลึกกว่า (global minimum) อยู่อีกฝั่ง. นี่คือเหตุผลที่ผลการเทรนขึ้นกับค่าเริ่มต้นที่สุ่มมา — เทรนสองครั้งด้วยข้อมูลเดียวกันอาจได้ weight คนละชุด.

แต่สไลด์ก็ใส่กรอบปลอบใจไว้ด้วย (อ้าง Hands-on Machine Learning with Scikit-Learn, Keras, and TensorFlow หน้า 279): "In practice, it turns out that this is rather rare in practice and usually fairly close to the global optimum." — ในทางปฏิบัติ local optima ที่แย่จริงๆ พบได้ยาก และจุดที่ติดมักให้ค่า cost ใกล้เคียงกับ global optimum อยู่แล้ว. ข้อสอบชอบถามตรงนี้: คำตอบที่ถูกคือ "nonconvex เป็นปัญหาในทางทฤษฎี แต่ในทางปฏิบัติมักไม่ร้ายแรง" ไม่ใช่ "nonconvex ทำให้เทรนไม่ได้" และไม่ใช่ "cost ของ NN เป็น convex".

ย่อหน้าสุดท้ายของหน้าคือประตูสู่ทั้งบท: "since neural networks can have many layers, computing the partial derivative of the cost at a specific node in an earlier layer with respect to parameters in the first layer is challenging. To address this problem, the backpropagation algorithm is used to efficiently compute these partial derivatives." — สูตร gradient descent ข้างบนสมมติว่าเรามี \(\partial J/\partial\theta\) อยู่แล้ว. ปัญหาจริงคือจะหามันอย่างไรเมื่อ \(\theta\) อยู่ลึกเข้าไปหลายชั้น. backpropagation คือคำตอบนั้น.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
ถ้าไม่มี cost function ที่เป็นตัวเลขตัวเดียวและหาอนุพันธ์ได้ เราจะไม่มีทางบอกเครื่องจักรว่า "ดีขึ้น" แปลว่าอะไร. cost function เปลี่ยนคำถามเชิงคุณภาพ ("ทำนายดีไหม") เป็นปัญหาคณิตศาสตร์ ("หาค่าต่ำสุดของฟังก์ชันนี้") ที่มีเครื่องมือมาตรฐานแก้ได้.
เปลี่ยนแล้วเกิดอะไร
ถ้าใช้ MSE กับงาน classification: ที่ \(y=1, h=0.1\) ค่าปรับคือ \(0.81\) แต่ cross-entropy ให้ \(2.303\) — ต่างกันเกือบ 3 เท่า และที่สำคัญกว่าคืออนุพันธ์ของ MSE ที่จุดนั้นถูกคูณด้วย \(g'(z)\) ซึ่งเล็กมากเมื่อ \(h\) ใกล้ 0 ⇒ โมเดล "มั่นใจผิด" แต่ gradient แทบเป็นศูนย์ ⇒ แก้ตัวไม่ได้. cross-entropy ออกแบบมาให้ \(g'\) หักล้างพอดี (เราจะพิสูจน์ใน §2).
เชื่อมกับ
สูตร cross-entropy ตัวนี้จะกลับมาอีก 2 ครั้งในบทนี้: เป็นที่มาของ \(\delta^{[L]} = a^{[L]} - y\) ใน §2 และเป็นฐานของ cost แบบ multi-class ใน §6.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 1Cost Function
ตามสไลด์หน้า 1 cost function ถูกนิยามว่าเป็นฟังก์ชันที่ใช้ทำอะไร?

1. Chain Rule: เครื่องมือเดียวที่ใช้พิสูจน์ backprop ทั้งหมด

ปัญหาที่หน้า 2 ทิ้งไว้คือ "หา \(\partial J/\partial\theta\) ของ weight ที่อยู่ลึกได้อย่างไร". อุปสรรคคือ weight ตัวนั้นไม่ได้ปรากฏใน \(J\) โดยตรง — มันส่งผลผ่านตัวกลางหลายทอด. เครื่องมือคณิตศาสตร์ที่จัดการเรื่อง "ผลกระทบผ่านตัวกลาง" ได้ชื่อว่า chain rule และมันคือเครื่องมือตัวเดียวที่ใช้ทั้งบท.

ต้องรู้ก่อน — "ฟังก์ชันซ้อนฟังก์ชัน" (composite function) คืออะไร

ฟังก์ชันซ้อนคือการเอาผลลัพธ์ของฟังก์ชันหนึ่งไปเป็น input ของอีกฟังก์ชัน. ตัวอย่างในชีวิตจริง: จำนวนชั่วโมงที่อ่านหนังสือ → คะแนนสอบ → เกรด. เกรดไม่ได้ขึ้นกับชั่วโมงอ่านโดยตรง แต่ขึ้นผ่านคะแนนสอบ.

เขียนเป็นคณิตศาสตร์: \(u = g(x)\) (ชั่วโมง → คะแนน) และ \(y = f(u)\) (คะแนน → เกรด) ⇒ \(y = f(g(x))\).

ตัวเลขจิ๋ว: อ่านเพิ่ม 1 ชั่วโมงได้คะแนนเพิ่ม 4 คะแนน (\(du/dx = 4\)); คะแนนเพิ่ม 1 คะแนนได้เกรดเพิ่ม 0.02 (\(dy/du = 0.02\)) ⇒ อ่านเพิ่ม 1 ชั่วโมงได้เกรดเพิ่ม \(4\times0.02 = 0.08\). อัตราแต่ละทอดคูณกัน — นั่นคือ chain rule ทั้งอัน.

สไลด์หน้า 3 นิยาม backpropagation ว่าเป็น algorithm ที่ใช้compute partial derivative (หรือที่เรียกว่าgradient) ของ output error ของเครือข่าย (หรือที่เรียกว่าcost) เทียบกับพารามิเตอร์แต่ละตัว (หรือที่เรียกว่าweight) เพื่อเอาไปเรียนรู้ weight ด้วยgradient descent นั่นคือค่า \(\dfrac{\partial J(\theta)}{\partial\theta_{ij}^{[l]}}\).

คำสี่คำนี้คือคำเดียวกันในภาษาต่างกัน และอาจารย์ตั้งใจทำสีเพื่อบอกว่าข้อสอบจะสลับคำพวกนี้: "partial derivative" = "gradient" (gradient คือเวกเตอร์ของอนุพันธ์ย่อยทุกตัว), "output error" = "cost", "parameter" = "weight". ประโยคสรุปที่มุมล่างของหน้าคือคำอธิบาย backprop ที่สั้นที่สุดในสไลด์ทั้งเล่ม: "Backpropagation → how much each weight connection contributed to the error" — backprop ตอบว่าเส้นเชื่อมแต่ละเส้นมีส่วนทำให้เกิดความผิดพลาดมากแค่ไหน.

สไลด์บอกต่อว่า backprop "built on the concept of the Chain Rule" — เทคนิคสำหรับ "differentiating a function of a function". รูปแบบ: ถ้า \(y = f(u)\) และ \(u = g(x)\) แล้วอนุพันธ์ของ \(f(g(x))\) คือ

$$\frac{dy}{dx} = \frac{dy}{du}\times\frac{du}{dx}$$

เหมือนอัตราแลกเงิน: บาท→ดอลลาร์ ×0.03 แล้ว ดอลลาร์→ยูโร ×0.92 ⇒ บาท→ยูโร ×(0.03×0.92) — อัตราแต่ละทอด "คูณต่อกัน"

สไลด์ทิ้งโจทย์ฝึกมือไว้ 2 ข้อก่อนเข้า backprop จริง โดยไม่ได้เฉลย — เราจะแก้ให้ครบทั้งสองข้อ.

Chain rule practice question: find dy/dx when y equals e raised to the power of x cubed, left as a blank exercise with no worked solution shown
Slide: Chain Rule's Example (1) — โจทย์เว้นคำตอบ (Lecture3.pdf, p.4)
โจทย์ 1: หา \(\dfrac{dy}{dx}\) เมื่อ \(y = e^{x^3}\)
  1. ขั้นที่ 1 — แยกเป็นสองทอด

    มองหา "ก้อนข้างใน" ที่ถูกฟังก์ชันอื่นครอบอยู่. ตรงนี้ \(x^3\) ถูก \(e^{(\cdot)}\) ครอบ:

    $$u = x^3,\qquad y = e^{u}$$
  2. ขั้นที่ 2 — หาอนุพันธ์แต่ละทอดแยกกัน

    ใช้สูตร \(\frac{d}{du}e^u = e^u\) (ฟังก์ชัน \(e\) พิเศษตรงที่อนุพันธ์เท่ากับตัวมันเอง) และ \(\frac{d}{dx}x^n = nx^{n-1}\):

    $$\frac{dy}{du} = e^{u} = e^{x^3},\qquad \frac{du}{dx} = 3x^2$$
  3. ขั้นที่ 3 — คูณต่อกันตาม chain rule
    $$\frac{dy}{dx} = e^{x^3}\cdot 3x^2 = 3x^2e^{x^3}$$
  4. ขั้นที่ 4 — ตรวจด้วยตัวเลขที่ \(x=1\)

    สูตรให้ \(3(1)^2e^{1} = 8.155\). ลองขยับจริง: \(x=1.001\) ⇒ \(e^{1.001^3} = e^{1.003003}\) ⇒ \((e^{1.003003}-e^{1})/0.001 = 8.175\) ✓ ใกล้ 8.155 (ต่างเพราะขั้นที่ขยับยังไม่เล็กพอ)

แพทเทิร์น: "คงฟังก์ชันชั้นนอกไว้ทั้งดุ้น (\(e^{x^3}\)) แล้วคูณอนุพันธ์ของชั้นใน (\(3x^2\))" — กลไกเดียวกับที่ใช้แยก \(\partial J/\partial\theta\) ทีละชั้นในโครงข่าย.

Second chain rule exercise: find dy/dx when y equals (2x-5) to the power of 10, with a hint to let u=2x-5 so that y=u^10, illustrated as a computation graph
Slide: From Chain Rule to Backpropagation — โจทย์ที่ 2 พร้อม hint u=2x−5 (Lecture3.pdf, p.5)
โจทย์ 2: หา \(\dfrac{dy}{dx}\) เมื่อ \(y = (2x-5)^{10}\) (hint ในสไลด์: ให้ \(u=2x-5\))
  1. ขั้นที่ 1 — แยกทอดตาม hint (computation graph: \(x \to u \to y\))
    $$u = 2x-5,\qquad y = u^{10}$$
  2. ขั้นที่ 2 — อนุพันธ์แต่ละทอด

    \(u^{10}\) ใช้สูตรกำลัง; \(2x-5\) อนุพันธ์คือ 2 (ค่าคงที่ −5 หายไป เพราะอนุพันธ์ของค่าคงที่เป็น 0):

    $$\frac{dy}{du} = 10u^{9},\qquad \frac{du}{dx} = 2$$
  3. ขั้นที่ 3 — คูณ แล้วแทน \(u\) กลับ
    $$\frac{dy}{dx} = 10u^{9}\cdot 2 = 20\,(2x-5)^{9}$$
  4. ขั้นที่ 4 — ตรวจด้วยตัวเลข ที่ \(x=3\) (\(u=1\))
    $$\frac{dy}{dx}\Big|_{x=3} = 20(1)^9 = 20$$

    ลองขยับ \(x\) จาก 3 เป็น 3.001: \(u=1.002\) ⇒ \(y = 1.002^{10} = 1.0202\) ⇒ \(\Delta y/\Delta x = 0.0202/0.001 \approx 20.18\) ✓ (ใกล้ 20)

สไลด์เรียกโครงสร้าง \(x\to u\to y\) นี้ว่า computation graph — และหัวข้อสไลด์คือ "From Chain Rule to Backpropagation" เพราะโครงข่ายประสาทเทียมคือ computation graph ที่ยาวกว่านี้ (\(x\to z^{[1]}\to a^{[1]}\to z^{[2]}\to a^{[2]}\to J\)) แค่นั้นเอง.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
NN คือฟังก์ชันซ้อนฟังก์ชัน: \(\theta\) ใน layer ลึกไม่ปรากฏใน \(J\) โดยตรง แต่ผ่านทอด \(z\to a\to z\to a\to\dots\to J\) — chain rule คือเครื่องมือเดียวที่แปลง "ผลกระทบทางอ้อมหลายทอด" เป็นผลคูณของอนุพันธ์แต่ละทอดได้.
เปลี่ยนแล้วเกิดอะไร
ลอง \(y=(3x+1)^5\): \(u=3x+1\), \(dy/du=5u^4\), \(du/dx=3\) ⇒ \(dy/dx = 15(3x+1)^4\). ตัวคูณหน้า 15 มาจาก \(5\times3\) (เลขชี้กำลัง × สัมประสิทธิ์ข้างใน) เหมือน \(10\times2=20\) — สูตรลัด \((ax+b)^n \to n\,a\,(ax+b)^{n-1}\).
เชื่อมกับ
pattern "ตัวคูณชั้นนอก × ตัวคูณชั้นใน" ขยายเป็นผลคูณ 4 เทอม (\(\delta\times\theta\times g'\times a\)) ใน §2 — ยิ่งเครือข่ายลึก ยิ่งมีชั้นให้คูณมากขึ้น.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 2Chain Rule
จาก y=(2x−5)¹⁰ โดยให้ u=2x−5 (y=u¹⁰) ค่า dy/dx ตาม chain rule เท่ากับอะไร?

2. จาก Chain Rule สู่ \(\partial J/\partial\theta\): สูตรทั่วไปของ Backprop

ตอนนี้เรามีเครื่องมือ (chain rule) และมีเป้าหมาย (\(\partial J/\partial\theta\)) แล้ว. หัวข้อนี้คือการเอาเครื่องมือไปจ่อกับเครือข่ายจริง ทีละสูตร จนได้ "สูตรสำเร็จ" ที่ใช้กับเครือข่ายกี่ชั้นก็ได้.

Apply chain rule to backpropagation slide: neural network as a composite function, with the layer-2 gradient written as dJ/dtheta[2] = dJ/dz[2] times dz[2]/dtheta[2] and the layer-1 gradient as the longer product dJ/dz[2] times dz[2]/da[1] times da[1]/dz[1] times dz[1]/dtheta[1], plus the statement that backpropagation involves 2 consecutive steps per example: forward computation and backward computation
Slide: Apply Chain Rule to Backpropagation (Lecture3.pdf, p.6)

ประโยคเปิดของหน้านี้คือกุญแจ: "Neural network is a composite function" — เครือข่ายคือฟังก์ชันซ้อนฟังก์ชันตามที่เราเพิ่งฝึกใน §1. เมื่อเป็นเช่นนั้น chain rule ก็ใช้ได้ทันที และสไลด์เขียนสองสมการเทียบกันให้เห็นว่า "ยิ่งลึกยิ่งยาว":

$$\frac{\partial J(\theta)}{\partial\theta^{[2]}} = \frac{\partial J(\theta)}{\partial z^{[2]}}\,\frac{\partial z^{[2]}}{\partial\theta^{[2]}}$$ $$\frac{\partial J(\theta)}{\partial\theta^{[1]}} = \frac{\partial J(\theta)}{\partial z^{[2]}}\,\frac{\partial z^{[2]}}{\partial a^{[1]}}\,\frac{\partial a^{[1]}}{\partial z^{[1]}}\,\frac{\partial z^{[1]}}{\partial\theta^{[1]}}$$

weight ของ layer สุดท้ายมี 2 ทอด; weight ของ layer แรกมี 4 ทอด — จำนวนทอด = ระยะทางจาก weight ตัวนั้นไปถึง cost

ลองไล่ทีละทอดของสมการล่างเพื่อให้เห็นว่ามันไม่ใช่สูตรที่ท่องจำ แต่คือ "เส้นทางเดิน": \(\theta^{[1]}\) ส่งผลต่อ \(z^{[1]}\) (ทอดที่ 4 นับจากขวา) → \(z^{[1]}\) ส่งผลต่อ \(a^{[1]}\) ผ่าน activation (ทอดที่ 3) → \(a^{[1]}\) ส่งผลต่อ \(z^{[2]}\) (ทอดที่ 2) → \(z^{[2]}\) ส่งผลต่อ \(J\) (ทอดที่ 1). อ่านจากซ้ายไปขวาในสมการคืออ่านจาก cost ย้อนกลับไปหา weight — ซึ่งก็คือชื่อ "back-propagation" นั่นเอง.

สไลด์สรุปว่า backpropagation ประกอบด้วย2 consecutive steps ต่อ 1 ตัวอย่าง: Forward Computation — "Find \(h_\theta(x)\) from left to right" คือไล่คำนวณจาก input ไป output เพื่อให้ได้ค่าทำนาย; และ Backward Computation — "Propagating error from right to left to find the error contribution from each connection weight in the network" คือไล่ error กลับจาก output มา input เพื่อหาว่าเส้นเชื่อมแต่ละเส้นรับผิดชอบความผิดพลาดเท่าไร. คำว่า consecutive (ต่อเนื่องกัน/เรียงลำดับ) สำคัญ: ทำ backward ก่อน forward ไม่ได้เด็ดขาด เพราะ backward ต้องใช้ค่า \(z, a\) ที่ forward ผลิตไว้.

2.1 Forward Computation: ต้องมีตัวเลขก่อนถึงจะย้อนกลับได้

Forward computation formula for a 1-example shallow neural network: hypothesis h(x)=a1[2]=g(z1[2]) where z1[2]=theta10[2]+theta11[2]a1[1]+theta12[2]a2[1]+theta13[2]a3[1], with the underlying formula z=sum of theta times x and a=g(z)
Slide: Forward Computation สำหรับ 1 example (Lecture3.pdf, p.7)

เครือข่ายในหน้านี้คือ input 2 ตัว → hidden 3 node → output 1 node. สูตรพื้นฐานที่ใช้กับทุก node มีสองบรรทัดเท่านั้น:

$$z = \sum_{i=0}^{n}\theta_i x_i,\qquad a = g(z)$$

บรรทัดแรกคือ "รวมข้อมูลเข้าแบบถ่วงน้ำหนัก" บรรทัดที่สองคือ "บีบผ่าน activation". จุดที่ต้องสังเกตคือผลรวมเริ่มที่ \(i=0\) ไม่ใช่ \(i=1\) — เพราะ index 0 คือ bias. สไลด์ทำสีแดงไว้ที่ \(x_0\) (bias unit ของ input layer) และ \(a_0^{[1]}\) (bias unit ของ hidden layer) ซึ่งเป็น node พิเศษที่มีค่าเท่ากับ 1 เสมอ ไม่ได้มาจากการคำนวณ และไม่มีเส้นเข้า. ที่ต้องทำสีเพราะนักเรียนมักลืม แล้วนับมิติของ \(\theta\) ผิดไปหนึ่งคอลัมน์.

เขียนสูตรของ output node ออกมาเต็มๆ ตามที่สไลด์ให้:

$$z_1^{[2]} = \theta_{10}^{[2]} + \theta_{11}^{[2]}a_1^{[1]} + \theta_{12}^{[2]}a_2^{[1]} + \theta_{13}^{[2]}a_3^{[1]},\qquad h_\theta(x) = a_1^{[2]} = g\!\left(z_1^{[2]}\right)$$

อ่าน index ให้ชัด (ระบบนี้มาจาก Andrew Ng ตามที่สไลด์หมายเหตุไว้): \(\theta_{12}^{[2]}\) หมายถึง "weight ใน layer 2 จาก node 2 ของ layer ก่อนหน้า ไปยัง node 1 ของ layer นี้" — ตัวเลขตัวแรกคือปลายทาง ตัวที่สองคือต้นทาง. ลำดับนี้ดูกลับด้านกับสามัญสำนึก แต่มันทำให้เขียนเป็นเมทริกซ์แล้วคูณได้พอดี (\(z = \theta a\)). ส่วน \(\theta_{10}^{[2]}\) ที่ต้นทางเป็น 0 คือ weight ของ bias — ซึ่งก็คือ \(\theta_{10}^{[2]}\times a_0^{[1]} = \theta_{10}^{[2]}\times 1\) นั่นเอง จึงเขียนสั้นๆ ได้แค่ \(\theta_{10}^{[2]}\).

2.2 นิยาม \(\delta\) และสูตรสำเร็จของสไลด์

Backward computation definitions: delta_j^[l] defined as the error of cost for a_j^[l], with the layer 2 delta computed as delta1[2] = h(x) - y, and layer 1 deltas computed as delta_j[1] = (theta_j1[2])^T times delta1[2] times g'(z_j[1]) for each of the three hidden nodes
Slide: Backward Computation — นิยาม δ และสูตร δ⁽¹⁾ จาก δ⁽²⁾ (Lecture3.pdf, p.8)

ก่อนดูสูตร ต้องเข้าใจว่าทำไมถึงต้องประดิษฐ์ตัวแปรชื่อ \(\delta\) ขึ้นมาเลย. เหตุผลคือความประหยัด: สังเกตว่าในสมการ chain rule ทั้งสองอันของหน้า 6 เทอม \(\dfrac{\partial J}{\partial z^{[2]}}\) ปรากฏเหมือนกัน. ถ้าเครือข่ายมี weight 1,000 ตัว เราคงไม่อยากคำนวณเทอมนี้ซ้ำ 1,000 ครั้ง. จึงตั้งชื่อมันไว้ครั้งเดียวแล้วใช้ซ้ำ — ชื่อนั้นคือ \(\delta\).

สไลด์นิยามว่า \(\delta_j^{(l)}\) = "error of cost for \(a_j^{[l]}\) (unit \(j\) in layer \(l\))" และให้สูตรทางคณิตศาสตร์กำกับว่า

$$\delta_j^{(l)} = \frac{\partial J}{\partial z_j^{[l]}}\quad\text{(from calculus — สไลด์เขียนว่า "I will prove it later")}$$

อ่านเป็นภาษาคน: "ถ้าดัน \(z\) ของ node นี้ขึ้นนิดเดียว cost จะเปลี่ยนไปเท่าไร" — ตัวเลขนี้คือ "ส่วนแบ่งความผิด" ของ node นั้น. โปรดสังเกตความไม่ตรงกันเล็กๆ ในสไลด์: คำบรรยายบอกว่าเป็น error ของ \(a_j^{[l]}\) แต่สูตรหารเทียบ \(z_j^{[l]}\). ตัวที่ใช้จริงทุกที่คือแบบที่หารเทียบ \(z\) (ถ้าใช้ \(a\) สูตร \(\delta^{[L]} = a^{[L]}-y\) จะไม่จริง) — จำแบบนี้ไปตอบข้อสอบ. สไลด์ยังนิยาม \(L\) = total number of layers in the network (not counting input layer) ⇒ เครือข่ายในรูปนี้มี \(L=2\).

จากนั้นสไลด์ให้สูตรสำเร็จ 4 บรรทัด (ยังไม่พิสูจน์ — พิสูจน์อยู่หน้า 10):

$$\delta_1^{(2)} = h_\theta(x) - y = a_1^{[2]} - y$$ $$\delta_1^{(1)} = \left(\theta_{11}^{[2]}\right)^{\!\top}\delta_1^{(2)} * g'\!\left(z_1^{[1]}\right),\quad \delta_2^{(1)} = \left(\theta_{12}^{[2]}\right)^{\!\top}\delta_1^{(2)} * g'\!\left(z_2^{[1]}\right),\quad \delta_3^{(1)} = \left(\theta_{13}^{[2]}\right)^{\!\top}\delta_1^{(2)} * g'\!\left(z_3^{[1]}\right)$$

พร้อมกำกับว่าสำหรับ sigmoid \(g'(z^{[l]}) = a^{[l]}(1-a^{[l]})\) และสูตรแปลง \(\delta\) เป็น gradient:

$$\frac{\partial J(\theta)}{\partial\theta_{ij}^{[l]}} = a_j^{[l-1]}\,\delta_i^{(l)}\qquad\text{(กำหนด }a^{[0]} := x\text{)}$$

output: error = ทำนาย − จริง. hidden: node นี้ "ยืม" error ของ layer ถัดไป × weight ที่เชื่อม × ความชันของ activation ของ node นี้เอง. gradient ของเส้นใดๆ = (error ปลายทาง) × (ค่าที่ไหลมาจากต้นทาง)

ทำไม \(\delta\) ของ hidden node ต้องมี 3 ตัวคูณพอดี — แต่ละตัวแปลว่าอะไร:

ส่วนเครื่องหมาย \(\top\) (transpose) และ \(*\) ในสไลด์: ในรูปแบบเวกเตอร์ \(\theta^{[l]\top}\delta^{[l]}\) คือคูณเมทริกซ์เพื่อกระจาย error ย้อนกลับ ส่วน \(*\) คือคูณทีละสมาชิก (element-wise) กับ \(g'\) ไม่ใช่คูณเมทริกซ์. ในสูตรรายตัวข้างบน \(\theta_{11}^{[2]}\) เป็นเลขตัวเดียว transpose จึงไม่ทำอะไรเลย — อาจารย์เขียน \(\top\) ไว้เพื่อให้รูปสูตรตรงกับเวอร์ชันเมทริกซ์ในหน้า 18.

2.3 กรณีเล็กที่สุด: Logistic Regression

Derive backpropagation on the smallest possible network: a logistic regression unit with inputs x1, x2 plus bias x0 feeding a single sigmoid node whose output h(x) lies in {0,1}, together with its gradient descent update rule theta_j := theta_j - (alpha/m) sum over examples of (h(x)-y) times x_j
Slide: Derive Backpropagation (Small Neural Network) — logistic regression (Lecture3.pdf, p.9)

ก่อนพิสูจน์สูตรกับเครือข่ายเต็ม สไลด์ย้อนกลับไปดูเครือข่ายที่เล็กที่สุดเท่าที่จะเป็นไปได้: node เดียว ซึ่งก็คือ logistic regression ที่เรียนมาแล้วใน Lesson 1. โครงสร้าง: รับ \(x_1, x_2\) (บวก \(x_0\) เป็น bias) → sigmoid node ตัวเดียว → output \(h_\theta(x)\) ที่ตีความเป็นคลาส \(\{0,1\}\). กฎอัปเดตของมันคือ

$$\theta_j := \theta_j - \frac{\alpha}{m}\sum_{i=1}^{m}\left(h_\theta(x^{(i)}) - y^{(i)}\right)x_j^{(i)}$$

เทียบกับสูตร backprop ที่เพิ่งเห็น: เทอม \(\left(h_\theta(x)-y\right)\) คือ \(\delta\) ของ output พอดี และ \(x_j\) คือ \(a_j^{[0]}\) พอดี ⇒ gradient \(= \delta\times a^{[0]}\) ⇒ ตรงกับกฎ \(\dfrac{\partial J}{\partial\theta_{ij}^{[l]}} = a_j^{[l-1]}\delta_i^{(l)}\) เป๊ะ. ข้อสรุปที่ได้จากหน้านี้: backpropagation ไม่ใช่สูตรใหม่เอี่ยม มันคือการขยายสูตรของ logistic regression ให้ไล่ย้อนได้หลายชั้น — ถ้าเครือข่ายมีชั้นเดียว backprop จะยุบกลายเป็น logistic regression ทันที. นี่คือเหตุผลที่อาจารย์ใส่หน้านี้คั่นก่อนพิสูจน์: ให้เห็นว่าเรากำลังต่อยอดจากของที่รู้อยู่แล้ว ไม่ใช่เริ่มจากศูนย์.

2.4 พิสูจน์สูตรทีละขั้น (สไลด์หน้า 10)

Mathematical proof deriving the two backpropagation formulas from the chain rule: dJ/dtheta[2] = dJ/dz[2] times dz[2]/dtheta[2], which equals (h(x)-y) times a[1]; and dJ/dtheta[1] expanded through the longer chain dJ/dz[2] times dz[2]/da[1] times da[1]/dz[1] times dz[1]/dtheta[1], which equals (h(x)-y) times theta[2] times a[1] times (1-a[1]) times x
Slide: Mathematical Proof — พิสูจน์สูตร δ ด้วย Chain Rule เต็มขั้น (Lecture3.pdf, p.10)

สไลด์เริ่มด้วยการเขียนเครือข่ายทั้งอันเป็นสมการซ้อนกัน 5 บรรทัด ซึ่งคือ "computation graph" ของเรานั่นเอง:

$$z^{[1]} = \theta^{[1]}x,\quad a^{[1]} = g(z^{[1]}),\quad z^{[2]} = \theta^{[2]}a^{[1]},\quad h_\theta(x) = a^{[2]} = g(z^{[2]}) = g\big(\theta^{[2]}g(\theta^{[1]}x)\big)$$

บรรทัดขวาสุดคือหัวใจ: \(h\) คือ \(g\) ซ้อน \(g\) — composite function ชัดๆ จึงใช้ chain rule ได้. ต่อไปนี้คือการพิสูจน์ทั้งสามชิ้นแบบละเอียดทุกบรรทัด.

พิสูจน์ ①: \(\delta^{[2]} = \partial J/\partial z^{[2]} = a^{[2]} - y\)
ให้ \(J = -\left[y\ln a + (1-y)\ln(1-a)\right]\) (cross-entropy ต่อ 1 ตัวอย่าง จากหน้า 1) และเขียน \(a\) แทน \(a^{[2]}\) เพื่อความสั้น; \(a = g(z^{[2]}) = \dfrac{1}{1+e^{-z^{[2]}}}\)
  1. ขั้นที่ 1 — แยกโซ่: \(z^{[2]}\to a\to J\) มี 2 ทอด
    $$\frac{\partial J}{\partial z^{[2]}} = \frac{\partial J}{\partial a}\cdot\frac{\partial a}{\partial z^{[2]}}$$
  2. ขั้นที่ 2 — ทอดแรก: อนุพันธ์ของ \(J\) เทียบ \(a\)

    ใช้ \(\frac{d}{da}\ln a = \frac{1}{a}\) และ \(\frac{d}{da}\ln(1-a) = \frac{-1}{1-a}\) (ตัว −1 มาจาก chain rule ของ \(1-a\)) แล้วรวมเศษส่วน:

    $$\frac{\partial J}{\partial a} = -\frac{y}{a} + \frac{1-y}{1-a} = \frac{-y(1-a) + (1-y)a}{a(1-a)} = \frac{-y+ya+a-ya}{a(1-a)} = \frac{a-y}{a(1-a)}$$
  3. ขั้นที่ 3 — ทอดที่สอง: อนุพันธ์ของ sigmoid (พิสูจน์เต็มใน §5A)
    $$\frac{\partial a}{\partial z^{[2]}} = a(1-a)$$
  4. ขั้นที่ 4 — คูณตาม chain rule: \(a(1-a)\) หักล้างกันพอดี
    $$\frac{\partial J}{\partial z^{[2]}} = \frac{a-y}{a(1-a)}\cdot a(1-a) = a - y$$

$$\delta^{[2]} = a^{[2]} - y = h_\theta(x) - y$$

การหักล้างในขั้นที่ 4 ไม่ใช่ความบังเอิญ — cross-entropy ถูกออกแบบมาคู่กับ sigmoid เพื่อให้ตัวคูณ \(g'\) ที่ output layer หายไป. ผลคือถ้าโมเดลมั่นใจผิด (\(a\) ใกล้ 0 แต่ \(y=1\)) gradient ยังใหญ่พอจะแก้ตัวได้ ไม่โดน \(g'\approx0\) ฆ่าทิ้ง.

พิสูจน์ ②: gradient ของ \(\theta^{[2]}\) (layer สุดท้าย — โซ่ 2 ทอด)
  1. ขั้นที่ 1 — เขียน chain rule ตามสไลด์
    $$\frac{\partial J}{\partial\theta_{1j}^{[2]}} = \frac{\partial J}{\partial z^{[2]}}\cdot\frac{\partial z^{[2]}}{\partial\theta_{1j}^{[2]}}$$
  2. ขั้นที่ 2 — เทอมที่สอง: หาอนุพันธ์ของผลรวมถ่วงน้ำหนัก

    \(z^{[2]} = \theta_{10}^{[2]}a_0^{[1]}+\theta_{11}^{[2]}a_1^{[1]}+\theta_{12}^{[2]}a_2^{[1]}+\dots\) เมื่อหารเทียบ \(\theta_{1j}^{[2]}\) ตัวเดียว เทอมอื่นทั้งหมดเป็นค่าคงที่ (อนุพันธ์ = 0) เหลือแค่ตัวคูณของมันเอง:

    $$\frac{\partial z^{[2]}}{\partial\theta_{1j}^{[2]}} = a_j^{[1]}\qquad(\text{และ } a_0^{[1]}=1 \text{ สำหรับ bias})$$
  3. ขั้นที่ 3 — คูณสองทอด
    $$\frac{\partial J}{\partial\theta_{1j}^{[2]}} = \delta^{[2]}\cdot a_j^{[1]} = \left(h_\theta(x)-y\right)a_j^{[1]}$$

ตรงกับที่สไลด์เขียนไว้ว่า \(\dfrac{\partial J(\theta)}{\partial\theta^{[2]}} = \left(h_\theta(x)-y\right)a^{[1]}\). ความหมายเชิงสัญชาตญาณ: เส้นที่ส่งสัญญาณแรง (\(a_j^{[1]}\) ใหญ่) ไปยัง node ที่ผิดมาก (\(\delta\) ใหญ่) คือเส้นที่ต้องแก้มากที่สุด.

พิสูจน์ ③: gradient ของ \(\theta^{[1]}\) (layer แรก — โซ่ 4 ทอด)
  1. ขั้นที่ 1 — เขียนโซ่ทั้งเส้น: \(\theta^{[1]}_{ji}\to z_j^{[1]}\to a_j^{[1]}\to z^{[2]}\to J\)
    $$\frac{\partial J}{\partial\theta_{ji}^{[1]}} = \underbrace{\frac{\partial J}{\partial z^{[2]}}}_{\delta^{[2]}}\cdot\underbrace{\frac{\partial z^{[2]}}{\partial a_j^{[1]}}}_{\theta_{1j}^{[2]}}\cdot\underbrace{\frac{\partial a_j^{[1]}}{\partial z_j^{[1]}}}_{g'(z_j^{[1]})}\cdot\underbrace{\frac{\partial z_j^{[1]}}{\partial\theta_{ji}^{[1]}}}_{x_i}$$
  2. ขั้นที่ 2 — แทนทีละเทอม พร้อมเหตุผล

    ทอด 1: \(\delta^{[2]} = h-y\) จากพิสูจน์ ①. ทอด 2: \(z^{[2]}\) เป็นผลรวมถ่วงน้ำหนักของ \(a^{[1]}\) ⇒ อนุพันธ์เทียบ \(a_j^{[1]}\) คือสัมประสิทธิ์ของมัน นั่นคือ \(\theta_{1j}^{[2]}\). ทอด 3: \(a = g(z)\) ⇒ อนุพันธ์คือ \(g'\) ซึ่งสำหรับ sigmoid เท่ากับ \(a_j^{[1]}(1-a_j^{[1]})\). ทอด 4: \(z_j^{[1]} = \sum_i\theta_{ji}^{[1]}x_i\) ⇒ อนุพันธ์เทียบ \(\theta_{ji}^{[1]}\) คือ \(x_i\).

  3. ขั้นที่ 3 — จับกลุ่ม 3 ตัวแรกแล้วตั้งชื่อว่า \(\delta_j^{[1]}\)
    $$\delta_j^{[1]} \equiv \delta^{[2]}\,\theta_{1j}^{[2]}\,g'(z_j^{[1]})\quad\Rightarrow\quad \frac{\partial J}{\partial\theta_{ji}^{[1]}} = \delta_j^{[1]}\,x_i$$

สไลด์เขียนผลลัพธ์เต็มไว้ว่า \(\dfrac{\partial J(\theta)}{\partial\theta^{[1]}} = \left(h_\theta(x)-y\right)\theta^{[2]}\big(a^{[1]}(1-a^{[1]})\big)x\) — ตรงกับผลคูณ 4 ทอดของเราทุกตัว. และเมื่อจับกลุ่มแล้ว ทุก layer ได้กฎเดียวกัน:

$$\frac{\partial J}{\partial\theta_{ij}^{[l]}} = \delta_i^{[l]}\cdot a_j^{[l-1]}$$

(error ของ node ปลายทาง) × (ค่าที่ส่งมาจากต้นทาง). สังเกตว่าเครือข่ายยิ่งลึกยิ่งมีตัวคูณ \(g'\) มาก — รากของ vanishing gradient ใน Lesson 5.

รูปแบบเมทริกซ์ (ที่ใช้ตอนเขียนโค้ด — ทำทุก node ใน layer พร้อมกัน):

$$\delta^{[l-1]} = \left(\theta^{[l]\top}\delta^{[l]}\right)\odot g'\!\left(z^{[l-1]}\right)$$

เครื่องหมาย \(\odot\) คือคูณทีละสมาชิก (element-wise) ไม่ใช่คูณเมทริกซ์ — ตรงกับเครื่องหมาย \(*\) ที่สไลด์ใช้. ตรวจขนาดให้เห็นภาพ: layer 1 มี 3 node, layer 2 มี 1 node ⇒ \(\theta^{[2]}\) ขนาด \(1\times4\) ⇒ \(\theta^{[2]\top}\delta^{[2]}\) ขนาด \((4\times1)(1\times1)=4\times1\) แล้วตัดแถว bias (แถวแรก) ทิ้งเหลือ \(3\times1\) เพื่อคูณกับ \(g'(z^{[1]})\) ที่มีขนาด \(3\times1\). ทำไมต้องตัดแถว bias: เพราะ \(a_0^{[1]}\) เป็นค่าคงที่ 1 ไม่ได้มาจาก \(z\) ใดๆ จึงไม่มี \(\delta\) ของตัวเอง — นี่คือจุดที่โค้ดของนักเรียนพังบ่อยที่สุดเวลาเขียน backprop เอง.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
จำนวนทอดในโซ่ (2 ทอดสำหรับ \(\theta^{[2]}\), 4 ทอดสำหรับ \(\theta^{[1]}\)) เท่ากับ "ระยะทาง" จาก \(\theta\) นั้นไปถึง \(J\) จริงๆ — และที่ backprop ประหยัดคือ \(\delta^{[2]}\) ที่คำนวณครั้งเดียว ถูกนำไปใช้ซ้ำในทุก gradient ที่อยู่ก่อนหน้า ไม่ต้องคำนวณโซ่ยาวใหม่ทุกครั้ง.
เปลี่ยนแล้วเกิดอะไร
ถ้าเครือข่ายมี 3 layer การหา \(\partial J/\partial\theta^{[1]}\) ต้องไล่ \(z^{[1]}\to a^{[1]}\to z^{[2]}\to a^{[2]}\to z^{[3]}\to J\) ผลคูณจึงยาวขึ้นอีก 2 ตัวคูณ (\(\theta^{[3]}\) กับ \(g'(z^{[2]})\) — รวมเป็น 6 ตัวคูณ จาก 4 ตัวในกรณี 2 layer) — จำนวนเทอมเพิ่มตามระยะทางเสมอ.
เชื่อมกับ
รากของ vanishing gradient (Lesson 5 §1): θ ใน layer แรกๆ มีโซ่ยาว มีตัวคูณ \(g'\le0.25\) เยอะ จึงเสี่ยง gradient หดเกือบ 0.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 3Backprop Derivation
ในการพิสูจน์ ∂J/∂θ[1] ด้วย chain rule (เครือข่าย 2 layer) เทอม ∂a[1]/∂z[1] มีค่าเท่ากับอะไร (เมื่อ activation function คือ sigmoid)?

3. ตัวอย่างคำนวณเต็มรูปแบบ: 2 Layer, 2 Training Examples

สไลด์หน้า 11–16 คือตัวอย่างที่อาจารย์เดินให้ดูในคาบ โดยเว้นตัวเลขไว้ทุกช่อง — นี่คือแบบฝึกหัดที่มีโอกาสออกสอบสูงที่สุดในบท. เราจะไล่ทีละหน้าและกรอกตัวเลขให้ครบ (ทุกค่าตรวจด้วย numpy แล้ว).

โจทย์: "Find partial derivative of each weight and do gradient descent for 1 iteration (2 examples) (Assume all sigmoid activation functions, \(y = \begin{bmatrix}1\\1\end{bmatrix}\))" — เครือข่าย input \(x_1,x_2\) (+ bias \(x_0=1\)) → hidden 2 node → output 1 node, sigmoid ทุก node, คำตอบจริงของทั้งสองตัวอย่างคือ 1.

Small neural network diagram for the worked example: x0=1, x1=1, x2=1 feeding into hidden nodes a1[1] and a2[1] with visible edge weights (1,1,0 to a1[1] and 1,0,1 to a2[1]), and both hidden nodes feeding into output a1[2] with weights (0,1,0), all under sigmoid activation, y=1
Slide: Example — Forward Computation ตัวอย่างที่ 1 (x₁=1, x₂=1) (Lecture3.pdf, p.11)

ตัวเลขที่เขียนกำกับบนเส้นแต่ละเส้นคือค่า weight เริ่มต้น. อ่านออกมาเป็นเมทริกซ์ (แถว = node ปลายทาง; คอลัมน์ = bias, \(x_1\), \(x_2\)):

$$\theta^{[1]} = \begin{bmatrix}1&1&0\\1&0&1\end{bmatrix},\qquad \theta^{[2]} = \begin{bmatrix}0&1&0\end{bmatrix}\ (\text{bias},\ a_1^{[1]},\ a_2^{[1]})$$

hidden node 1 ใช้เฉพาะ \(x_1\) (weight ของ \(x_2\) = 0); hidden node 2 ใช้เฉพาะ \(x_2\); output ใช้เฉพาะ hidden node 1

ค่า weight ที่เป็น 0 สามตัว (\(\theta_{12}^{[1]}=0\), \(\theta_{21}^{[1]}=0\), \(\theta_{12}^{[2]}=0\)) ไม่ได้ใส่มาเล่นๆ — มันจะทำให้เกิดผลลัพธ์ที่น่าตกใจสองอย่างข้างล่าง และนั่นคือสิ่งที่อาจารย์อยากให้เห็น.

ขั้น A — Forward ตัวอย่างที่ 1: \(x=(1,1)\)
\(x_0=1, x_1=1, x_2=1\); sigmoid \(g(z)=\dfrac{1}{1+e^{-z}}\)
  1. ขั้นที่ 1 — หา \(z\) ของ hidden ทั้งสอง node
    $$z_1^{[1]} = 1(1)+1(1)+0(1) = 2,\qquad z_2^{[1]} = 1(1)+0(1)+1(1) = 2$$

    (ตัวแรกคือ bias × 1, ตัวที่สองคือ weight ของ \(x_1\), ตัวที่สามคือ weight ของ \(x_2\))

  2. ขั้นที่ 2 — ผ่าน activation \(a = g(z)\)
    $$a_1^{[1]} = g(2) = \frac{1}{1+e^{-2}} = 0.8808,\qquad a_2^{[1]} = g(2) = 0.8808$$
  3. ขั้นที่ 3 — layer 2 (อย่าลืม \(a_0^{[1]}=1\))
    $$z_1^{[2]} = 0(1)+1(0.8808)+0(0.8808) = 0.8808$$ $$h_\theta(x) = g(0.8808) = 0.70699$$

ทำนายได้ \(0.707\) ในขณะที่คำตอบจริงคือ \(1\) ⇒ ทำนายต่ำไป ⇒ เดี๋ยว backward จะให้ gradient ที่ผลักให้ weight เพิ่มขึ้น.

Backward computation diagram for the first training example with every arrow reversed, pointing from output a1[2] back through the hidden nodes to x1, x2 and the bias units, with the same edge weights 1, 0, 1 and 0 written along each reversed arrow
Slide: Example — Backward Computation ตัวอย่างที่ 1 (Lecture3.pdf, p.12)

หน้านี้กลับทิศลูกศรทุกเส้นเพื่อย้ำว่าตอนนี้เรากำลังส่ง "ความผิด" เดินสวนทางกลับ โดยใช้ weight ชุดเดิม (ยังไม่อัปเดต). คำนวณได้ดังนี้:

ขั้น B — Backward ตัวอย่างที่ 1
จาก forward: \(h=0.70699\), \(a_1^{[1]}=a_2^{[1]}=0.8808\), \(y=1\), \(\theta_{11}^{[2]}=1\), \(\theta_{12}^{[2]}=0\)
  1. ขั้นที่ 1 — \(\delta\) ที่ output (สูตรตรงๆ ไม่ต้องใช้ \(g'\))
    $$\delta_1^{(2)} = h_\theta(x)-y = 0.70699 - 1 = -0.29301$$

    เครื่องหมายลบแปลว่า "ทำนายต่ำกว่าความจริง".

  2. ขั้นที่ 2 — หา \(g'\) ของ hidden ทั้งสอง node (ทั้งคู่ \(z=2\))
    $$g'(z_1^{[1]}) = a_1^{[1]}\left(1-a_1^{[1]}\right) = 0.8808(1-0.8808) = 0.10499$$ $$g'(z_2^{[1]}) = 0.8808(0.1192) = 0.10499$$
  3. ขั้นที่ 3 — \(\delta\) ของ hidden node 1 (weight ขาออก = 1)
    $$\delta_1^{(1)} = \theta_{11}^{[2]}\,\delta_1^{(2)}\,g'(z_1^{[1]}) = 1\times(-0.29301)\times0.10499 = -0.030764$$
  4. ขั้นที่ 4 — \(\delta\) ของ hidden node 2 (weight ขาออก = 0)
    $$\delta_2^{(1)} = 0\times(-0.29301)\times0.10499 = 0$$

\(\delta_2^{(1)}=0\) เป๊ะเพราะ weight ขาออกเป็น 0: ถ้าเส้นที่ส่งข้อมูลไปข้างหน้ามี weight 0 gradient ที่ไหลย้อนผ่านเส้นนั้นก็เป็น 0 — node นี้ไม่ได้เรียนรู้อะไรเลยในรอบนี้ ทั้งที่มันคำนวณค่า \(a_2^{[1]}=0.8808\) ออกมาอย่างขยันขันแข็ง.

Same reversed-arrow backward diagram for example 1, now annotated with the instruction to accumulate gradients Delta_ij^(l), meaning each example's gradient contribution is added into a running total rather than applied immediately
Slide: Example — Accumulate Gradients Δᵢⱼ⁽ˡ⁾ (Lecture3.pdf, p.13)

หน้านี้เพิ่มคำสั่งเดียวคือ "Accumulate gradients \(\Delta_{ij}^{(l)}\)" — แปลว่า อย่าเพิ่งอัปเดต weight ให้เอา gradient ของตัวอย่างนี้ไปบวกสะสมไว้ในตัวแปร \(\Delta\) ก่อน แล้วค่อยไปทำตัวอย่างที่ 2. เหตุผล: cost ที่เรานิยามไว้หน้า 1 คือค่าเฉลี่ยของทุกตัวอย่าง ดังนั้น gradient ของมันก็ต้องเป็นค่าเฉลี่ยของ gradient รายตัวอย่างเช่นกัน. ใช้สูตร \(\Delta_{ij}^{(l)} \mathrel{+}= a_j^{[l-1]}\delta_i^{(l)}\) กับตัวอย่างที่ 1:

ขั้น C — สะสม \(\Delta\) จากตัวอย่างที่ 1
\(\delta_1^{(2)}=-0.29301\); \(a^{[1]}=(a_0,a_1,a_2)=(1,\ 0.8808,\ 0.8808)\); \(\delta_1^{(1)}=-0.030764\), \(\delta_2^{(1)}=0\); \(x=(1,1,1)\)
  1. ขั้นที่ 1 — แถวของ \(\theta^{[2]}\) (ปลายทางคือ output node เดียว)
    $$\Delta_{10}^{(2)} = 1\times(-0.29301) = -0.29301$$ $$\Delta_{11}^{(2)} = 0.8808\times(-0.29301) = -0.25808$$ $$\Delta_{12}^{(2)} = 0.8808\times(-0.29301) = -0.25808$$
  2. ขั้นที่ 2 — แถวที่ 1 ของ \(\theta^{[1]}\) (ปลายทางคือ hidden node 1, ต้นทางคือ \(x\))
    $$\Delta_{10}^{(1)} = 1\times(-0.030764),\quad \Delta_{11}^{(1)} = 1\times(-0.030764),\quad \Delta_{12}^{(1)} = 1\times(-0.030764)$$

    ทั้งสามช่องเท่ากันหมด (\(-0.030764\)) เพราะ \(x_0=x_1=x_2=1\) พอดีในตัวอย่างนี้.

  3. ขั้นที่ 3 — แถวที่ 2 ของ \(\theta^{[1]}\)
    $$\Delta_{2j}^{(1)} = x_j\times 0 = 0\quad\text{ทุก } j$$

หลังตัวอย่างที่ 1: \(\Delta^{(2)} = [-0.29301,\ -0.25808,\ -0.25808]\) และ \(\Delta^{(1)} = \begin{bmatrix}-0.030764&-0.030764&-0.030764\\0&0&0\end{bmatrix}\) — ยังไม่ใช่ gradient สุดท้าย ต้องรอตัวอย่างที่ 2 มาบวกเพิ่มก่อน.

Same small neural network with the second training example: x1=1, x2=2, identical weights as before, forward computation to be recomputed with the new x2 value
Slide: Example — Forward Computation ตัวอย่างที่ 2 (x₁=1, x₂=2) (Lecture3.pdf, p.14)

ตัวอย่างที่ 2 เปลี่ยนแค่ \(x_2\) จาก 1 เป็น 2 (weight ยังเป็นชุดเดิม เพราะเรายังไม่ได้อัปเดต).

ขั้น D — Forward ตัวอย่างที่ 2: \(x=(1,2)\)
  1. ขั้นที่ 1 — hidden layer
    $$z_1^{[1]} = 1(1)+1(1)+0(2) = 2\ \Rightarrow\ a_1^{[1]} = g(2) = 0.8808$$ $$z_2^{[1]} = 1(1)+0(1)+1(2) = 3\ \Rightarrow\ a_2^{[1]} = g(3) = 0.95257$$

    node 1 ไม่ขยับเลยเพราะ weight ของ \(x_2\) เป็น 0; node 2 ขยับจาก 0.8808 เป็น 0.95257.

  2. ขั้นที่ 2 — output layer
    $$z_1^{[2]} = 0(1)+1(0.8808)+0(0.95257) = 0.8808,\qquad h_\theta(x) = g(0.8808) = 0.70699$$

ข้อสังเกตสำคัญ: \(h(x)\) เท่ากันเป๊ะกับตัวอย่างที่ 1 (0.70699) ทั้งที่ input ต่างกัน — เพราะ (1) \(a_1^{[1]}\) ไม่ขึ้นกับ \(x_2\) (weight = 0) และ (2) output ไม่ใช้ \(a_2^{[1]}\) (weight = 0). ข้อมูลของ \(x_2\) ไหลเข้าไปถึง \(a_2^{[1]}\) จริง แต่ตันอยู่ตรงนั้น "weight = 0" คือกำแพงที่ปิดทั้งขาไปและขากลับ.

Backward computation diagram for the second training example (x1=1, x2=2) with all arrows reversed and the same weights 1, 0, 1, 0 labelled on the edges
Slide: Example — Backward Computation ตัวอย่างที่ 2 (Lecture3.pdf, p.15)
ขั้น E — Backward ตัวอย่างที่ 2
  1. ขั้นที่ 1 — \(\delta\) ที่ output (เหมือนเดิมเพราะ \(h\) และ \(y\) เท่าเดิม)
    $$\delta_1^{(2)} = 0.70699 - 1 = -0.29301$$
  2. ขั้นที่ 2 — \(g'\) ของ hidden (ตอนนี้ node 2 ต่างจากเดิมแล้ว)
    $$g'(z_1^{[1]}) = 0.8808(0.1192) = 0.10499,\qquad g'(z_2^{[1]}) = 0.95257(1-0.95257) = 0.045177$$
  3. ขั้นที่ 3 — \(\delta\) ของ hidden
    $$\delta_1^{(1)} = 1\times(-0.29301)\times0.10499 = -0.030764,\qquad \delta_2^{(1)} = 0\times(-0.29301)\times0.045177 = 0$$
  4. ขั้นที่ 4 — สะสม \(\Delta\) เพิ่ม (ใช้ \(a^{[1]}=(1,\ 0.8808,\ 0.95257)\) และ \(x=(1,1,2)\))
    $$\Delta_{10}^{(2)}\ \mathrel{+}=\ -0.29301,\quad \Delta_{11}^{(2)}\ \mathrel{+}=\ 0.8808(-0.29301) = -0.25808,\quad \Delta_{12}^{(2)}\ \mathrel{+}=\ 0.95257(-0.29301) = -0.27912$$ $$\Delta_{10}^{(1)}\ \mathrel{+}=\ -0.030764,\quad \Delta_{11}^{(1)}\ \mathrel{+}=\ -0.030764,\quad \Delta_{12}^{(1)}\ \mathrel{+}=\ 2(-0.030764) = -0.061529$$

รวมสองตัวอย่างแล้ว: \(\Delta^{(2)} = [-0.58603,\ -0.51617,\ -0.53720]\) และ \(\Delta^{(1)}\) แถว 1 \(= [-0.061529,\ -0.061529,\ -0.092293]\) แถว 2 เป็นศูนย์ทั้งแถว. สังเกตว่าช่อง \(\Delta_{12}^{(1)}\) โตกว่าเพื่อนเพราะตัวอย่างที่ 2 มี \(x_2=2\) (ยิ่ง input ใหญ่ ยิ่งรับผิดชอบมาก).

Final step of the worked example: accumulate gradients Delta_ij[l] across both training examples, average them via D_ij[l] = (1/m) Delta_ij[l], then perform one gradient descent update step theta_ij[l] := theta_ij[l] - alpha * dJ/dtheta_ij[l] with alpha=0.1
Slide: Example — Accumulate Gradients และ Gradient Descent Update (Lecture3.pdf, p.16)

หน้าสุดท้ายของตัวอย่างระบุสองอย่าง: เฉลี่ยด้วย \(D_{ij}^{(l)} := \frac{1}{m}\Delta_{ij}^{(l)}\) แล้วอัปเดตด้วย gradient descent โดย "suppose alpha = 0.1".

ขั้น F — เฉลี่ยแล้วอัปเดต (\(m=2\), \(\alpha = 0.1\))
\(\Delta^{(2)} = [-0.58603,\ -0.51617,\ -0.53720]\); \(\Delta^{(1)}\) แถว 1 \(= [-0.061529,\ -0.061529,\ -0.092293]\), แถว 2 = 0
  1. ขั้นที่ 1 — หาร \(m=2\) ได้ gradient จริง \(D = \partial J/\partial\theta\)
    $$D^{(2)} = [-0.29301,\ -0.25808,\ -0.26860]$$ $$D^{(1)}\text{ แถว 1} = [-0.030764,\ -0.030764,\ -0.046147],\qquad \text{แถว 2} = [0,\ 0,\ 0]$$
  2. ขั้นที่ 2 — อัปเดต \(\theta := \theta - \alpha D\) พร้อมกันทุกตัว
    $$\theta^{[2]}:\ [0,\ 1,\ 0]\ \to\ [0.029301,\ 1.025808,\ 0.026860]$$ $$\theta^{[1]}\text{ แถว 1}:\ [1,\ 1,\ 0]\ \to\ [1.003076,\ 1.003076,\ 0.004615]$$ $$\theta^{[1]}\text{ แถว 2}:\ [1,\ 0,\ 1]\ \to\ [1,\ 0,\ 1]\ (\text{ไม่เปลี่ยน})$$

    ตัวอย่างการคำนวณช่องหนึ่ง: \(\theta_{11}^{[2]} = 1 - 0.1\times(-0.25808) = 1 + 0.025808 = 1.025808\) — gradient เป็นลบ ⇒ weight เพิ่มขึ้น เพราะสูตรมีเครื่องหมายลบนำหน้าอยู่แล้ว.

  3. ขั้นที่ 3 — ตรวจว่า cost ลดลงจริงหรือไม่ (ขั้นตอนที่สไลด์ไม่ได้ทำ แต่ควรทำเสมอ)

    forward ใหม่ด้วย weight ที่อัปเดตแล้ว: ตัวอย่างที่ 1 ได้ \(h = 0.72265\) ตัวอย่างที่ 2 ได้ \(h = 0.72313\) (จากเดิม 0.70699 ทั้งคู่) ⇒ cost เฉลี่ย \(-\ln h\) ลดจาก \(0.34674\) เหลือ \(0.32450\) ✓

ทุก weight ที่ gradient เป็นลบ (\(h<y\) — ทำนายต่ำไป) เพิ่มขึ้น เพื่อดัน \(h\) เข้าใกล้ \(y=1\); แถว node 2 ไม่ขยับเลยแม้แต่ช่องเดียวเพราะ gradient เป็น 0 ทั้งแถว. ถ้าเทรนต่อไปเรื่อยๆ ด้วย weight ชุดนี้ hidden node 2 จะไม่มีวันได้เรียนรู้ เพราะ \(\theta_{12}^{[2]}\) ก็ไม่เคยถูกอัปเดตให้พ้นจาก... เดี๋ยวก่อน — ดูที่ \(\theta_{12}^{[2]}\) หลังอัปเดต: มันกลายเป็น 0.02686 แล้ว (เพราะ gradient ของมันคือ \(a_2^{[1]}\delta^{(2)} \neq 0\)) ⇒ รอบถัดไป node 2 จะเริ่มมี \(\delta\) ไม่เป็นศูนย์และกลับมาเรียนรู้ได้. บทเรียน: weight ขาออกที่เป็น 0 ปิดกั้น gradient ของ node นั้นเฉพาะรอบปัจจุบัน ไม่ใช่ตลอดไป ตราบใดที่ตัว weight ขาออกเองยังได้รับการอัปเดต.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
forward ต้องเสร็จก่อน backward เพราะ \(\delta^{[1]}\) ต้องใช้ \(a^{[1]}\) จาก forward เพื่อหา \(g'(z^{[1]}) = a^{[1]}(1-a^{[1]})\) — ไม่มี \(a^{[1]}\) ก็ backward ไม่ได้ นี่คือเหตุผลเชิงกลไกของคำว่า "2 consecutive steps" ไม่ใช่แค่ลำดับที่สไลด์สอน.
เปลี่ยนแล้วเกิดอะไร
ถ้าเปลี่ยน \(y\) จาก 1 เป็น 0: \(\delta^{(2)} = 0.70699 - 0 = +0.70699\) ⇒ \(D_{11}^{(2)} = 0.8808\times0.70699 = +0.62272\) ⇒ \(\theta_{11}^{[2]} := 1 - 0.1(0.62272) = 0.93773\) (ลดลง แทนที่จะเพิ่ม) — ทิศตรงข้ามเป๊ะ เพราะตอนนี้ทำนายสูงเกินไป. และถ้าเปลี่ยน \(\alpha\) จาก 0.1 เป็น 1.0 ก้าวจะใหญ่ขึ้น 10 เท่า: \(\theta_{11}^{[2]} = 1.25808\).
เชื่อมกับ
ทิศทางอัปเดตที่สลับตามเครื่องหมายของ \((h-y)\) คือกลไกเดียวกับ Lesson 1 ที่ gradient descent "กลับทิศเข้าหาจุดต่ำสุดเสมอ" — จุดต่ำสุดที่นี่คือ \(h = y\).
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 4Worked Example
ในตัวอย่างคำนวณ (θ⁽²⁾=[0,1,0]) ทำไม δ₂⁽¹⁾ ของ node a₂⁽¹⁾ จึงเท่ากับ 0 เป๊ะทั้งสองตัวอย่าง?
คำถาม 5Gradient Descent Update
จากตัวอย่างเดียวกัน gradient ของ weight จาก a₁⁽¹⁾ ไป output คือ D₁₁⁽²⁾ ≈ −0.258 ที่ α=0.1 ค่า θ₁₁⁽²⁾ เดิม (=1) จะถูกอัปเดตเป็นเท่าใด?

4. Backpropagation Algorithm: สรุปเป็นขั้นตอนที่ใช้ได้ทุกโครงข่าย

ตัวอย่างใน §3 ทำกับเครือข่าย 2 layer 2 node. คำถามคือ "ถ้าเครือข่ายมี 5 layer ละ 100 node ต้องทำอย่างไร" — คำตอบคือทำเหมือนเดิมทุกอย่าง เพราะสูตรไม่ได้อ้างถึงขนาดของเครือข่ายเลย. สไลด์หน้า 17–18 จึงเขียนเป็นอัลกอริทึมทั่วไป.

Backpropagation algorithm pseudocode part 1: given a training set with m examples, initialize accumulated gradient Delta_ij[l] to 0, then for each training example set a[0]=x and perform forward computation through all layers: z[1]=theta[1]a[0], a[1]=g(z[1]), add bias, and so on up to h(x)=a[3]=g(z[3])
Slide: Backpropagation Algorithm — ส่วน Forward (Lecture3.pdf, p.17)

สไลด์เริ่มจาก "Given a training set \((x^{(1)},y^{(1)}), (x^{(2)},y^{(2)}) \dots (x^{(m)},y^{(m)})\) and set \(\Delta_{ij}^{(l)} := 0\)" — บรรทัดนี้คือการล้างกระปุกสะสม gradient ให้เป็นศูนย์ก่อนเริ่มรอบใหม่ทุกครั้ง. ถ้าลืมล้าง gradient ของรอบก่อนจะบวกทบเข้ามาเรื่อยๆ จนก้าวใหญ่เกินจริง (บั๊กคลาสสิกของคนเขียน backprop เอง และเป็นเหตุผลที่ PyTorch ต้องเรียก optimizer.zero_grad() ทุกรอบ).

จากนั้นวนทุกตัวอย่าง \(i = 1\) ถึง \(m\) แล้วทำสองขั้น: (1) "Set \(a^{[0]} := x\)" — ตั้งชื่อ input ว่าเป็น activation ของ layer 0 เพื่อให้สูตรเดียว \(\partial J/\partial\theta_{ij}^{[l]} = a_j^{[l-1]}\delta_i^{(l)}\) ใช้ได้กับ layer แรกด้วย; (2) ทำforward computation เพื่อหา \(h_\theta(x)\) (หรือ \(a^{[L]}\)). สไลด์แสดงตัวอย่างเครือข่าย 3 layer เต็มๆ ว่าไล่อย่างไร:

$$a^{[0]} = x \to z^{[1]} = \theta^{[1]}a^{[0]} \to a^{[1]} = g(z^{[1]})\ (\text{add bias } a_0^{[1]})$$ $$\to z^{[2]} = \theta^{[2]}a^{[1]} \to a^{[2]} = g(z^{[2]})\ (\text{add bias } a_0^{[2]}) \to z^{[3]} = \theta^{[3]}a^{[2]} \to h_\theta(x) = a^{[3]} = g(z^{[3]})$$

วงเล็บ "(add bias)" ที่สไลด์เขียนกำกับไว้สองครั้งคือขั้นตอนที่คนลืมบ่อยที่สุด: หลังคำนวณ \(a^{[l]}\) เสร็จ ต้องแปะเลข 1 เข้าไปด้านหน้าเวกเตอร์ ก่อนส่งเข้า layer ถัดไป ไม่งั้นมิติจะไม่ตรงกับ \(\theta^{[l+1]}\) ที่มี \(s_l+1\) คอลัมน์.

Backpropagation algorithm pseudocode part 2: compute output error delta[L]=a[L]-y, then compute delta[L-1] through delta[1] via delta[l-1]=(theta[l])^T delta[l] times g'(z[l-1]), accumulate Delta_ij[l] += a_j[l-1] delta_i[l], then average as D_ij[l]=(1/m)Delta_ij[l] and use in gradient descent, with an intuition box about updating weights that minimise the final loss
Slide: Backpropagation Algorithm (2) — ส่วน Backward และ Update (Lecture3.pdf, p.18)

หน้านี้ต่อจากขั้นที่ 2 ด้วยขั้นที่ 3 และ 4. ขั้นที่ 3: "compute the error \(\delta^{(L)} = a^{[L]} - y^{(i)}\)" — error ที่ชั้นนอกสุด. ขั้นที่ 4: ทำbackward computation "to measure the error contribution from each connection weight" โดยคำนวณ \(\delta^{(L)}, \delta^{(L-1)}, \dots, \delta^{(1)}\) ตามลำดับย้อนกลับด้วยสูตร

$$\delta^{(l-1)} = \left(\theta^{[l]}\right)^{\!\top}\delta^{(l)} * g'\!\left(z^{[l-1]}\right),\qquad g'(z^{[l]}) = a^{[l]}\left(1-a^{[l]}\right)\ \text{สำหรับ sigmoid}$$

แล้วสะสมและเฉลี่ย:

$$\Delta_{ij}^{(l)} := \Delta_{ij}^{(l)} + a_j^{[l-1]}\delta_i^{(l)},\qquad \frac{\partial J(\theta)}{\partial\theta_{ij}^{[l]}} = D_{ij}^{(l)} := \frac{1}{m}\Delta_{ij}^{(l)}$$

และปิดท้ายด้วย gradient descent \(\theta_{ij}^{[l]} := \theta_{ij}^{[l]} - \alpha\frac{\partial J(\theta)}{\partial\theta_{ij}^{[l]}}\) ทำซ้ำจนลู่เข้า.

กล่อง "Intuition" ที่มุมล่างขวาคือประโยคที่ควรท่องได้: "update weights that minimize the final loss. So if some weight leads to the node that largely contributes to the final loss (\(\delta_{\text{destination}}\) is large), the algorithm will calculate larger gradient for gradient descent to adjust the weight." — weight ที่ชี้ไปยัง node ที่ก่อความเสียหายมาก จะได้ gradient ใหญ่ และถูกปรับแรง. ลองกับตัวเลขใน §3: \(\delta^{(2)} = -0.293\) (ใหญ่) ส่งผลให้ \(D_{11}^{(2)} = -0.258\) (ใหญ่ตาม) ⇒ \(\theta_{11}^{[2]}\) ขยับ 0.0258; ส่วน \(\delta_2^{(1)} = 0\) (ไม่มีส่วนผิด) ⇒ gradient 0 ⇒ ไม่ขยับเลย. นี่คือความหมายของคำว่า "ส่วนแบ่งความผิด" อย่างเป็นรูปธรรม.

เรียบเรียงเป็นขั้นตอนที่จำไปสอบได้:

  1. ขั้นที่ 1 — เริ่มต้น

    ตั้ง \(\Delta_{ij}^{(l)} := 0\) ทุกตัว

  2. ขั้นที่ 2 — วนทุกตัวอย่างฝึก \((x^{(i)}, y^{(i)})\): Forward

    \(a^{[0]} = x\); คำนวณ \(z^{[l]} = \theta^{[l]}a^{[l-1]},\ a^{[l]} = g(z^{[l]})\) (เติม bias) ไปจนถึง \(a^{[L]}\)

  3. ขั้นที่ 3 — Error ที่ output
    $$\delta^{(L)} = a^{[L]} - y$$
  4. ขั้นที่ 4 — ส่งย้อนกลับ \(l = L, L-1, \dots, 2\)
    $$\delta^{(l-1)} = \left(\theta^{[l]\top}\delta^{(l)}\right)\odot g'\!\left(z^{[l-1]}\right)$$
  5. ขั้นที่ 5 — สะสม
    $$\Delta_{ij}^{(l)} \mathrel{+}= a_j^{[l-1]}\,\delta_i^{(l)}$$
  6. ขั้นที่ 6 — หลังครบทุกตัวอย่าง: เฉลี่ยแล้วอัปเดต
    $$D_{ij}^{(l)} = \frac{1}{m}\Delta_{ij}^{(l)},\qquad \theta_{ij}^{[l]} := \theta_{ij}^{[l]} - \alpha\,D_{ij}^{(l)}$$

ตัวอย่างใน §3 คือการรันอัลกอริทึมนี้ตรงๆ 1 รอบด้วย \(m=2, L=2\).

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
ทำไมต้องสะสม \(\Delta\) แล้วหารด้วย \(m\) ทีหลัง (ไม่อัปเดตทันทีทุกตัวอย่าง): เพราะ gradient ของ cost ที่รวมทุกตัวอย่างคือค่าเฉลี่ยของ gradient แต่ละตัวอย่าง — นี่คือ batch gradient descent. ถ้าอัปเดตทุกตัวอย่างทันทีจะกลายเป็น SGD (Lesson 4 §3) ซึ่งเป็นอัลกอริทึมคนละตัวและมีพฤติกรรมต่างกัน.
เปลี่ยนแล้วเกิดอะไร
ถ้า \(m=4\) และ \(\delta\times a\) ของ 4 ตัวอย่างเป็น \([-0.03,-0.02,-0.05,0.01]\): \(\Delta = -0.09\) แต่ \(D = -0.09/4 = -0.0225\) — ยิ่ง \(m\) มาก แต่ละตัวอย่างยิ่งมีน้ำหนักน้อยลง และขนาดก้าวไม่ระเบิดตามจำนวนข้อมูล.
เชื่อมกับ
การหารด้วย \(m\) คือ "mean" ตัวเดียวกับที่อยู่ในนิยาม cost หน้า 1 — ถ้า cost หารด้วย \(m\) gradient ของมันก็ต้องหารด้วย \(m\) ตามหลักอนุพันธ์ของผลรวม.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 6Backprop Algorithm
สูตร δ⁽ˡ⁻¹⁾ = (θ⁽ˡ⁾)ᵀδ⁽ˡ⁾ * g'(z⁽ˡ⁻¹⁾) ใช้คำนวณอะไร และทำไมต้องมีเทอม g' คูณอยู่ด้วย?

4A. ใช้งานจริง: Autodiff, มิติพารามิเตอร์, การสุ่มค่าเริ่มต้น, Unrolling

สี่หน้าถัดไป (19–22) คือ "เรื่องที่ต้องรู้ตอนลงมือทำจริง" ซึ่งข้อสอบเติมโค้ดชอบหยิบไปถาม.

4A.1 จาก Backpropagation สู่ Automatic Differentiation (หน้า 19)

From backpropagation to automatic differentiation slide: modern frameworks compute derivatives automatically through a computational graph using the same chain rule, with two modes - forward-mode AD propagating derivatives from inputs to outputs and reverse-mode AD propagating gradients from output to inputs - and a four-line PyTorch snippet showing model forward pass, loss, backward and optimizer step
Slide: From Backpropagation to Automatic Differentiation (Lecture3.pdf, p.19)

ข่าวดีของหน้านี้: "Modern deep-learning frameworks do not require us to manually derive every gradient" — เฟรมเวิร์กสมัยใหม่คำนวณอนุพันธ์ให้อัตโนมัติผ่าน computational graph โดยใช้ Chain Rule ตัวเดียวกับที่เราเพิ่งเรียน. เรายังต้องเข้าใจ backprop เพื่อ debug และเพื่อสอบ แต่ไม่ต้องหาอนุพันธ์ด้วยมือทุกครั้ง.

สไลด์แยก AD เป็นสองโหมดซึ่งเป็นจุดที่ข้อสอบชอบสลับ:

โหมดทิศทางเหมาะเมื่อ
Forward-mode ADpropagate derivatives จาก inputs → outputsinput น้อย output เยอะ
Reverse-mode ADpropagate gradients จาก output → inputsinput (พารามิเตอร์) เยอะ output เป็นสเกลาร์ตัวเดียว

เหตุผลที่ deep learning เลือก reverse-mode อยู่ในประโยคที่สไลด์ทำตัวหนา: "Neural networks typically have many parameters → one scalar loss, making reverse-mode particularly suitable." — ลองคิดเป็นตัวเลข: ถ้าโมเดลมีพารามิเตอร์ 1,000,000 ตัวและ loss 1 ตัว, forward-mode ต้องรัน 1,000,000 รอบ (รอบละหนึ่งพารามิเตอร์) ส่วน reverse-mode รันรอบเดียวได้ครบทุกอนุพันธ์. นี่คือเหตุผลเชิงประสิทธิภาพทั้งหมดของ backpropagation. สไลด์สรุปความสัมพันธ์ไว้ชัด: "Reverse-mode autodiff is the general computational technique; backpropagation is its application to efficiently compute gradients through a neural network" — reverse-mode AD คือเทคนิคทั่วไป ส่วน backprop คือการเอาเทคนิคนั้นมาใช้กับเครือข่ายประสาท.

y_pred = model(x)          # forward pass
loss = criterion(y_pred, y)
loss.backward()            # reverse-mode autodiff / backprop
optimizer.step()           # update parameters
โค้ดทำอะไร
y_pred = model(x)Forward computation ทั้งเครือข่าย: ไล่ \(z^{[l]} = \theta^{[l]}a^{[l-1]},\ a^{[l]}=g(z^{[l]})\) จนถึง \(a^{[L]}\). ระหว่างทาง PyTorch แอบบันทึก computational graph ไว้ด้วย (จำว่าค่าไหนมาจากการดำเนินการอะไร) — นี่คือสิ่งที่ทำให้บรรทัดที่ 3 ทำงานได้. ผลลัพธ์เป็น tensor ขนาด (batch, จำนวน output node)
loss = criterion(y_pred, y)คำนวณ cost \(J\) จากค่าทำนายเทียบคำตอบจริง. criterion คือฟังก์ชัน loss ที่เลือกไว้ (เช่น BCELoss สำหรับ binary, CrossEntropyLoss สำหรับ multi-class ตาม §6). ผลลัพธ์เป็นสเกลาร์ตัวเดียว — ตรงกับ "one scalar loss" ในสไลด์
loss.backward()ขั้น backward ทั้งหมดของ §4 รวบไว้ในบรรทัดเดียว: คำนวณ \(\delta^{(L)}\) แล้วไล่ย้อนหา \(\delta\) ทุกชั้น และเก็บ \(\partial J/\partial\theta\) ไว้ในช่อง .grad ของพารามิเตอร์แต่ละตัว. ยังไม่เปลี่ยนค่า \(\theta\)
optimizer.step()อัปเดต \(\theta := \theta - \alpha\,\partial J/\partial\theta\) โดยอ่านจากช่อง .grad ที่บรรทัดก่อนหน้าเติมไว้. \(\alpha\) คือ learning rate ที่ตั้งตอนสร้าง optimizer

ผลลัพธ์ที่คาด: โค้ด 4 บรรทัดนี้ไม่พิมพ์อะไรออกมา — ผลของมันคือค่า loss (ตัวเลขเดียว ลดลงเรื่อยๆ ตามรอบ) และพารามิเตอร์ของ model ที่ถูกแก้ไขในที่ (in-place). สไลด์ไม่ได้แสดง output ของบล็อกนี้ จึงไม่มีตัวเลขให้อ้าง.

ออกสอบสูง — ข้อความที่อาจารย์ทำสี

4A.2 Dimension of Parameters: สูตร b × (a+1) (หน้า 20)

Dimension of parameters slide: theta[1] written as a 3-row matrix of theta10 theta11 theta12 / theta20 theta21 theta22 / theta30 theta31 theta32 labelled 3x(2+1), theta[2] as a single row labelled 1x(3+1), and the general rule that if layer l-1 has a units (not counting x0) and layer l has b units then theta[l] has dimension b x (a+1)
Slide: Dimension of Parameters (Lecture3.pdf, p.20)

เครือข่ายในหน้านี้คือ input 2 → hidden 3 → output 1. สไลด์กางเมทริกซ์ออกมาให้เห็นทุกช่อง:

$$\theta^{[1]} = \begin{bmatrix}\theta_{10}&\theta_{11}&\theta_{12}\\\theta_{20}&\theta_{21}&\theta_{22}\\\theta_{30}&\theta_{31}&\theta_{32}\end{bmatrix}\ \ 3\times(2+1),\qquad \theta^{[2]} = \begin{bmatrix}\theta_{10}&\theta_{11}&\theta_{12}&\theta_{13}\end{bmatrix}\ \ 1\times(3+1)$$

นับตามจริง: \(\theta^{[1]}\) มี 3 แถวเพราะ hidden มี 3 node และมี 3 คอลัมน์เพราะ input มี 2 ตัวบวก bias อีก 1; \(\theta^{[2]}\) มี 1 แถวเพราะ output มี 1 node และ 4 คอลัมน์เพราะ hidden 3 node บวก bias. สรุปเป็นกฎทั่วไปตามที่สไลด์เขียน: ถ้า layer \(l-1\) มี \(a\) unit (ไม่นับ \(x_0\)) และ layer \(l\) มี \(b\) unit แล้วมิติของ \(\theta^{[l]}\) คือ \(b\times(a+1)\).

จำนวนแถว = จำนวน node ที่รับของ; จำนวนคอลัมน์ = จำนวน node ที่ส่งของ + 1 ช่องสำหรับ bias

ฝึกใช้สูตร \(b\times(a+1)\) กับเครือข่ายอื่น
ใช้กับสามโครงสร้าง: (i) 2→10→1, (ii) 2→10→10→1, (iii) 784→128→10
  1. ขั้นที่ 1 — เครือข่าย 2→10→1 (ตัวเดียวกับโจทย์ regularization หน้า 42)
    $$\theta^{[1]}: 10\times(2+1) = 10\times3 = 30,\qquad \theta^{[2]}: 1\times(10+1) = 1\times11 = 11$$

    รวม \(30+11 = 41\) พารามิเตอร์

  2. ขั้นที่ 2 — เพิ่ม hidden อีกชั้น 2→10→10→1
    $$10\times3 = 30,\qquad 10\times11 = 110,\qquad 1\times11 = 11\ \Rightarrow\ \text{รวม } 151$$

    จาก 41 เป็น 151 ทั้งที่ hidden node รวมเพิ่มแค่เท่าตัว (10→20) — เพราะชั้นกลางเชื่อมกันแบบทุกคู่ \(10\times10=100\) เส้น ไม่ใช่ \(10+10\)

  3. ขั้นที่ 3 — ภาพจริงขนาด MNIST 784→128→10
    $$128\times785 = 100{,}480,\qquad 10\times129 = 1{,}290\ \Rightarrow\ \text{รวม } 101{,}770$$

ข้อควรระวังในสไลด์: อาจารย์พิมพ์ \(\theta^{[2]} = [\theta_{10}\ \theta_{11}\ \theta_{12}\ \theta_{14}]\) — ตัวสุดท้ายควรเป็น \(\theta_{13}\) ไม่ใช่ \(\theta_{14}\) (เพราะ hidden มีแค่ 3 node ดังนั้น index ต้นทางวิ่งได้แค่ 0–3). นี่เป็น typo ของสไลด์; คำตอบที่ปลอดภัยในข้อสอบคือ index \(\theta_{10},\theta_{11},\theta_{12},\theta_{13}\) และขนาด \(1\times4\) ซึ่งสไลด์เองก็เขียนไว้ถูกว่า \(1\times(3+1)\).

ออกสอบสูง — ข้อความที่อาจารย์ทำสี

4A.3 Parameters Initialization: ทำไมห้ามเริ่มที่ศูนย์ (หน้า 21)

Parameters initialization slide: a network where every single weight is labelled 0, with the warning that not choosing parameters randomly might not capture interesting functions (redundant hidden units); randomly initializing breaks the symmetry and lets backpropagation train a diverse team of neurons; the initial solution is to randomly initialize each parameter to small values close to zero with -epsilon < theta < epsilon, plus two numpy lines using np.zeros and np.random.rand
Slide: Parameters Initialization (Lecture3.pdf, p.21)

เครือข่ายในหน้านี้มี weight เป็น 0 ทุกเส้น — และนั่นคือหายนะ. สไลด์อธิบายว่าการไม่สุ่มพารามิเตอร์ "might not capture interesting functions" ซึ่งเกิดอาการที่เรียกว่า redundant hidden units — hidden unit ที่ซ้ำซ้อน คือมีหลาย node แต่ทุก node คำนวณสิ่งเดียวกันเป๊ะ จึงเท่ากับมี node เดียว. ทางแก้คือ "Randomly initialize the weights, you break the symmetry and allow backpropagation to train a diverse team of neurons".

มาดูว่ามันพังอย่างไรด้วยตัวเลขจริง (เครือข่ายเดียวกับหน้า 21: \(x=(1,1)\), \(y=1\), weight ทุกตัวเป็น 0, sigmoid, \(\alpha=0.5\)):

รอบ\(h_\theta(x)\)\(a_1^{[1]}\)\(a_2^{[1]}\)\(\theta_{11}^{[2]}\)\(\theta_{12}^{[2]}\)\(\theta^{[1]}\) แถว 1\(\theta^{[1]}\) แถว 2
10.50000.50.50.1250.125[0, 0, 0][0, 0, 0]
20.59270.50.50.22680.2268[0.0064, 0.0064, 0.0064][0.0064, 0.0064, 0.0064]
30.66430.50480.50480.31160.3116[0.0159, 0.0159, 0.0159][0.0159, 0.0159, 0.0159]
50.76150.52010.52010.44550.4455[0.0382, 0.0382, 0.0382][0.0382, 0.0382, 0.0382]

อ่านตารางนี้ให้ออก: ค่า \(h\) ก็ลู่เข้าหา 1 อยู่นะ ดูเหมือนเทรนได้ — แต่แถว 1 กับแถว 2 ของ \(\theta^{[1]}\) เท่ากันทุกช่องทุกรอบ และ \(\theta_{11}^{[2]} = \theta_{12}^{[2]}\) ตลอดกาล. เหตุผลเชิงกลไก: เมื่อ weight เท่ากัน \(z_1^{[1]} = z_2^{[1]}\) ⇒ \(a_1^{[1]} = a_2^{[1]}\) ⇒ \(\delta_1^{(1)} = \delta_2^{(1)}\) ⇒ gradient เท่ากัน ⇒ อัปเดตเท่ากัน ⇒ ยังเท่ากันต่อไป. hidden 2 node ทำงานได้เท่ากับ 1 node เป๊ะ — ต่อให้ใส่ 100 node ก็ยังได้ความสามารถเท่า 1 node. นี่คือความหมายของ "redundant hidden units" และของคำว่า symmetry ที่ต้อง "break".

ทางแก้ที่สไลด์เสนอ (ในกรอบ "Initial Solution! (Advance solution later)"): สุ่มพารามิเตอร์แต่ละตัวเป็นค่าเล็กๆ ใกล้ศูนย์ คือ \(-\varepsilon < \theta_{ij}^{[l]} < \varepsilon\). คำว่า "advance solution later" หมายถึงวิธีที่ดีกว่า (Xavier / He initialization) ที่จะสอนใน Lesson 5 — แค่ "เล็ก" อย่างเดียวยังไม่พอสำหรับเครือข่ายลึก.

W = np.zeros((L_out, 1 + L_in))
W = np.random.rand(L_out, 1 + L_in) * 2 * epsilon_init - epsilon_init
โค้ดทำอะไร
np.zeros((L_out, 1 + L_in))สร้างเมทริกซ์ศูนย์ขนาด \(b\times(a+1)\) ตามสูตรหน้า 20 พอดี: L_out = จำนวน node ของ layer ปลายทาง (\(b\)), L_in = จำนวน node ต้นทาง (\(a\)), และ 1 + คือคอลัมน์ bias. บรรทัดนี้คือการจองที่ว่าง (placeholder) — ถ้าใช้ค่านี้เทรนจริงจะเจอปัญหา symmetry ตามตารางข้างบน
np.random.rand(L_out, 1 + L_in)สุ่มค่าจากการแจกแจงสม่ำเสมอในช่วง \([0,1)\) ขนาดเท่ากัน. ยังไม่ใช่คำตอบ เพราะค่าทั้งหมดเป็นบวก — ต้องแปลงช่วงก่อน
* 2 * epsilon_initขยายช่วงจาก \([0,1)\) เป็น \([0,\ 2\varepsilon)\). ถ้า epsilon_init = 0.12 ก็ได้ \([0,\ 0.24)\)
- epsilon_initเลื่อนช่วงลงมาให้คร่อมศูนย์: \([-\varepsilon,\ \varepsilon)\) = \([-0.12,\ 0.12)\) ตรงกับเงื่อนไข \(-\varepsilon < \theta < \varepsilon\) ในสไลด์พอดี. ลำดับ \(\times2\varepsilon\) ก่อนแล้วค่อย \(-\varepsilon\) สลับกันไม่ได้

ผลลัพธ์ที่คาด (รันจริงด้วย L_in=2, L_out=10, epsilon_init=0.12, seed=1): W.shape = (10, 3), ค่าต่ำสุด \(-0.1200\) ค่าสูงสุด \(0.1124\) — กระจายอยู่ในช่วง \([-0.12, 0.12)\) และไม่มีสองแถวใดเหมือนกัน ⇒ symmetry ถูกทำลายเรียบร้อย.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
การสุ่มไม่ได้มีไว้ "เพื่อความสุ่ม" แต่เพื่อให้ hidden unit แต่ละตัวเริ่มจากจุดต่างกัน จะได้เรียนรู้ feature คนละอย่าง. ถ้าเริ่มเท่ากัน gradient ก็เท่ากัน อัปเดตเท่ากัน และเท่ากันตลอดไป — ความสามารถของเครือข่ายยุบเหลือ 1 node ต่อ layer.
เปลี่ยนแล้วเกิดอะไร
ถ้าตั้ง \(\varepsilon\) ใหญ่เกิน (เช่น 10) ค่า \(z = \sum\theta x\) จะใหญ่ ⇒ sigmoid อิ่มตัว ⇒ \(g'\approx0\) ⇒ gradient หายตั้งแต่รอบแรก. ถ้าเล็กเกิน (เช่น \(10^{-8}\)) ทุก node เกือบเหมือนกันหมด symmetry แทบไม่ถูกทำลาย. จึงต้อง "small values close to zero" แต่ไม่ใช่ศูนย์.
เชื่อมกับ
นี่คือเหตุผลที่ §0 บอกว่าเทรนสองครั้งได้ weight คนละชุด (non-convex + สุ่มค่าเริ่มต้น) และเป็นประตูสู่ Xavier/He initialization ใน Lesson 5 §2.

4A.4 Unrolling Parameters: ยัด θ ทุกตัวลงเวกเตอร์เดียว (หน้า 22)

Unrolling parameters slide: to use an optimization package all thetas must be put into one long vector using np.concatenate of Theta1.ravel() and Theta2.ravel(), then recovered with np.reshape using slices sized hidden_layer_size times (input_layer_size + 1) and num_labels times (hidden_layer_size + 1)
Slide: Unrolling Parameters (Lecture3.pdf, p.22)

ปัญหาที่หน้านี้แก้: ไลบรารี optimizer แบบคลาสสิก (เช่น scipy.optimize.minimize) รับพารามิเตอร์เป็นเวกเตอร์ 1 มิติก้อนเดียว ไม่ใช่รายการของเมทริกซ์. แต่เครือข่ายของเรามี \(\theta^{[1]}\) ขนาด \(10\times3\) และ \(\theta^{[2]}\) ขนาด \(1\times11\) คนละรูป. ทางออกคือ "unroll" — คลี่ทุกเมทริกซ์เป็นแถวยาวแล้วต่อกัน ส่งเข้า optimizer และเมื่อต้องใช้งานก็ "roll back" กลับเป็นรูปเดิม.

# Unroll parameters
nn_params = np.concatenate([Theta1.ravel(), Theta2.ravel()])

# Get Theta1 and Theta2 back from initial_nn_params
Theta1 = np.reshape(nn_params[:hidden_layer_size * (input_layer_size + 1)],
                    (hidden_layer_size, (input_layer_size + 1)))

Theta2 = np.reshape(nn_params[(hidden_layer_size * (input_layer_size + 1)):],
                    (num_labels, (hidden_layer_size + 1)))
โค้ดทำอะไร
Theta1.ravel()คลี่เมทริกซ์ \(10\times3\) เป็นเวกเตอร์ยาว 30 โดยไล่ทีละแถว (row-major / C order ซึ่งเป็นค่าเริ่มต้นของ numpy). ravel ต่างจาก flatten ตรงที่พยายามคืน view ไม่ copy ถ้าทำได้
np.concatenate([...])ต่อเวกเตอร์สองอันเป็นอันเดียว: 30 + 11 = 41 ตัว. ลำดับสำคัญมาก — Theta1 ต้องมาก่อน Theta2 เพราะการ reshape กลับข้างล่างตัดช่วงตามลำดับนี้
nn_params[:hidden_layer_size * (input_layer_size + 1)]ตัดช่วงแรก: \(10\times(2+1) = 30\) ตัวแรก = ข้อมูลของ Theta1. สังเกตว่าสูตรในวงเล็บคือสูตรมิติ \(b\times(a+1)\) จากหน้า 20 เป๊ะๆ
np.reshape(..., (hidden_layer_size, (input_layer_size + 1)))พับ 30 ตัวกลับเป็นรูป \((10, 3)\). ต้องใช้ลำดับ row-major เดียวกับตอน ravel ค่าจึงกลับเข้าช่องเดิม
nn_params[(hidden_layer_size * (input_layer_size + 1)):]ตัดช่วงที่เหลือ (ตัวที่ 31 เป็นต้นไป) = 11 ตัวของ Theta2. เครื่องหมาย : อยู่หลังตัวเลขคราวนี้ (ต่างจากบรรทัดบนที่อยู่หน้า) — สลับกันเมื่อไรได้ข้อมูลผิดก้อนทันที
(num_labels, (hidden_layer_size + 1))พับกลับเป็น \((1, 11)\) โดย num_labels = จำนวน output node

ผลลัพธ์ที่คาด (รันจริงด้วย input_layer_size=2, hidden_layer_size=10, num_labels=1): nn_params.shape = (41,); หลัง reshape กลับได้ Theta1.shape = (10, 3) และ Theta2.shape = (1, 11) ที่มีค่าเท่ากับต้นฉบับทุกช่อง (ตรวจด้วย np.allclose ได้ True ทั้งคู่).

ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 7Dimension of Parameters
เครือข่ายมี input 2 node, hidden 10 node, output 1 node ตามกฎ b×(a+1) มิติของ θ⁽¹⁾ และ θ⁽²⁾ คือเท่าใด?
คำถาม 8เติมโค้ด — Initialization
ต้องการสุ่ม W ให้อยู่ในช่วง −ε < W < ε ตามสไลด์หน้า 21 บรรทัดใดถูกต้อง?

5. Activation Function คืออะไร และอยู่ตรงไหนของเครือข่าย

ตลอด §2–§4 เราเขียน \(g\) ไว้เฉยๆ โดยไม่ถามว่ามันคือฟังก์ชันอะไร. ตอนนี้ถึงเวลาแล้ว เพราะ \(g'\) เป็นตัวคูณอยู่ในสูตร \(\delta\) ของทุก layer — เลือก \(g\) ผิด gradient ตายทั้งเครือข่าย.

More on activation function slide: an activation function is a nonlinear function that transforms or compresses the weighted and summed input values in a node, with a zoomed-in view of one node showing z = sum from i=0 to n of theta_i x_i and a = g(z), and red labels marking the Bias Unit x0 and the Weights theta10, theta11, theta12
Slide: More on Activation Function (Lecture3.pdf, p.23)

นิยามที่อาจารย์ทำสีไว้: activation function คือ nonlinear function ที่ "transforms or compresses the weighted and summed input values in a node, yielding the neuron's activation" — แปลง/บีบค่าที่รวมแบบถ่วงน้ำหนักมาแล้ว ให้กลายเป็น activation ของ neuron. คำว่า "compresses" อธิบายพฤติกรรมของ sigmoid/tanh ได้ดี: ไม่ว่า \(z\) จะเป็น 1,000 หรือ −1,000 ผลลัพธ์ถูกบีบให้อยู่ในช่วงแคบๆ เสมอ.

หน้านี้ซูมเข้าไปดูภายใน node หนึ่งตัวเพื่อแยกองค์ประกอบสามอย่างให้เห็นชัด: Bias Unit 𝑥0 คือ input พิเศษที่มีค่า 1 เสมอ, Weight θ10[1], θ11[1], θ12[1] คือตัวคูณของแต่ละเส้นที่เข้ามา (สามตัวเพราะมี bias + \(x_1\) + \(x_2\)) และ g (สไลด์ทำสีแดงตัวหนา) คือ activation. การคำนวณภายใน node เป็นสองจังหวะเสมอ:

$$z = \sum_{i=0}^{n}\theta_i x_i \qquad\text{แล้วจึง}\qquad a = g(z)$$

ทำไมต้องมี bias unit: ถ้าไม่มี \(x_0\) สมการ \(z = \theta_{11}x_1 + \theta_{12}x_2\) จะถูกบังคับให้ผ่านจุดกำเนิดเสมอ — เมื่อ input เป็น 0 ทั้งหมด \(z\) ต้องเป็น 0 และ \(a = g(0) = 0.5\) ตายตัว. bias คือตัวเลื่อนเส้นแบ่ง ทำให้ node "มีความเห็นของตัวเอง" ได้แม้ไม่มี input. เปรียบเทียบกับสมการเส้นตรง \(y = mx + c\): bias คือ \(c\) ส่วน weight คือ \(m\) — ถ้าไม่มี \(c\) เส้นตรงทุกเส้นต้องลากผ่านจุด (0,0).

สไลด์แบ่ง activation ออกเป็นสองที่ใช้งานซึ่งใช้คนละเกณฑ์ในการเลือก และนี่คือโครงของ §5 ถึง §6 ทั้งหมด:

ต้องรู้ก่อน — \(e\) และ \(e^{x}\) (exponential) คืออะไร

sigmoid, tanh, softmax และ softplus ทั้งหมดสร้างจาก \(e^{x}\) ถ้าไม่คุ้นกับมันจะอ่านสูตรไม่ออกเลย.

\(e\) คือค่าคงที่ \(2.71828\dots\) (เหมือน \(\pi\) แต่คนละตัว). \(e^{x}\) แปลว่า "เอา \(e\) มายกกำลัง \(x\)" ค่าที่ควรจำ:

\(x\)−3−10123
\(e^{x}\)0.04980.367912.71837.389120.086

สมบัติสามข้อที่ใช้ตลอดบทนี้: (1) \(e^{x} > 0\) เสมอ ไม่ว่า \(x\) จะติดลบแค่ไหน — นี่คือเหตุผลที่ softmax ใช้มันแปลงคะแนนติดลบให้เป็นความน่าจะเป็นได้; (2) \(e^{0}=1\); (3) \(e^{-x} = 1/e^{x}\) เช่น \(e^{-2} = 1/7.3891 = 0.1353\).

ลองคำนวณ sigmoid ด้วยมือ: \(g(2) = \dfrac{1}{1+e^{-2}} = \dfrac{1}{1+0.1353} = \dfrac{1}{1.1353} = 0.8808\) ✓ (ตรงกับตัวเลขใน §3). และฟังก์ชันผกผันของมันคือ \(\ln\) (natural log) ที่ใช้ใน cross-entropy: \(\ln(e^{x}) = x\).

Activation function at the hidden layers slide: a shallow neural network with 2 inputs, 10 hidden units a1[1] through a10[1] and one output, listing well-known non-linear activation functions sigmoid, tanh, ReLU, leaky ReLU and more such as ELU and SELU, alongside the gradient expression x1 delta1(1) = x1 (theta11[2])^T delta1(2) times g'(z1[1])
Slide: Activation Function at the Hidden Layers (Lecture3.pdf, p.24)

เหตุผลที่ hidden layer ต้องใช้ฟังก์ชันไม่เชิงเส้น สไลด์เขียนไว้ตรงๆ: "In order to learn more complex relationships, activation functions should expose non-linearity into the output of a neuron" (จะพิสูจน์ใน §5C). รายการที่สไลด์ให้มี 4 ตัวหลัก + กลุ่มขยาย: Sigmoid, Tanh, ReLU, Leaky ReLU และ "More activation functions such as ELU, SELU…".

แต่สิ่งที่สำคัญกว่ารายชื่อคือสูตร gradient ที่อาจารย์ยกมากำกับไว้ในหน้าเดียวกัน เพราะมันคือเหตุผลว่าทำไมการเลือก activation ถึงอยู่ในบท backpropagation ไม่ใช่บทอื่น:

$$x_1\delta_1^{(1)} = x_1\left(\theta_{11}^{[2]}\right)^{\!\top}\delta_1^{(2)} * g'\!\left(z_1^{[1]}\right)$$

นี่คือ gradient ของ \(\theta_{11}^{[1]}\) ที่เราพิสูจน์ไปแล้วใน §2 — และ \(g'\) นั่งอยู่เป็นตัวคูณตัวหนึ่งในนั้น. ตีความเป็นตัวเลข: ถ้าใช้ sigmoid และ \(z_1^{[1]}\) บังเอิญเป็น 4, ค่า \(g'(4) = 0.0177\) ⇒ gradient ของ weight ตัวนี้ถูกหั่นเหลือ 1.77% ทันทีในชั้นเดียว. ถ้าใช้ ReLU ที่ \(z=4\), \(g'=1\) ⇒ gradient ผ่านไปเต็มๆ. การเลือก activation จึงคือการเลือกว่าจะให้ gradient ไหลย้อนได้ดีแค่ไหน ไม่ใช่แค่เรื่องรูปร่างกราฟสวยงาม.

เครือข่ายตัวอย่างในหน้านี้คือ Shallow Neural Network: input 2 → hidden 10 (\(a_1^{[1]}\) ถึง \(a_{10}^{[1]}\)) → output 1 ซึ่งเป็นเครือข่ายเดียวกับที่จะใช้ในแบบฝึกหัดหน้า 47–48 และในโจทย์นับพารามิเตอร์หน้า 42. คำว่า "shallow" (ตื้น) หมายถึงมี hidden layer ชั้นเดียว ตรงข้ามกับ "deep" ที่มีหลายชั้น.

ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 9Activation Function
ตามนิยามในสไลด์หน้า 23 activation function คืออะไร และทำอะไรกับค่าที่เข้ามาใน node?

5A. Sigmoid และ Tanh: อนุพันธ์ ข้อดี และปัญหา zero-centered

5A.1 Sigmoid และอนุพันธ์ (หน้า 25)

Sigmoid function sigma(z)=1/(1+e^-z) with full derivative proof shown step by step, concluding sigma'(z)=sigma(z)(1-sigma(z)), alongside plots of the sigmoid curve (S-shaped, 0 to 1) and its derivative curve (bell-shaped, peaking at 0.25 when z=0)
Slide: Sigmoid และอนุพันธ์ — พิสูจน์เต็ม (Lecture3.pdf, p.25)

สไลด์หน้านี้ไล่พิสูจน์ \(\sigma'\) ทีละบรรทัดจนได้รูปสวยงาม \(\sigma(z)(1-\sigma(z))\). เหตุผลที่อาจารย์ยอมเสียทั้งหน้าให้การพิสูจน์นี้: รูปสุดท้ายทำให้คำนวณอนุพันธ์ได้จากค่า \(a\) ที่ forward คำนวณไว้แล้ว ไม่ต้องคำนวณ \(e^{-z}\) ใหม่ — ประหยัดมหาศาลเมื่อมี node เป็นล้าน.

พิสูจน์ \(\sigma'(z) = \sigma(z)\big(1-\sigma(z)\big)\) (ตามสไลด์หน้า 25)
\(\sigma(z) = \dfrac{1}{1+e^{-z}}\); ใช้ quotient rule \(\left(\dfrac{u}{v}\right)' = \dfrac{v u' - u v'}{v^2}\)
  1. ขั้นที่ 1 — ใส่ quotient rule ตรงๆ (\(u=1\), \(v=1+e^{-z}\))

    \(u' = 0\) (อนุพันธ์ของค่าคงที่) และ \(v' = -e^{-z}\) (chain rule: \(\frac{d}{dz}e^{-z} = e^{-z}\times(-1)\)):

    $$\sigma'(z) = \frac{(1+e^{-z})\cdot 0 - 1\cdot(-e^{-z})}{(1+e^{-z})^2} = \frac{e^{-z}}{(1+e^{-z})^2}$$
  2. ขั้นที่ 2 — แยกเป็นผลคูณของสองเศษส่วน (เพื่อให้เห็น \(\sigma\) โผล่ออกมา)
    $$\frac{e^{-z}}{(1+e^{-z})^2} = \frac{1}{1+e^{-z}}\cdot\frac{e^{-z}}{1+e^{-z}} = \sigma(z)\cdot\frac{e^{-z}}{1+e^{-z}}$$
  3. ขั้นที่ 3 — ทำเศษส่วนที่สองให้เป็น \(1-\sigma\) ด้วยเล่ห์ "บวกลบตัวเดียวกัน"

    เขียน \(e^{-z} = (1+e^{-z}) - 1\) แล้วแยกเศษ:

    $$\frac{e^{-z}}{1+e^{-z}} = \frac{(1+e^{-z}) - 1}{1+e^{-z}} = 1 - \frac{1}{1+e^{-z}} = 1-\sigma(z)$$
  4. ขั้นที่ 4 — ตรวจด้วยตัวเลขที่ \(z=2\)

    สูตร: \(\sigma(2)=0.8808\) ⇒ \(\sigma'(2) = 0.8808\times0.1192 = 0.10499\). ลองขยับจริง: \(\sigma(2.001) = 0.880902\) ⇒ \((0.880902-0.880797)/0.001 = 0.105\) ✓

$$\sigma'(z) = \sigma(z)\big(1-\sigma(z)\big) = a(1-a)$$
\(z\)−4−2024
\(\sigma(z)\)0.0180.1190.50.8810.982
\(\sigma'(z)\)0.01770.1050.250.1050.0177

อนุพันธ์ของ sigmoid มีค่าสูงสุดเพียง 0.25 ที่ \(z=0\) (เพราะ \(0.5\times0.5 = 0.25\) และผลคูณ \(a(1-a)\) ใหญ่สุดเมื่อ \(a=0.5\)) และหดเร็วเมื่อ \(|z|\) โต — ที่ \(z=\pm2\) เหลือ 0.105 ซึ่งต่ำกว่าครึ่งของยอดแล้ว. ถ้า sigmoid ต่อกัน \(L\) layer gradient จะถูกคูณด้วยตัวเลข \(\le0.25\) ซ้ำ \(L\) ครั้ง — เช่น 10 layer ⇒ \(0.25^{10} \approx 9.5\times10^{-7}\) คือเกือบหนึ่งในล้าน. นี่คือรากของ vanishing gradient ที่ Lesson 5 จะลงลึก.

5A.2 Tanh และอนุพันธ์ (หน้า 26)

Tanh and its derivative slide: the tanh function f(x) = (e^x - e^-x)/(e^x + e^-x) with a full quotient-rule derivation ending at f'(x) = 1 - f(x)^2, plus a plot of tanh rising from -1 to 1 and its bell-shaped derivative peaking at 1.0
Slide: Tanh (or Hyperbolic) and its Derivative (Lecture3.pdf, p.26)

สไลด์ใช้ quotient rule แบบเดียวกับ sigmoid แต่เศษและส่วนเป็นฟังก์ชันทั้งคู่ จึงยาวกว่า. ไล่ตามทุกบรรทัด:

พิสูจน์ \(f'(x) = 1 - f(x)^2\) เมื่อ \(f(x) = \tanh x\) (ตามสไลด์หน้า 26)
\(f(x) = \dfrac{e^{x}-e^{-x}}{e^{x}+e^{-x}}\); ให้ \(u = e^{x}-e^{-x}\), \(v = e^{x}+e^{-x}\)
  1. ขั้นที่ 1 — หาอนุพันธ์ของ \(u\) และ \(v\) ก่อน (สังเกตว่ามันสลับกัน)

    \(\frac{d}{dx}e^{-x} = -e^{-x}\) ดังนั้น \(u' = e^{x}-(-e^{-x}) = e^{x}+e^{-x} = v\) และ \(v' = e^{x}+(-e^{-x}) = e^{x}-e^{-x} = u\)

  2. ขั้นที่ 2 — ใส่ quotient rule (บรรทัดแรกในสไลด์)
    $$f'(x) = \frac{(e^{x}+e^{-x})\dfrac{d(e^{x}-e^{-x})}{dx} - (e^{x}-e^{-x})\dfrac{d(e^{x}+e^{-x})}{dx}}{(e^{x}+e^{-x})^2}$$
  3. ขั้นที่ 3 — แทน \(u'=v\) และ \(v'=u\) (บรรทัดที่สองในสไลด์)
    $$f'(x) = \frac{(e^{x}+e^{-x})(e^{x}+e^{-x}) - (e^{x}-e^{-x})(e^{x}-e^{-x})}{(e^{x}+e^{-x})^2} = \frac{(e^{x}+e^{-x})^2 - (e^{x}-e^{-x})^2}{(e^{x}+e^{-x})^2}$$
  4. ขั้นที่ 4 — แยกเศษออกเป็นสองเศษส่วน (บรรทัดสุดท้ายในสไลด์)
    $$= \frac{(e^{x}+e^{-x})^2}{(e^{x}+e^{-x})^2} - \frac{(e^{x}-e^{-x})^2}{(e^{x}+e^{-x})^2} = 1 - f(x)^2$$
  5. ขั้นที่ 5 — ค่าตัวอย่าง
    $$x=0:\ 1-0^2=1;\qquad x=1:\ 1-0.7616^2 = 0.420;\qquad x=2:\ 1-0.964^2 = 0.0707;\qquad x=4:\ 0.0013$$

ยอดของอนุพันธ์คือ 1 ที่ \(x=0\) — สูงกว่า sigmoid 4 เท่า ⇒ gradient ไหลย้อนได้ดีกว่าในชั้นต้นๆ. แต่ดูค่าที่ \(x=2\): tanh เหลือ 0.0707 ส่วน sigmoid เหลือ 0.105 — tanh หดเร็วกว่าเมื่อออกจากศูนย์. สรุปคือ tanh ดีกว่าตรงกลาง แต่ทั้งคู่ตายเหมือนกันที่ปลาย.

5A.3 Sigmoid vs Tanh (หน้า 27)

Sigmoid vs tanh slide: left plot overlays both curves showing sigmoid rising from 0 to 1 while tanh rises from -1 to 1 and crosses zero at x=0; right plot overlays their gradients showing the tanh gradient peaking at 1.0 and the sigmoid gradient peaking at 0.25, both flattening to zero beyond roughly x = plus or minus 4
Slide: Sigmoid vs Tanh (Lecture3.pdf, p.27)

อาจารย์สรุปการเปรียบเทียบไว้เป็นสามบรรทัดใต้กราฟ: "Sigmoid → Output is in [0,1]", "Tanh → Output is in [-1,1] (outputs - zero-centered)", และ "Both sigmoid and tanh slow when x is too large/small".

อ่านกราฟคู่ขวา (กราฟอนุพันธ์) ด้วยตัวเลขจริง: ที่ \(x=0\) เส้น tanh แตะ 1.00 ส่วนเส้น sigmoid แตะแค่ 0.25 — ต่างกัน 4 เท่า. เลยออกไปที่ \(|x|\ge4\) ทั้งสองเส้นแบนติดศูนย์ (sigmoid 0.0177, tanh 0.0013) ⇒ ตรงนั้นคือ "dead zone" ที่ gradient แทบไม่มี. นี่คือความหมายเชิงตัวเลขของคำว่า "slow when x is too large/small" — ไม่ใช่ว่าโค้ดทำงานช้า แต่คือการเรียนรู้ช้า เพราะ gradient เล็กจนแทบไม่ขยับ weight.

คำว่า "zero-centered" ของ tanh หมายความว่าอะไร: output ของ tanh กระจายรอบ 0 (ได้ทั้งบวกและลบ) ส่วน sigmoid ให้ค่าบวกเสมอ (0 ถึง 1) มีค่าเฉลี่ยราว 0.5. ฟังดูเป็นเรื่องเล็ก แต่หน้าถัดไปอธิบายว่ามันทำให้การเทรนช้าลงจริงๆ.

5A.4 ทำไม "ไม่ zero-centered" ถึงเป็นปัญหา (หน้า 28)

Slide linking the layer-2 gradient formula dJ/dtheta[2] = (h(x)-y) a[1] and the gradient descent update rule to a hand-drawn sketch of a zig-zag path in the w1-w2 plane travelling from a point labelled src to a point labelled tgt instead of going straight
Slide: Gradient Descent กับผลของ activation ที่ไม่ zero-centered (Lecture3.pdf, p.28)

หน้านี้วางสามอย่างไว้ด้วยกัน: สูตร gradient ของ layer 2, กฎอัปเดต gradient descent, และภาพวาดมือของเส้นทางที่วิ่งซิกแซกจากจุด src ไปจุด tgt ในระนาบ \((w_1, w_2)\). ทั้งสามอย่างเชื่อมกันเป็นเหตุผลเดียว ดังนี้:

จากสูตร \(\dfrac{\partial J}{\partial\theta^{[2]}} = \big(h_\theta(x)-y\big)a^{[1]}\) สังเกตว่า gradient ของ weight ทุกเส้นที่เข้า node เดียวกันมี \((h-y)\) เป็นตัวคูณร่วม ต่างกันแค่ \(a_j^{[1]}\). ถ้า activation เป็น sigmoid ⇒ \(a_j^{[1]} > 0\) ทุกตัว ⇒ gradient ของ weight ทุกตัวในแถวนั้นมีเครื่องหมายเดียวกันเสมอ (ตามเครื่องหมายของ \(h-y\)).

ลองกับตัวเลขจาก §3: \(\delta^{(2)} = -0.293\), \(a^{[1]} = (1,\ 0.8808,\ 0.8808)\) ⇒ gradient = \((-0.293,\ -0.258,\ -0.258)\) — ลบทั้งสามตัว ⇒ weight ทุกตัวเพิ่มพร้อมกัน. รอบถัดไปถ้าทำนายเกิน gradient จะบวกทั้งแถว ⇒ weight ทุกตัวลดพร้อมกัน. ผลคือทิศทางที่เดินได้มีแค่ "ขึ้นทั้งคู่" หรือ "ลงทั้งคู่" (ควอดรันต์ที่ 1 กับ 3 ของระนาบ \((w_1,w_2)\)) — แต่ถ้าจุดหมายอยู่ในทิศ "\(w_1\) ขึ้น \(w_2\) ลง" เราไปตรงๆ ไม่ได้ ต้องเดินซิกแซกสลับไปมาทีละก้าวเล็กๆ ซึ่งก็คือเส้นทางที่วาดไว้ในภาพ. ถ้าใช้ tanh ที่ \(a\) มีทั้งบวกและลบ เครื่องหมายของ gradient แต่ละตัวอิสระต่อกัน ⇒ เดินเฉียงตรงไปหาเป้าได้ทันที.

activation ที่ให้ค่าบวกล้วนบังคับให้ weight ทุกตัวในแถวเดียวกันขยับทิศเดียวกัน — เหมือนพายเรือที่ทุกคนต้องพายข้างเดียวกันเสมอ จะเลี้ยวก็ต้องสลับไปมา

สไลด์อ้างลิงก์ StackExchange ("why are non-zero-centered activation functions a problem in backpropagation") และหน้า 26 อ้างบทความของ LeCun ("Why zero-mean output") เป็นแหล่งอ่านต่อ — นี่คือเหตุผลทั้งหมดที่ตารางหน้า 32 ให้ "outputs - zero-centered" เป็นข้อดีของ tanh และ "outputs - not zero-centered" เป็นข้อเสียของ sigmoid.

5A.5 ผลการทดลองจริง: sigmoid vs tanh (หน้า 29)

Comparison between sigmoid and tanh: two rows of experiment output, the top row labelled sigmoid with training set accuracy 98.666667, a cost curve descending slowly over 6000 iterations, a gradient plot bounded within plus or minus 0.4, and a spiral dataset decision boundary; the bottom row labelled tanh with training set accuracy 99.833333, a cost curve dropping sharply before iteration 2000, a gradient plot spanning plus or minus 1.5, and a tighter spiral boundary
Slide: Comparison between sigmoid and tanh (Lecture3.pdf, p.29)

อาจารย์รันเครือข่ายเดียวกันบนชุดข้อมูล Spiral สองครั้ง เปลี่ยนแค่ activation ของ hidden layer แล้ววางผลเทียบกัน. ตัวเลขที่ต้องจำ:

# Comparison between sigmoid and tanh  (Spiral dataset, network เดียวกัน, 6000 iterations)
sigmoid   # Training Set Accuracy: 98.666667   gradient อยู่ในช่วงประมาณ -0.4 ถึง 0.4
tanh      # Training Set Accuracy: 99.833333   gradient อยู่ในช่วงประมาณ -1.5 ถึง 1.5
โค้ดทำอะไร
sigmoidป้ายกำกับของการรันชุดแรก — hidden layer ใช้ \(g(z)=1/(1+e^{-z})\). ผลที่ได้: Training Set Accuracy: 98.666667 เส้น cost ลงช้าแบบเป็นขั้นบันได และยังไม่แบนสนิทเมื่อถึงรอบที่ 6000
# Training Set Accuracy: 98.666667ความแม่นบน training set (หน่วยเป็นเปอร์เซ็นต์) ของการรันด้วย sigmoid. ถ้า training set มี 600 จุด นี่คือทายผิด 8 จุด
tanhป้ายกำกับของการรันชุดที่สอง — เปลี่ยนเฉพาะ activation ของ hidden layer เป็น \(\tanh\) ที่เหลือเหมือนเดิมทุกอย่าง. ผลที่ได้: Training Set Accuracy: 99.833333 เส้น cost ดิ่งลงเกือบสุดตั้งแต่ก่อนรอบที่ 2000
# Training Set Accuracy: 99.833333ความแม่นของการรันด้วย tanh — ทายผิดเพียง 1 จุดจาก 600 จุด. ดีขึ้นจาก sigmoid ประมาณ 1.17 จุดเปอร์เซ็นต์ โดยไม่แตะโครงสร้างเครือข่ายเลย

ผลลัพธ์ที่คาด (อ่านจากสไลด์): sigmoid = 98.666667, tanh = 99.833333. และกราฟ gradient ก็ยืนยันการพิสูจน์ในหัวข้อก่อนหน้าพอดี: gradient ของ sigmoid หนาแน่นอยู่ในช่วงแคบ \(\pm0.4\) ในขณะที่ tanh แกว่งถึง \(\pm1.5\) — อนุพันธ์ยอด 1 เทียบกับยอด 0.25 แสดงตัวออกมาเป็นขนาด gradient จริงๆ และ gradient ที่ใหญ่กว่าก็แปลว่า weight ขยับได้เร็วกว่าในแต่ละรอบ ซึ่งเห็นได้จากเส้น cost ของ tanh ที่ดิ่งเร็วกว่า.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
"รูปร่าง" ของอนุพันธ์ (ไม่ใช่แค่ช่วง output) กำหนดว่า gradient ไหลย้อนได้ไกลแค่ไหน เพราะ \(g'\) เป็นตัวคูณใน \(\delta\) โดยตรง — sigmoid ที่ช่วง output ดูดี (บีบ [0,1] ตีความเป็นความน่าจะเป็นได้) แต่อนุพันธ์เล็กและไม่ zero-centered ยังทำให้เทรนยาก.
เปลี่ยนแล้วเกิดอะไร
ที่ \(z=2\) (ไม่ใช่ 0): \(\sigma'(2) = 0.8808\times0.1192 = 0.105\) ลดไปกว่าครึ่งจากยอด 0.25 ทั้งที่ \(z=2\) ยังไม่ไกลจาก 0 — sigmoid saturate เร็วมาก. เปลี่ยนเป็น tanh ที่ \(z=0\) ได้ 1.0 (4 เท่า) ซึ่งสะท้อนออกมาเป็น accuracy 99.83% เทียบกับ 98.67% ในการทดลองหน้า 29.
เชื่อมกับ
\(z=2\) นี้คือ \(z_1^{[1]}\) ใน §3: \(\delta_1^{(1)}\) เล็ก (\(-0.0308\)) ส่วนหนึ่งเพราะ \(g'(2)=0.105\) ไม่ใช่ 0.25 — ตัวคูณหายเกินครึ่งตั้งแต่ layer เดียว.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 10Activation Derivative
อนุพันธ์ของ sigmoid σ'(z)=σ(z)(1−σ(z)) มีค่าสูงสุดเท่าใด และเกิดที่ z เท่าใด?

5B. ReLU, Leaky ReLU และตารางเปรียบเทียบ activation ทั้งสี่

5B.1 ReLU (หน้า 30)

ReLU function f(x)=0 for x<0 and f(x)=x for x>=0, piecewise linear, with derivative f'(x)=0 for x<0 and f'(x)=1 for x>=0, a simple step-like derivative
Slide: Rectified Linear Unit (ReLU) and its Derivative (Lecture3.pdf, p.30)

ReLU คือฟังก์ชันที่ง่ายที่สุดในบทนี้ — "ถ้าติดลบให้เป็น 0 ถ้าไม่ติดลบก็ปล่อยผ่าน":

$$f(x) = \begin{cases}0, & x < 0\\ x, & x \ge 0\end{cases}\qquad\qquad f'(x) = \begin{cases}0, & x < 0\\ 1, & x \ge 0\end{cases}$$

ลองใส่ตัวเลข: \(f(-3)=0\), \(f(-0.1)=0\), \(f(0)=0\), \(f(2)=2\), \(f(1000)=1000\). และอนุพันธ์: \(f'(-3)=0\), \(f'(2)=1\), \(f'(1000)=1\).

ทำไมอนุพันธ์ที่เป็น 1 คงที่ถึงเปลี่ยนเกม: ย้อนกลับไปที่สูตร \(\delta^{(l-1)} = (\theta^{[l]})^\top\delta^{(l)} * g'(z^{[l-1]})\). ถ้า \(g'=1\) เสมอในฝั่งบวก ตัวคูณนี้ไม่หั่น gradient เลย — คูณ 1 กี่ครั้งก็ยังเป็นตัวมันเอง. เทียบกันตรงๆ กับ sigmoid ในเครือข่าย 10 layer: sigmoid ให้ \(0.25^{10} = 9.5\times10^{-7}\) ส่วน ReLU (สมมติทุก node อยู่ฝั่งบวก) ให้ \(1^{10} = 1\) — ต่างกันประมาณหนึ่งล้านเท่า. นี่คือเหตุผลตัวเลขที่ ReLU ทำให้เทรนเครือข่ายลึกได้จริง.

ข้อเสียที่มากับความเรียบง่าย: ในฝั่ง \(x<0\) อนุพันธ์เป็น 0 สนิท ⇒ ถ้า node หนึ่งบังเอิญมี \(z<0\) สำหรับข้อมูลทุกตัว มันจะไม่ได้รับ gradient เลยตลอดกาล (เรียกว่า "dying ReLU"). ตารางหน้า 32 เรียกอาการนี้ว่า "information loss on \(x<0\)". อีกข้อคือ output ไม่มีขอบบน (\([0,\infty]\)) ซึ่งตารางเรียกว่า "output can be Infinite".

5B.2 Leaky ReLU (หน้า 31)

Leaky ReLU function f(x)=0.01x for x<0 and f(x)=x for x>=0 with its derivative f'(x)=0.01 for x<0 and 1 for x>=0, so the negative side has a small non-zero slope instead of being completely flat
Slide: Leaky ReLU and its Derivative (Lecture3.pdf, p.31)

Leaky ReLU แก้ปัญหา "ฝั่งลบตาย" ด้วยการให้ความชันเล็กๆ แทนที่จะเป็น 0 สนิท:

$$f(x) = \begin{cases}0.01x, & x < 0\\ x, & x \ge 0\end{cases}\qquad\qquad f'(x) = \begin{cases}0.01, & x < 0\\ 1, & x \ge 0\end{cases}$$

ตัวเลขเทียบกัน: ที่ \(x=-5\) ReLU ให้ \(f=0,\ f'=0\) (ตายสนิท) ส่วน Leaky ReLU ให้ \(f=-0.05,\ f'=0.01\) — เล็กมากแต่ไม่ใช่ศูนย์ ⇒ ยังมี gradient ไหลกลับผ่านได้ ⇒ node มีโอกาสฟื้นกลับมาใช้งานได้. ราคาที่จ่ายคือ output ขยายออกทั้งสองฝั่ง \([-\infty, \infty]\) ซึ่งตารางหน้า 32 ระบุเป็นข้อเสีย "output can be Infinite".

ReLU ปิดประตูฝั่งลบสนิท; Leaky ReLU แง้มประตูไว้ 1% เพื่อให้ gradient เล็ดลอดกลับมาได้

5B.3 ตารางเปรียบเทียบทั้งสี่ (หน้า 32) — หน้าที่ออกสอบบ่อยที่สุดของ §5

Four-column comparison table of Sigmoid, Tanh, ReLU and Leaky ReLU with rows for equation, output range, differential equation, advantages and disadvantages, each column topped by a plot of the function and a red plot of its derivative
Slide: ตารางเปรียบเทียบ Sigmoid · Tanh · ReLU · Leaky ReLU (Lecture3.pdf, p.32)

นี่คือตารางเดียวกับในสไลด์ ถอดออกมาเป็นข้อความให้อ่านได้โดยไม่ต้องเพ่งรูป (ข้อความในช่องเป็นคำของอาจารย์):

SigmoidTanhReLULeaky ReLU
Equation\(\sigma(x)=\dfrac{1}{1+e^{-x}}\)\(f(x)=\dfrac{e^{x}-e^{-x}}{e^{x}+e^{-x}}\)\(f(x)=\begin{cases}0,&x<0\\x,&x\ge0\end{cases}\)\(f(x)=\begin{cases}0.01x,&x<0\\x,&x\ge0\end{cases}\)
Output Range[0, 1][−1, 1][0, ∞][−∞, ∞]
Differential Equation\(\sigma'(x)=\sigma(x)(1-\sigma(x))\)\(f'(x)=1-f(x)^2\)\(f'(x)=\begin{cases}0,&x<0\\1,&x\ge0\end{cases}\)\(f'(x)=\begin{cases}0.01,&x<0\\1,&x\ge0\end{cases}\)
Advantageseasy to understand; Output is in [0,1] → classificationOutput is in [-1,1] → classification; outputs - zero-centeredfast calculation (better convergence)fast calculation
Disadvantagesslow when x is too large/small; outputs - not zero-centeredslow when x is too large/smalloutput can be Infinite; information loss on x<0 (??)output can be Infinite

ข้อดีของ ReLU ที่อาจารย์ทำสีแดงไว้ช่องเดียวในตารางทั้งตารางคือ fast calculation (better convergence) — คำนวณเร็ว จึงลู่เข้าเร็วกว่า. คำว่า "เร็ว" มีสองความหมายซ้อนกัน: (1) เร็วเชิงเครื่อง — ReLU คือการเทียบกับ 0 หนึ่งครั้ง ไม่ต้องคำนวณ \(e^{-x}\) ซึ่งเป็นการยกกำลังที่แพงกว่ามาก; (2) เร็วเชิงการเรียนรู้ — เพราะ \(g'=1\) ไม่หั่น gradient จึงเดินลงเขาได้ก้าวใหญ่กว่า ตามที่เห็นในกราฟ cost หน้า 34 ที่ ReLU ลู่เข้าภายใน ~1000 รอบขณะที่ sigmoid/tanh ใช้หลายพันรอบ.

จุดที่อาจารย์เองก็ตั้งข้อสงสัยไว้: ในช่อง Disadvantages ของ ReLU มีข้อความ "information loss on x<0" ตามด้วยเครื่องหมายคำถามสีแดง "??" — อ่านได้ว่าอาจารย์กำลังบอกว่าข้อเสียข้อนี้ยังถกเถียงได้: การตัดค่าลบทิ้งดูเหมือนสูญเสียข้อมูล แต่ในทางปฏิบัติมันคือกลไกที่ทำให้เครือข่าย "เลือกเปิดเฉพาะบาง node" (sparsity) ซึ่งมักช่วยมากกว่าทำร้าย. คำตอบที่ปลอดภัยในข้อสอบ: ระบุตามตารางว่าเป็นข้อเสียที่สไลด์เขียนไว้ แต่รู้ด้วยว่าในทางปฏิบัติ ReLU ยังเป็น state of the art (หน้า 33).

ข้อสังเกตที่ควรเห็นจากตาราง: ช่อง Advantages ของ sigmoid และ tanh พูดถึง "ช่วง output เหมาะกับ classification" (คุณสมบัติของค่าที่ออกมา) ส่วนของ ReLU/Leaky ReLU พูดถึง "fast calculation" (คุณสมบัติของการคำนวณ) — สองตระกูลนี้เก่งคนละด้าน จึงเป็นที่มาของหลักการเลือกว่า hidden layer ใช้ตระกูล ReLU, output layer ใช้ sigmoid/softmax ซึ่งจะสรุปใน §6.

5B.4 ควรใช้ activation ตัวไหนที่ hidden layer (หน้า 33)

What activation to use for hidden layers slide: rectified linear units (ReLU) are the current state of the art; because the gradient of a ReLU is either zero or a constant it is possible to reign in the vanishing exploding gradient issue; softplus f(x) = ln[1 + exp(x)] is the smooth version of ReLU and differentiable everywhere; if ReLU does not work try leaky ReLU or variants such as ELU, SELU, GELU; with a plot overlaying the dashed red ReLU and the smooth blue Softplus curve
Slide: What Activation to use for Hidden Layers (Lecture3.pdf, p.33)

คำแนะนำหลักที่อาจารย์ทำสีไว้: • Rectified linear units (ReLU) "are the current state of the art because they have proven to work in many different situations" — ReLU คือมาตรฐานปัจจุบันของ hidden layer. เหตุผลเชิงกลไกที่สไลด์ให้: "Because the gradient of a ReLU is either zero or a constant, it is possible to reign in the vanishing exploding gradient issue. ReLU activation functions have shown to train better in practice than sigmoid activation functions."

แกะประโยคนี้ให้เป็นตัวเลข: อนุพันธ์ของ ReLU มีได้แค่ 0 หรือ 1 — ไม่มีค่ากลางๆ อย่าง 0.25 หรือ 0.0177. ผลคือเมื่อคูณต่อกันหลายชั้น ผลคูณเป็นได้แค่ 0 (ทางตัน) หรือ 1 (ผ่านเต็ม) ไม่มีการ "หดทีละนิดจนหายไป" แบบ \(0.25^{10}\) และไม่มีการ "โตทีละนิดจนระเบิด" แบบตัวคูณ > 1 ⇒ คุมได้ทั้ง vanishing และ exploding gradient ตามที่สไลด์ว่า.

Softplus — สไลด์เสนอเป็นรุ่นเรียบของ ReLU: "Softplus is considered to be the smooth version of the ReLU. It has quite a similar shape to the ReLU but differentiable everywhere on the graph."

$$f(x) = \ln\big[1 + \exp(x)\big]$$

ลองตัวเลขเทียบกับ ReLU เพื่อดูว่า "smooth" แปลว่าอะไร: ที่ \(x=-3\) ReLU ให้ 0 พอดี Softplus ให้ \(\ln(1+0.0498) = 0.0486\); ที่ \(x=0\) ReLU ให้ 0 Softplus ให้ \(\ln 2 = 0.693\); ที่ \(x=2\) ReLU ให้ 2 Softplus ให้ \(\ln(1+7.389) = 2.127\). เห็นได้ว่า Softplus เกาะติด ReLU ที่ปลายทั้งสองข้าง แต่โค้งมนตรงมุมหัก \(x=0\) ซึ่งเป็นจุดเดียวที่ ReLU หาอนุพันธ์ไม่ได้ทางคณิตศาสตร์ (ความชันซ้ายเป็น 0 ความชันขวาเป็น 1 ไม่เท่ากัน) — Softplus จึง "differentiable everywhere" ตามที่สไลด์ว่า. ในทางปฏิบัติ ReLU ยังชนะเพราะเร็วกว่ามาก และปัญหามุมหักที่ \(x=0\) เป๊ะๆ แทบไม่เกิดกับเลขทศนิยมจริง.

ถ้า ReLU ไม่เวิร์ค: สไลด์แนะให้ลอง leaky ReLU หรือญาติของมันคือ ELU, SELU, GELU (สไลด์เขียนว่า "or its variances such as ELU, SELU, GELU..") พร้อมลิงก์อ่านต่อที่ encord.com. ทั้งสามตัวนี้สไลด์ไม่ได้ให้สูตร — ข้อสอบจึงน่าจะถามแค่ระดับ "รู้จักชื่อและรู้ว่าเป็นทางเลือกเมื่อ ReLU มีปัญหา". ลำดับที่ควรจำ: ReLU ก่อนเสมอ → ถ้ามีปัญหา (เช่น node ตายเยอะ) ค่อยไป leaky ReLU → แล้วจึง ELU/SELU/GELU. แหล่งอ้างอิงของหน้านี้คือหนังสือ Getting started with deep learning ของ Adam Gibson และ Josh Patterson.

5B.5 ผลการทดลองสามตัวเทียบกัน (หน้า 34)

Three-column comparison of sigmoid, tanh and relu on the spiral dataset: each column shows a cost curve, a gradient-magnitude plot and a decision boundary, with training set accuracies printed underneath as 98.666667, 99.833333 and 100.000000 respectively, and the relu run converging within about 4000 iterations with gradients spanning plus or minus 1.0
Slide: Comparison — sigmoid / tanh / relu (Lecture3.pdf, p.34)

หน้านี้ขยายการทดลองของหน้า 29 โดยเพิ่ม relu เข้ามาเป็นคอลัมน์ที่สาม ใช้ชุดข้อมูล Spiral เดียวกัน:

# Comparison: same network on the Spiral dataset, only the hidden activation changes
sigmoid   # Training Set Accuracy:  98.666667   (6000 iterations, gradient ~ -0.4 .. 0.4)
tanh      # Training Set Accuracy:  99.833333   (6000 iterations, gradient ~ -1.5 .. 1.5)
relu      # Training Set Accuracy: 100.000000   (4000 iterations, gradient ~ -1.0 .. 1.0)
โค้ดทำอะไร
sigmoidคอลัมน์ที่ 1 — ผลเดิมจากหน้า 29: 98.666667%. เส้น cost ยังไม่แบนสนิทเมื่อครบ 6000 รอบ และเส้นแบ่งคลาสบนภาพ Spiral ยังเก็บหางเกลียวด้านนอกได้ไม่หมด
tanhคอลัมน์ที่ 2 — 99.833333% ด้วยจำนวนรอบเท่ากัน. gradient แกว่งกว้างที่สุดในสามตัว (\(\pm1.5\)) สอดคล้องกับอนุพันธ์ยอด 1.0 ของมัน
reluคอลัมน์ที่ 3 — 100.000000% และแกนนอนของกราฟหยุดที่ 4000 รอบ ไม่ใช่ 6000 กล่าวคือได้คะแนนเต็มโดยใช้รอบน้อยกว่าอีกสองตัวหนึ่งในสาม — นี่คือ "better convergence" ที่ตารางหน้า 32 ทำสีแดงไว้ แสดงตัวเป็นตัวเลขจริง
# Training Set Accuracy: ...บรรทัดผลลัพธ์ที่โปรแกรมพิมพ์ออกมาใต้ภาพแต่ละคอลัมน์ — เป็นความแม่นบน training set ไม่ใช่ test set จึงบอกได้แค่ว่าโมเดล fit ข้อมูลฝึกได้ดีแค่ไหน (100% อาจหมายถึง overfit ก็ได้ ต้องดู validation ตาม §6A)

ผลลัพธ์ที่คาด (อ่านจากสไลด์): 98.666667 → 99.833333 → 100.000000. กราฟ gradient ของ relu มีลักษณะเฉพาะที่ควรสังเกต: มันกว้าง \(\pm1.0\) ในช่วงต้น แล้วยุบลงเกือบเป็นศูนย์หลังรอบที่ ~1000 ในขณะที่ของ sigmoid ยังแกว่งยาวไปจนถึงรอบ 5000 — แปลว่า relu หาคำตอบเจอแล้วจึงหยุดขยับ ส่วน sigmoid ยังคลำทางอยู่. เตือน: ตัวเลขเหล่านี้มาจากภาพในสไลด์โดยตรง ไม่ได้รันใหม่ (TensorFlow ไม่ได้ติดตั้งในเครื่องที่ใช้เตรียมบทเรียนนี้).

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
ReLU แก้ปัญหาที่ sigmoid/tanh มีร่วมกัน คือ "อนุพันธ์เล็กกว่า 1 เสมอ" ซึ่งทำให้ผลคูณหลายชั้นหดหายไป. การให้อนุพันธ์เป็น 1 พอดี (ไม่ใช่ 0.9 หรือ 1.1) คือจุดพอดีที่ไม่หดและไม่ระเบิด.
เปลี่ยนแล้วเกิดอะไร
ถ้าเปลี่ยนความชันฝั่งบวกของ ReLU จาก 1 เป็น 1.1: 10 layer ⇒ \(1.1^{10} = 2.59\) เท่า, 50 layer ⇒ \(1.1^{50} = 117\) เท่า ⇒ exploding gradient. ถ้าเป็น 0.9: \(0.9^{50} = 0.005\) ⇒ vanishing. เลข 1 เป๊ะคือค่าเดียวที่เสถียรทุกความลึก.
เชื่อมกับ
นี่คือสะพานตรงไปยัง Lesson 5 (vanishing/exploding gradient + weight initialization) — ReLU เป็นเครื่องมือชิ้นแรกที่แก้ปัญหานั้น ส่วน initialization และ batch normalization เป็นชิ้นถัดไป.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 11ตารางเปรียบเทียบ Activation
ตามตารางหน้า 32 ข้อใดจับคู่ช่วง output (Output Range) กับ activation function ได้ถูกต้องทั้งหมด?
คำถาม 12อ่านผลทดลอง (หน้า 29, 34)
จากผลการทดลองบนชุดข้อมูล Spiral ในสไลด์หน้า 29 และ 34 ข้อใดตรงกับตัวเลขที่พิมพ์ออกมา?

5C. ทำไม activation ต้องไม่เป็น Linear

Why not linear activation function slide: with f(x)=x at every node, layer 1 computes three linear combinations of x1 and x2, and layer 2 combines them again to give z1[2] = a + b x1 + c x2, a plain linear function, showing the whole 2-layer network collapses to a single linear function
Slide: Why not Linear Activation Function? (Lecture3.pdf, p.35)

สไลด์ตอบคำถามนี้ด้วยการลองทำจริง: สมมติ \(f(x)=x\) (linear — คือไม่ทำอะไรเลย) ทุก node ในเครือข่าย input 2 → hidden 3 → output 1 แล้วดูว่าได้อะไร.

Computation on layer 1 (สไลด์เขียนสามบรรทัด):

$$z_1^{[1]} = \theta_{10}^{[1]}+\theta_{11}^{[1]}x_1+\theta_{12}^{[1]}x_2,\quad z_2^{[1]} = \theta_{20}^{[1]}+\theta_{21}^{[1]}x_1+\theta_{22}^{[1]}x_2,\quad z_3^{[1]} = \theta_{30}^{[1]}+\theta_{31}^{[1]}x_1+\theta_{32}^{[1]}x_2$$

และเนื่องจาก \(f\) เป็น identity ⇒ \(a_j^{[1]} = f(z_j^{[1]}) = z_j^{[1]}\) (activation ไม่ได้แปลงอะไรเลย).

Computation on layer 2: \(z_1^{[2]} = \theta_{10}^{[2]} + \theta_{11}^{[2]}z_1^{[1]} + \theta_{12}^{[2]}z_2^{[1]} + \theta_{13}^{[2]}z_3^{[1]}\) — เมื่อแทน \(z_j^{[1]}\) ที่เป็นพหุนามดีกรี 1 ของ \(x_1,x_2\) เข้าไป แล้วรวมพจน์เหมือนกัน จะได้รูป

$$z_1^{[2]} = a + bx_1 + cx_2 \quad \to \quad (\textit{Linear Function})$$

ตามที่สไลด์สรุปไว้ทุกตัวอักษร. หัวข้อบนหน้าระบุผลเสียตรงๆ: "Not capable to learn complex relationship (just output linear function)".

พิสูจน์ด้วยตัวเลขจริง: linear ซ้อน linear ยังเป็น linear
ลดรูปเหลือ 1 input เพื่อให้เห็นชัด: layer 1 \(z^{[1]} = 2x + 1\); layer 2 \(z^{[2]} = 3a^{[1]} - 4\); activation เป็น \(f(x)=x\) ทุก node
  1. ขั้นที่ 1 — activation ไม่เปลี่ยนค่า
    $$a^{[1]} = f(z^{[1]}) = z^{[1]} = 2x + 1$$
  2. ขั้นที่ 2 — แทนเข้า layer 2 แล้วกระจาย
    $$z^{[2]} = 3(2x+1) - 4 = 6x + 3 - 4 = 6x - 1$$
  3. ขั้นที่ 3 — ลองเพิ่ม layer ที่ 3 ดูว่าช่วยไหม
    $$z^{[3]} = 2a^{[2]} + 5 = 2(6x-1) + 5 = 12x + 3$$
  4. ขั้นที่ 4 — ตรวจด้วยตัวเลข

    ที่ \(x=0\): \(z^{[3]} = 3\); ที่ \(x=1\): 15; ที่ \(x=2\): 27 — ผลต่างคงที่ 12 ทุกก้าว ⇒ เป็นเส้นตรงแน่นอน (ถ้าไม่เป็นเส้นตรง ผลต่างจะไม่คงที่)

ไม่ว่าจะซ้อนกี่ layer ก็ได้ฟังก์ชันเชิงเส้นของ \(x\) ตัวเดียว (สไลด์เขียนในรูป \(a+bx_1+cx_2\)). แปลว่าเครือข่าย 100 layer ที่ใช้ linear activation มีความสามารถเท่ากับ linear regression ตัวเดียว — เสียพารามิเตอร์ไปเปล่าๆ. non-linearity จึงไม่ใช่ของประดับ แต่เป็นสิ่งเดียวที่ทำให้ "ความลึก" มีความหมาย.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
การพิสูจน์นี้เป็นพีชคณิตล้วนๆ ไม่ใช่การสังเกตเชิงประสบการณ์: ผลรวมเชิงเส้นของผลรวมเชิงเส้น ยังคงเป็นผลรวมเชิงเส้น. ดังนั้น "ความลึกเพิ่มความสามารถ" เป็นจริงก็ต่อเมื่อมี non-linearity คั่นระหว่างชั้น.
เปลี่ยนแล้วเกิดอะไร
ใส่ sigmoid คั่นแค่ชั้นเดียวในตัวอย่างข้างบน: \(a^{[1]} = g(2x+1)\) ⇒ \(z^{[2]} = 3g(2x+1)-4\) ซึ่งเป็นเส้นโค้งรูป S ที่ผลต่างไม่คงที่แล้ว (ที่ \(x=0\to1\) ค่าเปลี่ยน 0.664 แต่ที่ \(x=2\to3\) เปลี่ยนแค่ 0.017) — เครือข่ายจึงวาดขอบเขตการตัดสินใจที่โค้งได้.
เชื่อมกับ
เหตุผลเดียวกับที่ Lesson 2 §1 บอกว่า NN แก้ปัญหา "ต้องสร้าง polynomial feature ด้วยมือ" — ถ้าไม่มี non-linearity ที่ hidden layer เครือข่ายทำได้แค่สิ่งที่ linear regression ทำได้อยู่แล้ว. และเป็นเหตุผลที่ output layer ของงาน regression ใช้ linear ได้ (หน้า 36) เพราะมันเป็นชั้นสุดท้าย ไม่มีชั้นถัดไปให้ยุบรวมด้วย.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 13Why Non-linear
ถ้าทุก node ในเครือข่ายใช้ activation แบบ linear (f(x)=x) ไม่ว่าจะมีกี่ layer ผลลัพธ์สุดท้ายเป็นอย่างไร?

6. Activation ที่ Output Layer: Regression, Binary และ Softmax

ที่ hidden layer เราเลือก activation ตามเกณฑ์ "gradient ไหลดีไหม" (จึงเลือก ReLU). ที่ output layer เกณฑ์เปลี่ยนไปคนละเรื่อง: ค่าที่ออกมาต้องอยู่ในรูปที่ตีความได้ตรงกับงาน. ทำนายราคาบ้านแล้วได้ค่าในช่วง [0,1] ก็ใช้ไม่ได้; ทำนายความน่าจะเป็นแล้วได้ค่า 7.3 ก็ใช้ไม่ได้เช่นกัน.

Activation function at the output layer slide: for regression use a linear activation f(x)=x or no activation; for binary classification use sigmoid f(x)=1/(1+e^-x) marked with three stars, or tanh; for multiclass classification use sigmoid or tanh per node with one node per class, or use Softmax marked with three stars which rescales outputs so they add up to 1.0
Slide: Activation Function at the Output Layer (Lecture3.pdf, p.36)

สไลด์แบ่งเป็นสามกรณีตามชนิดของงาน และใส่ดอกจัน *** กำกับตัวเลือกที่แนะนำ ซึ่งเป็นจุดที่ข้อสอบชอบหยิบ:

ชนิดงานActivation ที่ outputเหตุผล / สูตร
Regressionlinear activation (หรือไม่ใส่ activation เลย)\(f(x)=x\) — ทำนายตัวเลขที่เป็นเท่าไรก็ได้ ห้ามบีบช่วง
Binary Classificationsigmoid *** (หรือ tanh)\(f(x)=\dfrac{1}{1+e^{-x}}\) ให้ค่าใน [0,1] ตีความเป็นความน่าจะเป็นของคลาส 1 ได้; tanh ให้ \(\dfrac{e^{x}-e^{-x}}{e^{x}+e^{-x}}\) ในช่วง [−1,1]
Multiclass Classificationsigmoid (หรือ tanh) ทีละ node — 1 node = 1 class หรือ Softmax ***Softmax = "Rescaling outputs so they add up to 1.0"

ทำไม regression ใช้ linear ได้ทั้งที่ §5C เพิ่งบอกว่า linear ไม่ดี: เพราะข้อห้ามใน §5C เป็นเรื่องของ hidden layer ที่มีชั้นถัดไปมารวมต่อ (จึงยุบเป็นเส้นตรง). output layer เป็นชั้นสุดท้าย ไม่มีใครมารวมต่อแล้ว — ความไม่เชิงเส้นที่ hidden layer สร้างไว้ยังอยู่ครบ. ถ้าดันใส่ sigmoid ที่ output ของงาน regression ค่าทำนายจะถูกบีบอยู่ใน [0,1] ⇒ ทำนายราคาบ้าน 3 ล้านไม่ได้เลย.

Multi-class classification with sigmoid at output node: a label vector y = [2,1,3,0,...] converted to one-hot rows 0010, 0100, 0001, 1000, a network with one output node per class illustrated with four ball icons, and the cost function J = -(1/m) sum over i sum over k of y_k log h(x)_k + (1-y_k) log(1-h(x)_k)
Slide: Multi-class Classification (Sigmoid at Output Node) (Lecture3.pdf, p.37)

หน้านี้อธิบายวิธีแรกของ multiclass: ใช้ sigmoid แยกทุก node. ขั้นแรกต้องแปลงคำตอบให้เป็น one-hot encoding ก่อน. ตัวอย่างในสไลด์ใช้ 4 คลาส และแปลงเวกเตอร์ \(y = [2,\ 1,\ 3,\ 0,\ \dots]^\top\) เป็นเมทริกซ์:

\(y\) เดิมone-hotอ่านว่า
20 0 1 0ช่องที่ 3 เป็น 1 (นับคลาสจาก 0) ⇒ คลาส 2
10 1 0 0ช่องที่ 2 เป็น 1 ⇒ คลาส 1
30 0 0 1ช่องที่ 4 เป็น 1 ⇒ คลาส 3
01 0 0 0ช่องที่ 1 เป็น 1 ⇒ คลาส 0

ทำไมต้อง one-hot: ถ้าปล่อยคำตอบเป็นตัวเลข 0,1,2,3 โมเดลจะเข้าใจผิดว่าคลาส 3 "มากกว่า" คลาส 1 สามเท่า และคลาส 2 อยู่ "ระหว่าง" คลาส 1 กับ 3 — ทั้งที่มันเป็นแค่ชื่อ (ฟุตบอล/บาสเกตบอล/เทนนิส/ปิงปอง ตามภาพลูกบอล 4 ลูกในสไลด์) ไม่มีลำดับ. one-hot ทำให้ทุกคลาสอยู่ห่างกันเท่ากันหมด และทำให้ output layer มี 1 node ต่อ 1 คลาสพอดี.

cost function ของวิธีนี้คือ cross-entropy ของหน้า 1 แต่บวกผลรวมอีกชั้นเพื่อไล่ทุกคลาส \(k\):

$$J(\theta) = -\frac{1}{m}\sum_{i=1}^{m}\sum_{k=1}^{K}\Big[y_k^{(i)}\log\big(h_\theta(x^{(i)})\big)_k + \big(1-y_k^{(i)}\big)\log\Big(1-\big(h_\theta(x^{(i)})\big)_k\Big)\Big]$$

โดยที่ \(k\) = จำนวนคลาส output (สไลด์กำกับว่า "k is more than 2 classes"). อ่านให้ออก: ผลรวมชั้นนอก \(\sum_i\) ไล่ตัวอย่าง, ผลรวมชั้นใน \(\sum_k\) ไล่ node output. ในทางปฏิบัติแปลว่า "ทำ binary classification พร้อมกัน \(K\) ปัญหา" — node ที่ 1 ตอบว่า "ใช่ฟุตบอลไหม", node ที่ 2 ตอบว่า "ใช่บาสไหม" ฯลฯ แยกกันเป็นอิสระ. จุดอ่อนของวิธีนี้: เพราะแต่ละ node ตัดสินเองโดยไม่คุยกัน ผลรวมของ output ทั้งหมดจึงไม่จำเป็นต้องเท่ากับ 1 — อาจได้ \([0.9,\ 0.8,\ 0.1,\ 0.7]\) ซึ่งตีความเป็นความน่าจะเป็นของคลาสที่แยกขาดจากกันไม่ได้. นี่คือปัญหาที่หน้า 38 มาแก้.

Softmax activation function for multi-class classification: t_i = e^(z_i^[L]), a_i^[L] = t_i divided by the sum of all t values so each output is normalized and they add up to 1, with a note that the exponential handles negative outputs and amplifies the maximum value, the loss J = -(1/m) sum sum y_k log h(x)_k, and a diagram of an MLP with a ReLU hidden layer feeding a softmax output layer
Slide: Multi-class Classification (Softmax at Output Node) (Lecture3.pdf, p.38)

สไลด์นิยามว่า Softmax คือ activation ของทั้ง output layer พร้อมกัน (ไม่ใช่ทีละ node) ที่ rescales outputs ให้ node ทั้งหมดบวกกันได้ 1 และคืนค่าเป็น probability distribution เหนือคลาสที่ "mutually exclusive" (แยกขาดจากกัน — เป็นได้แค่คลาสเดียว). สไลด์เสริมว่ามันคือ "A generalization of logistic regression for multi-class classification".

สูตรสองบรรทัดตามสไลด์: ตั้ง \(t_i = e^{z_i^{[L]}}\) แล้ว

$$a_i^{[L]} = \frac{t_i}{\sum_{i=1}^{n}t_i}$$

คอมเมนต์ที่อาจารย์เขียนกำกับไว้ท้ายสูตร: "each \(a_i^{[L]}\) are normalized, and they add up to 1." — ทุกช่องถูก normalize แล้วและบวกกันได้ 1

คำนวณ Softmax ด้วยมือ ทีละขั้น (3 คลาส)
สมมติ output layer ให้ \(z = [1,\ 3,\ 0.5]\) (ค่าดิบก่อน activation เรียกว่า logit)
  1. ขั้นที่ 1 — ยกกำลัง \(e\) ทุกช่อง (ได้ \(t_i\))
    $$t = [e^{1},\ e^{3},\ e^{0.5}] = [2.7183,\ 20.0855,\ 1.6487]$$

    สังเกตว่าช่องที่ 2 ซึ่งเดิมนำอยู่ 2 หน่วย ตอนนี้นำอยู่เกือบ 7 เท่า — exponential ขยายช่องว่าง.

  2. ขั้นที่ 2 — รวมทุกช่อง
    $$\sum t_i = 2.7183+20.0855+1.6487 = 24.4525$$
  3. ขั้นที่ 3 — หารแต่ละช่องด้วยผลรวม
    $$a = \left[\frac{2.7183}{24.4525},\ \frac{20.0855}{24.4525},\ \frac{1.6487}{24.4525}\right] = [0.1112,\ 0.8214,\ 0.0674]$$
  4. ขั้นที่ 4 — ตรวจ
    $$0.1112+0.8214+0.0674 = 1.0000\ ✓$$

อ่านผลเป็นภาษาคน: "โมเดลเชื่อว่าเป็นคลาสที่ 2 ด้วยความมั่นใจ 82.1%, คลาสที่ 1 11.1%, คลาสที่ 3 6.7%" — ตีความเป็นความน่าจะเป็นได้ทันทีเพราะบวกกันได้ 1 พอดี ซึ่งวิธี sigmoid แยก node ของหน้า 37 ทำไม่ได้.

ทำไมต้องใช้ exponential — สไลด์ให้เหตุผลไว้สองข้อ ใน note ที่ควรท่องได้: "The reason why using exponential is that some output might be negative – aka to logistic that mapping to [0,1] and it also amplifies the maximum value relative to the other values, forcing the model to be 'less neutral' toward prediction."

  1. เหตุผลที่ 1 — จัดการค่าติดลบ

    logit อาจติดลบได้ เช่น \(z = [-1,\ -2]\). ถ้าหารด้วยผลรวมตรงๆ จะได้ \(-1/(-3) = 0.333\) และ \(-2/(-3)=0.667\) ⇒ คลาสที่คะแนนต่ำกว่ากลับได้ความน่าจะเป็นสูงกว่า — ผิดสิ้นเชิง. แต่ \(e^{x} > 0\) เสมอ ⇒ \(e^{-1}=0.3679,\ e^{-2}=0.1353\) ⇒ ได้ \([0.7311,\ 0.2689]\) ซึ่งเรียงลำดับถูกต้อง. นี่คือความหมายของ "aka to logistic that mapping to [0,1]".

  2. เหตุผลที่ 2 — ขยายช่องว่างของตัวที่มากที่สุด ("less neutral")

    จากตัวอย่างข้างบน \(z=[1,3,0.5]\): ถ้าใช้สัดส่วนธรรมดา \(1/4.5, 3/4.5, 0.5/4.5 = [0.222, 0.667, 0.111]\) แต่ softmax ให้ \([0.111, 0.821, 0.067]\) — ตัวที่ชนะได้ส่วนแบ่งเพิ่มจาก 66.7% เป็น 82.1%. โมเดลจึง "กล้าฟันธง" มากขึ้นแทนที่จะตอบกลางๆ.

Loss ของ softmax ที่สไลด์ให้ ต่างจากของหน้า 37 ตรงที่มีเทอมเดียว:

$$J(\theta) = -\frac{1}{m}\sum_{i=1}^{m}\sum_{k=1}^{K}y_k^{(i)}\log\big(h_\theta(x^{(i)})\big)_k$$

เพราะสไลด์กำกับว่า \(y_k^{(i)} = 1\) only for the correct class, 0 otherwise ⇒ ในผลรวม \(\sum_k\) มีแค่พจน์เดียวที่ไม่เป็นศูนย์ คือพจน์ของคลาสที่ถูก. พูดง่ายๆ: cost = \(-\log(\)ความน่าจะเป็นที่โมเดลให้กับคำตอบที่ถูก\()\). จากตัวอย่างข้างบน ถ้าคำตอบจริงคือคลาสที่ 2: cost \(= -\ln 0.8214 = 0.1967\) (ต่ำ ดี); ถ้าคำตอบจริงคือคลาสที่ 3: cost \(= -\ln 0.0674 = 2.697\) (สูง โดนปรับหนัก). ไม่ต้องมีเทอม \((1-y)\log(1-h)\) เพราะการบังคับให้ผลรวมเป็น 1 อยู่แล้วทำให้การดันคลาสที่ถูกขึ้น อัตโนมัติ กดคลาสที่ผิดลง.

ภาพขวาของสไลด์ (Figure 10-9 จากหนังสือ Hands-on ML) แสดงสถาปัตยกรรมที่ใช้จริง: input layer → hidden layer (e.g., ReLU) → Softmax output layer — ตรงกับคำแนะนำรวมของบทนี้พอดี คือ ReLU ที่ hidden, softmax ที่ output สำหรับงาน multiclass.

คำนวณ: \(\delta^{[L]}\) ของ softmax + cross-entropy
logit \(z = [2, 1, 0]\) ⇒ \(a = [0.6652,\ 0.2447,\ 0.0900]\); คลาสจริงคือคลาสแรก \(y = [1,0,0]\)
  1. ขั้นที่ 1 — ใช้สูตรเดิม \(\delta = a - y\) ทีละช่อง
    $$\delta = [0.6652-1,\ 0.2447-0,\ 0.0900-0] = [-0.3348,\ 0.2447,\ 0.0900]$$
  2. ขั้นที่ 2 — ตีความเครื่องหมาย

    ช่องของคลาสที่ถูก (−0.3348): ลบ ⇒ ต้องเพิ่ม \(z_1\); ช่องคลาสผิด (บวก): ต้องลด \(z_2, z_3\). ผลรวมของ \(\delta\) เท่ากับ 0 พอดี — สมเหตุสมผล เพราะผลรวมของ \(a\) และของ \(y\) ต่างก็เป็น 1.

สูตร \(\delta^{[L]} = a^{[L]} - y\) จาก §2 ใช้ได้เหมือนเดิมกับ softmax + cross-entropy — เป็นเหตุผลเดียวกับที่ sigmoid + cross-entropy หักล้าง \(g'\) พอดี. นี่คือสาเหตุที่เฟรมเวิร์กรวม softmax เข้าไปในฟังก์ชัน loss (เช่น CrossEntropyLoss ของ PyTorch รับ logit ดิบ ไม่ใช่ softmax แล้ว) — รวมกันแล้วอนุพันธ์ง่ายและเสถียรกว่าแยกกัน.

คำนวณ: softmax ไม่เปลี่ยนเมื่อบวกค่าคงที่ให้ทุก logit
เปลี่ยน \(z = [2,1,0]\) เป็น \(z' = [12, 11, 10]\) (บวก 10 ทุกตัว)
  1. ขั้นที่ 1 — ดึง \(e^{10}\) ออกจากทุกเทอม
    $$a_1' = \frac{e^{12}}{e^{12}+e^{11}+e^{10}} = \frac{e^{10}\cdot e^{2}}{e^{10}\,(e^{2}+e^{1}+1)}$$
  2. ขั้นที่ 2 — \(e^{10}\) หักล้างกันบนล่าง
    $$a_1' = \frac{e^{2}}{e^{2}+e^{1}+1} = \frac{7.389}{11.107} = 0.6652$$

เท่ากับตัวอย่างเดิมเป๊ะ ⇒ softmax ขึ้นกับความต่างระหว่าง logit เท่านั้น ไม่ขึ้นกับระดับสัมบูรณ์. ใช้จริง: โค้ดมักลบ \(\max(z)\) ก่อนคำนวณ (เช่น \([2,1,0]\to[0,-1,-2]\)) เพื่อกัน \(e^{z}\) ล้น (overflow) โดยไม่เปลี่ยนคำตอบ — ตรวจแล้วได้ \([0.1112, 0.8214, 0.0674]\) เท่าเดิมทุกตำแหน่ง.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
softmax ต้อง normalize ทั้ง layer พร้อมกัน เพราะเป้าหมายคือความน่าจะเป็นที่รวมกันได้ 1 พอดี (คลาสแยกขาดจากกัน) — คำนวณทีละ node แบบ sigmoid ไม่มีทางบังคับผลรวม = 1 ได้เลย ดังที่เห็นในวิธีของหน้า 37.
เปลี่ยนแล้วเกิดอะไร
ถ้าใช้ sigmoid แยก node กับงานที่คลาสแยกขาดจากกัน อาจได้ \([0.9, 0.8, 0.1, 0.7]\) (รวม 2.5) ซึ่งแปลเป็นความน่าจะเป็นไม่ได้ และถ้าใช้ softmax กับงานที่ติดได้หลายป้ายพร้อมกัน (multi-label เช่น รูปหนึ่งมีทั้งหมาและแมว) ก็ผิด เพราะ softmax บังคับให้แย่งกัน 100% — เลือกตามว่าคลาส mutually exclusive หรือไม่.
เชื่อมกับ
คุณสมบัติ "บวกค่าคงที่แล้วไม่เปลี่ยน" คือเหตุผลที่ implementation จริง (Keras/PyTorch) ลบ \(\max(z)\) เพื่อความเสถียรเชิงตัวเลข — ต่อใน Lesson 5 ตอนเขียน Keras.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 14Softmax vs Sigmoid
ข้อแตกต่างสำคัญระหว่าง Softmax กับ Sigmoid เมื่อใช้เป็น activation ที่ output layer คืออะไร?

6A. ประเมินและปรับปรุงโมเดล: Train / Validation / Test, Bias vs Variance

ถึงตรงนี้เราเทรนโมเดลเป็นแล้ว. คำถามถัดไปคือ "รู้ได้อย่างไรว่ามันดีจริง" — และคำตอบไม่ใช่ accuracy บน training set (ซึ่ง relu ได้ 100% ในหน้า 34 แต่นั่นคือข้อสอบที่โมเดลเคยเห็นเฉลยมาแล้ว).

Model evaluation slide: goal is to determine how well a model performs on unseen examples; split into Training, Validation and Test Set e.g. randomly 60-20-20 or 70-15-15 with a diagram showing a data column split into m_train 60 percent, m_cv 20 percent and m_test 20 percent; or split into Training and Test Set 80-20 or 70-30 and perform Cross Validation with a schematic of 5-fold CV where one shaded fold rotates through five rows
Slide: Model Evaluation (Lecture3.pdf, p.39)

อาจารย์เปิดหน้าด้วยการทำสี • Goal ไว้ชัดเจน: determine how well a model can be expected to perform on unseen examples — เป้าหมายคือคาดการณ์ผลบนข้อมูลที่โมเดลไม่เคยเห็น ไม่ใช่ข้อมูลที่ใช้เทรน. จากนั้นตั้งคำถาม • How to evaluate the model และให้สองแนวทาง:

แนวทางที่ 1 — แบ่งสามส่วน: • Training, Validation และ Test Set เช่น สุ่มแบ่ง 60-20-20 หรือ 70-15-15. แปลงเป็นตัวเลขจริงกับชุดข้อมูล 1,000 ตัวอย่าง:

สัดส่วน\(m_{\text{train}}\)\(m_{\text{cv}}\) (validation)\(m_{\text{test}}\)
60-20-20600200200
70-15-15700150150

หน้าที่ของแต่ละส่วนต่างกันคนละเรื่อง และนี่คือจุดที่สับสนบ่อย: training set ใช้ปรับ \(\theta\) (backprop ทำงานกับชุดนี้เท่านั้น); validation set ใช้ตามที่สไลด์เขียนว่า "Evaluate an array of different architectures (#hidden units, #layer, lambda….) on your validation set" — คือใช้เลือก hyperparameter ว่าจะเอากี่ layer กี่ node \(\lambda\) เท่าไร; test set ใช้รายงานผลครั้งเดียวตอนจบ ห้ามเอามาตัดสินใจอะไรทั้งสิ้น (ไม่งั้นมันก็กลายเป็น validation set อีกอัน).

คำเตือนที่สำคัญที่สุดของหน้า: "Make sure that all train/validation/test set comes from the same distribution to preventing data leakage during the testing process." — ทุกชุดต้องมาจากการแจกแจงเดียวกัน. ตัวอย่างที่ผิด: เทรนด้วยรูปถ่ายจากกล้องมืออาชีพ แต่ test ด้วยรูปจากมือถือ ⇒ ผลที่วัดได้ไม่สะท้อนความจริง. ส่วน data leakage คืออาการที่ข้อมูล test รั่วเข้าไปในขั้นตอนเทรน เช่น normalize ข้อมูลทั้งก้อนก่อนแบ่ง (ค่าเฉลี่ยที่ใช้ปนข้อมูล test ไปแล้ว) หรือมีตัวอย่างซ้ำอยู่ทั้งสองฝั่ง ⇒ คะแนน test สูงเกินจริง.

แนวทางที่ 2 — แบ่งสองส่วนแล้วทำ cross validation: • Training และ Test Set (เช่น สุ่ม 80-20 หรือ 70-30) แล้วทำ Cross Validation. สไลด์อธิบายวิธี k-fold ไว้ว่า "dividing the dataset into k subsets (folds). The model is trained on k-1 folds and validated on the remaining fold, with this process repeated k times".

เดิน 5-fold cross validation ด้วยตัวเลข (ตามภาพ schematic ในสไลด์)
training set 1,000 ตัวอย่าง, \(k=5\)
  1. ขั้นที่ 1 — แบ่งเป็น 5 ก้อนเท่าๆ กัน
    $$1000 / 5 = 200\ \text{ตัวอย่างต่อ fold}$$
  2. ขั้นที่ 2 — วน 5 รอบ แต่ละรอบสลับว่า fold ไหนเป็นตัววัด

    รอบที่ 1: เทรนด้วย fold 2,3,4,5 (800 ตัวอย่าง) วัดด้วย fold 1 (200); รอบที่ 2: เทรนด้วย fold 1,3,4,5 วัดด้วย fold 2; … จนถึงรอบที่ 5 — ทุกตัวอย่างได้เป็น "ตัววัด" พอดีหนึ่งครั้ง

  3. ขั้นที่ 3 — เฉลี่ยคะแนน 5 รอบ

    เช่นได้ accuracy \([0.91, 0.88, 0.93, 0.90, 0.89]\) ⇒ เฉลี่ย \(0.902\) และส่วนเบี่ยงเบนบอกว่าผลนิ่งแค่ไหน

ข้อดีเหนือการแบ่งครั้งเดียว: ถ้าแบ่ง validation แค่ก้อนเดียว 200 ตัว ผลอาจ "ฟลุ๊ก" ตามว่าสุ่มได้ตัวอย่างง่ายหรือยาก. k-fold ใช้ข้อมูลทุกตัวทั้งเป็นตัวเทรนและตัววัด ⇒ ประมาณการนิ่งกว่า. ราคาที่จ่าย: ต้องเทรน \(k\) ครั้ง — สไลด์ระบุ 5-fold, 10-fold เป็นค่าที่นิยม. นี่คือเหตุผลที่ deep learning (ซึ่งเทรนครั้งเดียวก็นานแล้ว) มักใช้แนวทางที่ 1 มากกว่า.

Model improvement slide: High Bias (not fit training set well) fixed by adding relevant features, training longer with more iterations, increasing hidden units and layers; High Variance (only fit training very well) fixed by getting more data, removing non-informative features, removing hidden units and layers, regularization, dropout, early stopping and data augmentation; with a diagnostic curve where J_train keeps falling while J_cv turns upward, and two training-history plots labelled High Bias (Underfitting) and High Variance (Overfitting)
Slide: Model Improvement — Diagnostic Bias vs Variance (Lecture3.pdf, p.40)

เมื่อวัดผลแล้วไม่พอใจ หน้านี้บอกว่าต้องวินิจฉัยก่อนว่าเป็นโรคไหน แล้วจึงเลือกยา — ใช้ยาผิดโรคจะแย่ลง:

อาการสังเกตจากวิธีแก้ที่สไลด์ให้
High Bias (not fit training set well) = Underfitting\(J_{\text{train}}\) สูง และ \(J_{cv}\) ก็สูงพอๆ กันAdd relevant features · Train longer / increase #iteration · Increase #hidden, #layer
High Variance (only fit training very well) = Overfitting\(J_{\text{train}}\) ต่ำมาก แต่ \(J_{cv}\) สูง (ช่องว่างกว้าง)Get more data · Remove non informative features · Remove some #hidden, #layer · Regularization · Dropout (later) · Early stopping (later) · Data Augmentation (later)

สังเกตว่ารายการทั้งสองฝั่งตรงข้ามกันเป๊ะ: bias สูงให้ เพิ่ม hidden/layer, variance สูงให้ ลด hidden/layer. นี่คือกับดักข้อสอบที่พบบ่อยที่สุดของหน้านี้ — ถ้าจำสลับกันก็ตอบผิดทั้งข้อ. วิธีจำ: bias สูง = โมเดลโง่เกินไป ต้องทำให้ฉลาดขึ้น; variance สูง = โมเดลท่องจำมากเกินไป ต้องทำให้มันจำน้อยลง. คำว่า "(later)" ที่กำกับ Dropout / Early stopping / Data Augmentation หมายถึงจะสอนในบทหลัง (Lesson 6) — ส่วน Regularization สอนในหน้าถัดไปของบทนี้เลย.

กราฟ "Diagnostic Bias vs Variance" ตรงกลางหน้าคือเครื่องมือวินิจฉัยที่ใช้จริง: แกนนอนคือ Training Time (จำนวนรอบ) เส้นสีแดง \(J_{\text{train}}\) ลดลงเรื่อยๆ ไม่หยุด ส่วนเส้นสีเขียว \(J_{cv}\) ลดลงช่วงแรกแล้วกลับเชิดขึ้น. ช่วงซ้ายสุด (ทั้งสองเส้นยังสูง) คือโซน High Bias; ช่วงขวาสุด (เส้นแดงต่ำ เส้นเขียวสูง ช่องว่างกว้าง) คือโซน High Variance; จุดที่ \(J_{cv}\) ต่ำสุดคือจุดที่ควรหยุด. นี่เชื่อมกับข้อความใต้ภาพพอดี: "A major challenge in training neural networks is how long to train them — long enough to learn the mapping, but not so long that it overfits the training data. Stop training at the point when performance on a validation set starts to degrade." ซึ่งก็คือนิยามของ early stopping นั่นเอง. ภาพ training history สองภาพด้านขวาแสดงอาการจริง: ภาพบน (High Bias) เส้น acc และ val_acc ต่ำใกล้กันทั้งคู่ราว 0.6–0.7; ภาพล่าง (High Variance) เส้น acc ไต่ขึ้นเกือบ 0.9 แต่ val_acc ค้างที่ ~0.7 และ val_loss เชิดขึ้นสวนทางกับ loss ที่ดิ่งลงเหลือ 0.2 — ช่องว่างระหว่างเส้นฝึกกับเส้น validation คือตัวชี้วัด overfitting ที่อ่านง่ายที่สุด.

ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 15Bias vs Variance
โมเดลให้ training accuracy 99% แต่ validation accuracy 71% ตามสไลด์หน้า 40 ควรทำอย่างไร?

7. Regularization: บีบ weight ให้เล็กเพื่อแก้ High Variance

หน้า 40 ระบุ "Regularization" เป็นหนึ่งในยาแก้ High Variance สามหน้าถัดไปคือคำอธิบายเต็มของยาตัวนั้น.

Regularization slide: keep all features (each contributes a bit to predict output) but constrains or regularizes the parameters to small values (many cases towards zero but not zero); the L1 (lasso) and L2 (ridge) regularization, focusing on L2, adds the term lambda over m times the triple sum of theta squared to the cost; two Circle Dataset scatter plots compare a wiggly decision boundary with a smooth one
Slide: Regularization (Lecture3.pdf, p.41)

แนวคิดที่อาจารย์ทำสีไว้: • Keep all features (each contributes a bit to predict output) แต่ constrains or regularizes พารามิเตอร์ให้เป็นค่าเล็กๆ ("many cases towards zero but not zero").

ทำไมวิธีนี้ถึงแก้ overfitting ได้: ลองนึกถึงเครือข่ายที่ท่องจำข้อมูลฝึกได้เป๊ะ — มันต้องวาดเส้นแบ่งที่หยักไปมาอย่างรุนแรงเพื่อเลี้ยวหลบจุดแปลกๆ ทุกจุด และการจะหยักแรงได้ต้องมี weight ที่ใหญ่ (เพราะ \(z=\sum\theta x\) จะเปลี่ยนเร็วเมื่อ \(\theta\) ใหญ่). ดังนั้นการบีบ \(\theta\) ให้เล็กลงก็คือการบังคับให้เส้นแบ่ง "เรียบขึ้น" โดยอัตโนมัติ. ภาพ Circle Dataset สองภาพในสไลด์แสดงผลนี้ตรงๆ: ภาพซ้ายเส้นแบ่งบิดเป็นหยักเว้าแหว่งไล่ตามจุดข้อมูลรายจุด ส่วนภาพขวาเส้นแบ่งเป็นวงรีเรียบที่คลุมกลุ่มจุดสีแดงตรงกลางได้โดยไม่ไล่ตามจุดรบกวนแต่ละจุด — ข้อมูลชุดเดียวกัน ต่างกันแค่มีเทอม regularization หรือไม่.

"Keep all features" คือจุดต่างสำคัญ — ไม่ได้ทิ้ง feature ไหนเลย แค่ลดเสียงของทุก feature ลงพร้อมกัน

วิธีทำคือบวกเทอมโทษ (penalty) เข้าไปใน cost:

$$J_{\text{reg}}(\theta) = J(\theta) + \frac{\lambda}{m}\left[\sum_{l=1}^{L}\sum_{i=1}^{s_i}\sum_{j=1}^{s_j}\left(\theta_{ij}^{(l)}\right)^2\right]$$

ผลรวมมีสามชั้นเพราะต้องไล่ให้ครบทุก weight: \(l\) = layer, \(i\) = node ปลายทางใน layer นั้น, \(j\) = node ต้นทาง. ส่วน \(\lambda\) (lambda) คือ hyperparameter ที่ควบคุมว่าจะบีบแรงแค่ไหน — \(\lambda=0\) คือไม่บีบเลย, \(\lambda\) ใหญ่คือบีบจน weight เกือบเป็นศูนย์หมด (underfit).

Cost function with regularization slide: L2 regularization or Ridge adds cost proportional to the square of the value of parameters, with a worked question asking how many parameters are in the regularization term for a 3-layer binary classification network with 2 inputs, 10 hidden and 1 output; L1 regularization or Lasso adds cost proportional to the absolute value of parameters; with a bold note that the regularization term should only be added during training
Slide: Cost Function with Regularization (Lecture3.pdf, p.42)

หน้านี้วาง L2 กับ L1 เทียบกันให้เห็นว่าต่างกันแค่จุดเดียว:

L2 (Ridge)L1 (Lasso)
เทอมที่บวกเข้า cost\(\dfrac{\lambda}{m}\left[\sum_l\sum_i\sum_j\left(\theta_{ij}^{(l)}\right)^2\right]\)\(\dfrac{\lambda}{m}\left[\sum_l\sum_i\sum_j\left|\theta_{ij}^{(l)}\right|\right]\)
คำที่อาจารย์ทำสี"square of the value of parameters""absolute value of parameters"
\(\theta = 3\) โดนปรับเท่าไร (ต่อ \(\lambda/m\))\(3^2 = 9\)\(|3| = 3\)
\(\theta = 0.5\) โดนปรับเท่าไร\(0.5^2 = 0.25\)\(|0.5| = 0.5\)

อาจารย์ทำสีไว้ว่า • L2 Regularization (หรือ Ridge) คือการเพิ่ม cost ที่แปรผันกับ square of the value of parameters ส่วน • L1 Regularization (หรือ Lasso) แปรผันกับ absolute v alue of parameters.

ตัวเลขในตารางบอกความต่างเชิงพฤติกรรม: L2 ลงโทษ weight ตัวใหญ่หนักกว่ามาก (\(\theta=3\) โดน 9 ส่วน \(\theta=0.5\) โดนแค่ 0.25 — ต่างกัน 36 เท่า ทั้งที่ค่าต่างกัน 6 เท่า) จึงเน้นกด weight ก้อนใหญ่ให้เล็กลงแต่ไม่ค่อยฆ่าให้เป็นศูนย์. ส่วน L1 ลงโทษเป็นสัดส่วนตรง (ต่างกัน 6 เท่าพอดี) ⇒ มีแรงกดคงที่แม้ weight เล็กมาก จึงมักดัน weight บางตัวให้เป็นศูนย์สนิท (เท่ากับคัด feature ทิ้ง).

เฉลยโจทย์ในสไลด์: "How many parameters in regularization term?"
โจทย์จากสไลด์: binary classification, เครือข่าย 3 layer (#input = 2, #hidden = 10, #output = 1)
  1. ขั้นที่ 1 — ใช้กฎ \(b\times(a+1)\) จากหน้า 20 กับ \(\theta^{[1]}\)
    $$\theta^{[1]}: 10 \times (2+1) = 30$$
  2. ขั้นที่ 2 — \(\theta^{[2]}\)
    $$\theta^{[2]}: 1 \times (10+1) = 11$$
  3. ขั้นที่ 3 — รวม
    $$30 + 11 = 41$$

41 พารามิเตอร์ ถ้านับรวม bias ตามสูตรมิติในสไลด์. หมายเหตุที่ควรรู้ (เสริมความเข้าใจ นอกสไลด์): ในทางปฏิบัติ bias มักไม่ถูก regularize (เพราะ bias ไม่ได้ทำให้เส้นแบ่งหยัก แค่เลื่อนตำแหน่ง) ⇒ จำนวนที่ถูกบีบจริงคือ \(10\times2 + 1\times10 = 30\) ตัว. สไลด์หน้า 43 ก็สอดคล้องกับข้อนี้เพราะแยกสูตร gradient ของ \(j=0\) ออกจาก \(j\ge1\). ในข้อสอบ: ถ้าโจทย์ถามตามสูตรผลรวมสามชั้นที่เขียนไว้หน้า 41–42 ให้ตอบ 41; ถ้าโจทย์ระบุว่า "ไม่รวม bias" ให้ตอบ 30.

คำเตือนตัวหนาใต้หน้า 42 ที่ออกสอบง่ายมาก: "Note that the regularization term should only be added to the cost function during training. Once the model is trained, you want to evaluate the model's performance using the unregularized performance measure." — เทอม regularization ใส่เฉพาะตอนเทรนเท่านั้น. เหตุผล: ค่า \(J_{\text{reg}}\) เป็นส่วนผสมของ "ทำนายผิดเท่าไร" กับ "weight ใหญ่เท่าไร" ⇒ ถ้าเอาไปรายงานผล ตัวเลขจะไม่ใช่ความผิดพลาดของการทำนายจริง และเทียบข้ามโมเดลที่ใช้ \(\lambda\) ต่างกันไม่ได้เลย.

Gradient descent with L2 regularization slide: Lasso may behave erratically when several features are strongly correlated and is not amenable to gradient descent, hence focusing on L2; the highlighted update rule theta := theta - alpha times dJ/dtheta, with the regularized gradient written as D = (1/m) Delta for j=0 and D = (1/m) Delta + (lambda/m) theta for j >= 1, and a note that some literature divides the cost function by 2
Slide: Gradient Descent with L2 Regularization (Lecture3.pdf, p.43)

ประโยคแรกของหน้าตอบคำถามที่ค้างจากหน้า 41 ว่า "ทำไมเน้น L2": "Unfortunately, Lasso may behave erratically when several features are strongly correlated and is not amenable to gradient descent, which means that we won't be able to solve it from scratch. Hence, we will focus on L2." — เหตุผลสองข้อคือ (1) L1 แกว่งไม่นิ่งเมื่อ feature สัมพันธ์กันมาก และ (2) L1 เข้ากับ gradient descent ไม่ได้. ข้อหลังมีเหตุผลทางคณิตศาสตร์ตรงไปตรงมา: อนุพันธ์ของ \(|\theta|\) ที่ \(\theta=0\) ไม่มีอยู่จริง (ความชันฝั่งซ้ายเป็น −1 ฝั่งขวาเป็น +1 ไม่เท่ากัน — เหมือนมุมหักของ ReLU ที่ 0) ส่วนอนุพันธ์ของ \(\theta^2\) คือ \(2\theta\) ซึ่งหาได้ทุกจุดรวมทั้งที่ 0. เมื่อจะเขียน backprop เองจากศูนย์จึงใช้ L2 ได้สะดวกกว่า.

สูตร gradient ที่รวม regularization แล้ว (สไลด์แยกเป็นสองกรณี):

$$\frac{\partial}{\partial\theta_{ij}^{(l)}}J(\Theta) = D_{ij}^{(l)} = \frac{1}{m}\Delta_{ij}^{(l)}\qquad\qquad\text{สำหรับ } j = 0$$ $$\frac{\partial}{\partial\theta_{ij}^{(l)}}J(\Theta) = D_{ij}^{(l)} = \frac{1}{m}\Delta_{ij}^{(l)} + \frac{\lambda}{m}\theta_{ij}^{(l)}\qquad\text{สำหรับ } j \ge 1$$

คอลัมน์ \(j=0\) คือ bias — ไม่ถูกบีบ; คอลัมน์อื่นบวกเทอม \(\dfrac{\lambda}{m}\theta\) เข้าไปใน gradient

แล้วอัปเดตด้วยกฎเดิมทุกประการ \(\theta_{ij}^{[l]} := \theta_{ij}^{[l]} - \alpha\dfrac{\partial J(\theta)}{\partial\theta_{ij}^{[l]}}\) (สไลด์ไฮไลต์สีเหลืองไว้เพื่อย้ำว่าไม่มีอะไรเปลี่ยนในขั้นอัปเดต — สิ่งที่เปลี่ยนคือค่าของ gradient เท่านั้น).

คำนวณ: ผลของเทอม regularization ต่อ gradient 1 ตัว
ใช้ตัวเลขจาก §3: \(\frac{1}{m}\Delta_{11}^{(2)} = -0.25808\), \(\theta_{11}^{[2]} = 1\), \(m=2\), \(\alpha=0.1\); ลอง \(\lambda = 0.1\)
  1. ขั้นที่ 1 — เป็น \(j=1\) (ไม่ใช่ bias) จึงบวกเทอม regularization
    $$D_{11}^{(2)} = -0.25808 + \frac{0.1}{2}(1) = -0.25808 + 0.05 = -0.20808$$
  2. ขั้นที่ 2 — อัปเดต
    $$\theta_{11}^{[2]} := 1 - 0.1(-0.20808) = 1.020808$$

    เทียบกับกรณีไม่มี regularization ที่ได้ 1.025808 — weight โตน้อยลง

  3. ขั้นที่ 3 — ส่วน bias \(j=0\) ไม่เปลี่ยนสูตร
    $$D_{10}^{(2)} = -0.29301\ (\text{เท่าเดิม}) \Rightarrow \theta_{10}^{[2]} := 0.029301$$

เทอม \(\frac{\lambda}{m}\theta\) มีเครื่องหมายเดียวกับ \(\theta\) เสมอ ⇒ เมื่อเข้าสูตร \(\theta - \alpha D\) มันจะดึง \(\theta\) เข้าหาศูนย์ทุกรอบ ไม่ว่า \(\theta\) จะเป็นบวกหรือลบ. ผลสะสมคือ weight ถูก "หดตัว" ทีละนิดทุกรอบ (บางตำราจึงเรียกว่า weight decay) ซึ่งสมดุลกับแรงจาก \(\Delta\) ที่พยายามดันให้ใหญ่ขึ้นเพื่อ fit ข้อมูล.

หมายเหตุท้ายหน้า 43: "Note that some literature divides the cost function by 2 so that the gradient of regularization terms are resulted as above. We will use this equation and this trick in the workshop." — บางตำราเขียน cost เป็น \(\frac{1}{2m}\) และเทอม penalty เป็น \(\frac{\lambda}{2m}\sum\theta^2\) เพื่อให้เวลาหาอนุพันธ์ เลข 2 จากกำลังสอง (\(\frac{d}{d\theta}\theta^2 = 2\theta\)) ไปหักกับ 2 ที่ตัวส่วนพอดี ⇒ เหลือ \(\frac{\lambda}{m}\theta\) สวยงามตามสูตรข้างบน. สไลด์ระบุว่าจะใช้รูปนี้ต่อใน workshop จึงควรจำรูปนี้.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
NN มีพารามิเตอร์กระจายหลาย layer พร้อมกัน (ไม่ใช่ \(\theta\) ก้อนเดียวแบบ logistic regression) การบีบให้เล็กจึงต้องรวมทุกตัวทุก layer ในเทอมเดียว — จึงเป็นที่มาของผลรวมสามชั้น \(\sum_l\sum_i\sum_j\).
เปลี่ยนแล้วเกิดอะไร
เพิ่ม hidden layer อีก 1 ชั้น (2→10→10→1): \(\theta^{[1]}:30\), \(\theta^{[2]}:110\), \(\theta^{[3]}:11\) รวม \(151\) — จาก 41 เป็น 151 (เกือบ 4 เท่า) ทั้งที่ hidden node รวมเพิ่มแค่เท่าตัว เพราะ layer กลางเชื่อมกัน \(10\times10=100\) เส้น. ยิ่งพารามิเตอร์เยอะ ยิ่งเสี่ยง overfit ยิ่งต้องพึ่ง regularization.
เชื่อมกับ
เหตุผลที่ Lesson 4 §2 บอกว่า deep network เสี่ยง overfit กว่า wide network ที่พารามิเตอร์เท่ากัน และเป็นยาตัวเดียวกับ Dropout / Early stopping ที่ Lesson 6 จะสอน (ทั้งหมดอยู่ในรายการ High Variance หน้า 40).
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 16Regularization
ตามสไลด์หน้า 42–43 ข้อใดอธิบาย L1 (Lasso) และ L2 (Ridge) ได้ถูกต้อง?

7A. Best Practice, Parameter vs Hyperparameter และ Tuning Guideline

Best practice to model improvement slide: start with relatively few layers and parameters, gradually increase the size of the layers or add new layers until diminishing returns on validation loss, use techniques to overcome overfitting; with three training-history plots labelled High Bias (Underfitting), High Variance (Overfitting) and Low Bias and Low Variance (Right Model)
Slide: Best Practice to Model Improvement (Lecture3.pdf, p.44)

สไลด์ให้สูตรการทำงานสามข้อ: (1) "Starting with relatively few layers and/or parameters" — เริ่มจากเล็กก่อน; (2) "Gradually increase the size of the layers (increase the number of neurons) or add new layers until you see diminishing returns with regards to validation loss" — ค่อยๆ ขยายจนกว่าจะเริ่มได้ผลตอบแทนลดน้อยถอยลง โดยดูจาก validation loss ไม่ใช่ training loss; (3) "Use techniques to overcome overfitting" — เมื่อขยายจนเริ่ม overfit ก็ใส่ยาจากรายการหน้า 40.

กราฟสามภาพใต้หน้าคือสามสถานะที่ต้องแยกให้ออกจากเส้น 4 เส้น (loss, accuracy, val_loss, val_accuracy): ภาพ High Bias — เส้น accuracy กับ val_accuracy พันกันอยู่แถว 0.6–0.7 และ loss ลงช้าๆ ค้างที่ ~0.55 แปลว่าโมเดลไม่เก่งพอแม้แต่กับข้อมูลที่เคยเห็น; ภาพ High Variance — accuracy ไต่ถึง ~0.93 แต่ val_accuracy ค้างที่ ~0.73 และ val_loss เชิดขึ้นสวนทาง loss ที่ลงไปถึง ~0.2 แปลว่าท่องจำข้อมูลฝึกแต่ใช้กับของใหม่ไม่ได้; ภาพ Low Bias and Low Variance (Right Model) — ทั้ง accuracy และ val_accuracy วิ่งไปชนเพดานเกือบ 1.0 พร้อมกัน และ loss กับ val_loss ก็ลงมาต่ำใกล้กันทั้งคู่ภายในราว 4 epoch. ตัวชี้วัดที่ต้องดูจึงไม่ใช่เส้นใดเส้นหนึ่ง แต่คือ "ช่องว่างระหว่างเส้นฝึกกับเส้น validation" ควบคู่กับ "ระดับความสูงของทั้งคู่".

Parameters and hyper parameter slide: Parameter is theta which is initialized randomly; Hyper Parameter is a parameter that controls theta, listing learning rate alpha, number of layers, number of hidden units, lambda, keep_prob, activation functions and number of iterations; with a machine-learning versus deep-learning pipeline diagram where deep learning merges feature extraction and classification
Slide: Parameters and Hyper Parameter (Lecture3.pdf, p.45)

นิยามสองคำที่สับสนกันบ่อยที่สุดในวิชานี้: Parameter คือ \(\theta\) ซึ่ง "initialized randomly" แล้วโมเดลเรียนรู้เองผ่าน backprop + gradient descent; Hyper Parameter คือ "a parameter that control \(\theta\)" — ตัวที่เราตั้งเองก่อนเทรน และเป็นตัวกำหนดว่า \(\theta\) จะถูกเรียนอย่างไร.

รายการ hyperparameter ที่สไลด์ให้ โดยสองตัวแรกทำสีแดงไว้: • Learning rate 𝛼, #layer, # hidden units, lambda, keep_prob, activation functions, #iterations. สังเกตว่าทุกตัวในรายการนี้ไม่มีตัวไหนถูกอัปเดตโดย gradient descent เลย — นั่นคือเส้นแบ่งที่ชัดที่สุดระหว่างสองคำ. (\(\lambda\) คือค่าความแรงของ regularization จาก §7; keep_prob เป็นของ Dropout ซึ่งจะสอนใน Lesson 6.)

parameter = สิ่งที่โมเดลเรียนเอง; hyperparameter = ปุ่มที่เราหมุนเอง แล้วเลือกค่าที่ดีที่สุดด้วย validation set

Hyperparameter tuning guideline slide: Number of Layers typically 1-5 with 1 hidden layer by default and 2 possibly enough, larger and more layers identify subtler patterns; Number of Hidden Units - too few lacks flexibility, too many is expensive and prone to overfitting, the pyramid sizing practice has been largely abandoned in favour of the same number of neurons in all hidden layers, typically 5 to 100 units; Learning rate alpha tuned by plotting the cost function or automatic debugging
Slide: Hyperparameter Tuning Guideline (Lecture3.pdf, p.46)

หน้านี้ให้ตัวเลขที่ใช้ตอบข้อสอบได้ตรงๆ สามกลุ่ม:

1. • Number of Layers — "Typically, 1-5, 1 hidden layer is by default and 2 layers might be good enough" และ "larger and more layers are capable of identifying more subtle patterns and complex decision boundaries". ตัวเลขที่ต้องจำ: 1–5 ชั้น, ค่าเริ่มต้นคือ 1 ชั้น, 2 ชั้นมักพอแล้ว.

2. • Number of Hidden Units — สไลด์ให้การชั่งน้ำหนักสองด้านและข้อปฏิบัติที่เปลี่ยนไป:

ประเด็นสิ่งที่สไลด์ระบุ
น้อยเกินไป"the model might not have enough flexibility to capture the nonlinearities in the data" (underfit)
มากเกินไป"computation expensive and the model is prone to overfitting"
รูปพีระมิดเคยนิยมจัดให้ node ลดหลั่นลงทีละชั้น "however this practice has been largely abandoned now, as it seems that simply using the same number of neurons in all hidden layers performs just as well in most cases, or even better, and there is just one hyperparameter to tune instead of one per layer"
ช่วงที่ใช้บ่อย"somewhere in the range of 5 to 100" โดยถ้า input น้อยให้ใช้ hidden ราว 3-4 เท่าของจำนวน input; ถ้า input มากให้ใช้ hidden น้อยกว่าจำนวน input; และปิดท้ายว่า "the perfect amounts of neurons is still somewhat of a dark art"

ข้อ "พีระมิดถูกเลิกใช้แล้ว" เป็นจุดที่อาจารย์เขียนยาวที่สุดในหน้า จึงมีโอกาสออกสอบสูง — และเหตุผลที่ให้ไว้ไม่ใช่แค่ "ผลเท่ากัน" แต่คือมี hyperparameter ให้จูนแค่ตัวเดียวแทนที่จะเป็นตัวหนึ่งต่อชั้น. ลองคิดเป็นตัวเลข: เครือข่าย 3 hidden layer แบบพีระมิดต้องเลือก \((n_1, n_2, n_3)\) สามตัว ถ้าแต่ละตัวมี 10 ทางเลือกก็ต้องลอง \(10^3 = 1000\) แบบ; แต่ถ้าใช้จำนวนเท่ากันทุกชั้นเหลือ 10 แบบ — ประหยัดกว่าร้อยเท่า.

3. • Learning rate 𝜶 — "By plotting the cost function or automatic debugging, however the best is parameter tuning (later class)" — วิธีพื้นฐานคือพล็อตกราฟ cost ดูด้วยตา (\(\alpha\) ใหญ่ไป cost จะแกว่งหรือพุ่งขึ้น; \(\alpha\) เล็กไป cost จะลงช้ามาก) ส่วนวิธีที่ดีที่สุดคือ hyperparameter tuning อย่างเป็นระบบ ซึ่งสไลด์บอกว่าจะสอนในคาบหลัง (Lesson 6).

ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 17Hyperparameter Tuning
ตามสไลด์หน้า 46 ข้อใดตรงกับ guideline เรื่องจำนวน layer และจำนวน hidden unit?

8. Binary Classification Exercise: ฝึกเขียนสูตรทั่วไปด้วยตัวเอง

สองหน้าสุดท้ายก่อน references คือแบบฝึกหัดที่อาจารย์ทิ้งไว้ให้เขียนเอง — ไม่มีตัวเลข \(\theta\) ให้ เพราะเป้าหมายคือฝึกเขียนสูตร ไม่ใช่กดเครื่องคิดเลข.

Binary classification exercise forward computation: a shallow neural network with inputs x1, x2 plus bias x0, ten hidden units a1[1] through a10[1] each with weights theta10[1] through theta102[1], and one output a1[2] producing h(x) in {0,1}, shown next to the Spiral dataset scatter plot with red and blue classes
Slide: Binary Classification Exercise – Forward Computation (Lecture3.pdf, p.47)

โจทย์: shallow neural network ที่รับ \(x_1, x_2\) (+ \(x_0\)) → hidden 10 node → output 1 node ที่ให้คำตอบเป็น \(\{0,1\}\) บนชุดข้อมูล Spiral (เกลียวสองสีที่แยกกันด้วยเส้นตรงไม่ได้ — จึงต้องใช้ hidden layer). เฉลย Forward Computation:

เฉลยหน้า 47 — Forward Computation (\(j = 1,\dots,10\))
\(\theta^{[1]}\) ขนาด \(10\times3\) (ตามกฎ \(b\times(a+1)\)), \(\theta^{[2]}\) ขนาด \(1\times11\); sigmoid ที่ output เพราะเป็น binary classification (หน้า 36)
  1. ขั้นที่ 1 — hidden layer ทีละ node
    $$z_j^{[1]} = \theta_{j0}^{[1]} + \theta_{j1}^{[1]}x_1 + \theta_{j2}^{[1]}x_2,\qquad a_j^{[1]} = g\!\left(z_j^{[1]}\right)$$

    ทำซ้ำ 10 ครั้ง (\(j=1\) ถึง 10) — เช่น node สุดท้ายคือ \(z_{10}^{[1]} = \theta_{10,0}^{[1]} + \theta_{10,1}^{[1]}x_1 + \theta_{10,2}^{[1]}x_2\) ซึ่งตรงกับป้าย \(\theta_{10\,0}^{[1]}, \theta_{10\,1}^{[1]}, \theta_{10\,2}^{[1]}\) บนเส้นในรูป

  2. ขั้นที่ 2 — เติม bias ของ hidden layer
    $$a_0^{[1]} = 1\ \Rightarrow\ a^{[1]} = \left[1,\ a_1^{[1]},\ a_2^{[1]},\ \dots,\ a_{10}^{[1]}\right]\ (11\ \text{ช่อง})$$
  3. ขั้นที่ 3 — output layer (ผลรวมยาว 10 พจน์ + bias)
    $$z_1^{[2]} = \theta_{10}^{[2]} + \sum_{j=1}^{10}\theta_{1j}^{[2]}a_j^{[1]},\qquad h_\theta(x) = a_1^{[2]} = g\!\left(z_1^{[2]}\right)$$
  4. ขั้นที่ 4 — แปลงเป็นคำตอบ \(\{0,1\}\)
    $$\hat{y} = \begin{cases}1, & h_\theta(x) \ge 0.5\\ 0, & h_\theta(x) < 0.5\end{cases}$$

ข้อควรระวังในสไลด์: ป้าย weight จาก \(a_{10}^{[1]}\) ไป output ในรูปเขียนว่า \(\theta_{13}^{[2]}\) ซึ่งเป็นการยกรูปมาจากสไลด์หน้า 20 ที่มี hidden แค่ 3 node. ในเครือข่าย 10 node นี้ index ที่ถูกต้องคือ \(\theta_{1,10}^{[2]}\) — เป็น typo ของสไลด์. คำตอบที่ปลอดภัยในข้อสอบ: \(\theta^{[2]}\) มี 11 ช่อง คือ \(\theta_{10}^{[2]}\) (bias) และ \(\theta_{11}^{[2]}\) ถึง \(\theta_{1,10}^{[2]}\).

Binary classification exercise backward computation: the same shallow network with 2 inputs, 10 hidden units and one output, this time asking for the backward pass formulas, again next to the Spiral dataset scatter plot
Slide: Binary Classification Exercise – Backward Computation (Lecture3.pdf, p.48)

หน้า 48 ถามส่วน backward ของเครือข่ายเดียวกัน. ประเด็นทั้งหมดของแบบฝึกหัดนี้คือ: สูตรไม่เปลี่ยนเลยแม้ hidden จะมี 10 node แทน 2 node — เปลี่ยนแค่ช่วงของ \(j\).

เฉลยหน้า 48 — Backward Computation (\(j = 1,\dots,10\))
  1. ขั้นที่ 1 — error ที่ output
    $$\delta_1^{(2)} = a_1^{[2]} - y = h_\theta(x) - y$$
  2. ขั้นที่ 2 — กระจายย้อนกลับไปทุก hidden node
    $$\delta_j^{(1)} = \theta_{1j}^{[2]}\,\delta_1^{(2)}\,g'\!\left(z_j^{[1]}\right),\qquad g'\!\left(z_j^{[1]}\right) = a_j^{[1]}\left(1-a_j^{[1]}\right)$$

    สังเกตว่า \(a_0^{[1]}\) ไม่มี \(\delta\) เพราะมันเป็นค่าคงที่ 1 ไม่ได้มาจาก \(z\) ใดๆ ⇒ มี \(\delta^{(1)}\) เพียง 10 ตัว ไม่ใช่ 11

  3. ขั้นที่ 3 — แปลง \(\delta\) เป็น gradient
    $$\frac{\partial J}{\partial\theta_{1j}^{[2]}} = \delta_1^{(2)}a_j^{[1]}\ (11\ \text{ค่า รวม } j=0),\qquad \frac{\partial J}{\partial\theta_{ji}^{[1]}} = \delta_j^{(1)}x_i\ (10\times3 = 30\ \text{ค่า})$$
  4. ขั้นที่ 4 — สะสม เฉลี่ย และอัปเดต
    $$\Delta_{ij}^{(l)} \mathrel{+}= a_j^{[l-1]}\delta_i^{(l)};\qquad D_{ij}^{(l)} = \frac{1}{m}\Delta_{ij}^{(l)};\qquad \theta_{ij}^{[l]} := \theta_{ij}^{[l]} - \alpha D_{ij}^{(l)}$$

รวมแล้วต้องคำนวณ gradient \(30 + 11 = 41\) ค่าต่อหนึ่งรอบ — ตรงกับจำนวนพารามิเตอร์ที่นับไว้ในโจทย์ regularization หน้า 42 พอดี (เครือข่ายเดียวกัน). และสูตรทุกบรรทัดเหมือนกับ §3 ทุกตัวอักษร ต่างแค่ \(j\) วิ่งถึง 10 แทน 2.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
backprop เป็น local operation: แต่ละ node คำนวณ \(\delta\) ของตัวเองจากแค่ \(\delta\) ของ node ที่มันเชื่อมโดยตรงใน layer ถัดไป ไม่ต้องรู้ว่าเครือข่ายทั้งอันมีกี่ node — จึงมีรูปสูตรเดียวกันไม่ว่า hidden จะมี 2, 10 หรือ 100 node.
เปลี่ยนแล้วเกิดอะไร
hidden 100 node แทน 10: สูตร \(\delta_j^{(1)}=\theta_{1j}^{[2]}\delta_1^{(2)}g'(z_j^{[1]})\) ไม่เปลี่ยนเลย สิ่งที่เปลี่ยนคือ "จำนวนครั้ง" ที่รันสูตร (100 ครั้ง) และขนาดเมทริกซ์ (\(\theta^{[1]}\): \(100\times3\), \(\theta^{[2]}\): \(1\times101\) ⇒ พารามิเตอร์ \(300+101 = 401\) ตัว).
เชื่อมกับ
เหตุผลที่ backprop สเกลไปโมเดลพารามิเตอร์พันล้านตัวได้ (LLM ใน timeline ของ Lesson 1) — ถ้าต้องมีสูตรพิเศษต่อขนาด จะเขียนเป็นโค้ดทั่วไปไม่ได้เลย.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 18Binary Classification Exercise
เครือข่ายใน exercise หน้า 47–48 (input 2, hidden 10, output 1) ต้องคำนวณ δ ของ hidden layer กี่ค่า และ gradient ของ θ⁽²⁾ กี่ค่า?


ชัยชนะของบทเรียนนี้
คุณควรอธิบายได้ว่า cost function วัดอะไรและทำไม regression กับ classification ใช้คนละสูตร, บอกได้ว่า nonconvex/local optima คืออะไรและร้ายแรงแค่ไหนในทางปฏิบัติ, พิสูจน์สูตร \(\delta^{[L]}=a^{[L]}-y\) และ \(\delta^{(l-1)}=(\theta^{[l]\top}\delta^{(l)})\odot g'(z^{[l-1]})\) ได้ด้วย chain rule เอง พร้อมบอกได้ว่าแต่ละตัวคูณในโซ่แทนอะไร, รันตัวอย่างเต็ม 2 layer 2 examples ได้มือ (forward → \(\delta\) → \(\Delta\) → \(D\) → update \(\theta\) พร้อมตรวจว่า cost ลด), นับมิติพารามิเตอร์ด้วยกฎ \(b\times(a+1)\), อธิบายได้ว่าทำไมห้าม initialize เป็นศูนย์ (redundant hidden units) และอ่านโค้ด numpy ของ initialization/unrolling ออก, พิสูจน์ \(\sigma'=\sigma(1-\sigma)\) และ \(\tanh' = 1-\tanh^2\), เทียบ activation ทั้งสี่ตามตารางหน้า 32 ได้ครบทุกช่อง, อธิบายได้ว่าทำไม ReLU เป็น state of the art และทำไม activation เชิงเส้นใช้ไม่ได้, เลือก activation ที่ output layer ตามชนิดงานและคำนวณ softmax ด้วยมือได้, แบ่งข้อมูล 60-20-20 / 70-15-15 และอธิบาย k-fold ได้, วินิจฉัย bias/variance แล้วเลือกยาถูกโรค, และเขียนสูตร cost + L2 regularization พร้อม gradient ที่แยก \(j=0\) ออกจาก \(j\ge1\) ได้ — Lesson 4 จะขยายทั้งหมดนี้จาก 2 layer เป็น \(L\) layer พร้อม optimizer ที่ฉลาดกว่า gradient descent ธรรมดา.

ภาคผนวก: Slide ทั้งหมดใน Lecture3.pdf (49 หน้า) — เช็คว่าอ่านครบ

หมายเหตุ: เนื้อหาทั้ง 49 หน้านี้เหมือนกับ Lecture2.pdf หน้า 50-98 เป๊ะทุกตัวอักษร (ดู Lesson 2 หมายเหตุต้นบท) ภาคผนวกนี้จึงครอบคลุมทั้ง Lecture2.pdf หน้า 50-98 ไปในตัว.

หน้าเนื้อหาสถานะ
1–2Cost Function (regression / classification) · Parameter Learning, gradient descent, nonconvex – local optima✓ หัวข้อ 0 (มีรูปทั้งสองหน้า, สูตรครบ, ตัวอย่างตัวเลข)
3–5Backpropagation เกริ่นนำ + Chain Rule และโจทย์ฝึก 2 ข้อ (e^(x³), (2x−5)¹⁰)✓ หัวข้อ 1 (คำศัพท์ที่ทำสีครบ, เฉลยโจทย์ทั้งสองข้อพร้อมตรวจตัวเลข)
6Apply Chain Rule to Backpropagation — ∂J/∂θ[2], ∂J/∂θ[1], 2 consecutive steps✓ หัวข้อ 2 (มีรูป, ไล่ทอดโซ่ทีละทอด)
7Forward Computation (1 example) — z=Σθx, a=g(z), bias x₀ และ a₀⁽¹⁾✓ หัวข้อ 2.1 (มีรูป, อธิบายระบบ index)
8Backward Computation — นิยาม δ, L, สูตร δ⁽¹⁾ จาก δ⁽²⁾✓ หัวข้อ 2.2 (มีรูป, แยกความหมายของ 3 ตัวคูณ)
9Derive Backpropagation (Small NN) — logistic regression เป็นกรณีเล็กสุด✓ หัวข้อ 2.3 (มีรูป, เทียบสูตรกับกฎ backprop)
10Mathematical Proof — พิสูจน์ δ ด้วย Chain Rule เต็มขั้น✓ หัวข้อ 2.4 (มีรูป, พิสูจน์ครบ 3 ชิ้นทีละบรรทัด)
11–16Example — forward/backward/accumulate ของ 2 ตัวอย่าง และ gradient descent 1 รอบ (α=0.1)✓ หัวข้อ 3 (มีรูปครบทั้ง 6 หน้า, กรอกตัวเลขที่สไลด์เว้นไว้ทุกช่อง ตรวจด้วย numpy)
17–18Backpropagation Algorithm — forward, δ⁽ᴸ⁾, backward, Δ, D, update + กล่อง Intuition✓ หัวข้อ 4 (มีรูปทั้งสองหน้า, เรียบเรียงเป็น 6 ขั้น)
19From Backpropagation to Automatic Differentiation — forward/reverse-mode AD + โค้ด PyTorch✓ หัวข้อ 4A.1 (มีรูป, โค้ดใน <pre> + ตารางอธิบายทีละบรรทัด)
20Dimension of Parameters — กฎ b × (a+1)✓ หัวข้อ 4A.2 (มีรูป, ฝึกใช้กฎ 3 เครือข่าย, ชี้ typo θ₁₄)
21Parameters Initialization — redundant hidden units, break symmetry, −ε < θ < ε + โค้ด numpy✓ หัวข้อ 4A.3 (มีรูป, ตารางสาธิต symmetry 5 รอบ, โค้ดใน <pre> + ตารางอธิบาย)
22Unrolling Parameters — np.concatenate / np.reshape กลับเป็น Theta1, Theta2✓ หัวข้อ 4A.4 (มีรูป, โค้ดใน <pre> + ตารางอธิบาย, ระบุ shape จริง)
23–24More on Activation Function (นิยาม, bias unit, weight) · Activation ที่ hidden layer และสูตร gradient✓ หัวข้อ 5 (มีรูปทั้งสองหน้า, prereq เรื่อง e^x)
25Sigmoid and its Derivative — พิสูจน์เต็ม σ'=σ(1−σ)✓ หัวข้อ 5A.1 (มีรูป, พิสูจน์ 4 ขั้น + ตารางค่า)
26Tanh and its Derivative — พิสูจน์เต็ม f'(x)=1−f(x)²✓ หัวข้อ 5A.2 (มีรูป, พิสูจน์ 5 ขั้นตามบรรทัดในสไลด์)
27Sigmoid vs Tanh — ช่วง output, zero-centered, ทั้งคู่ช้าเมื่อ x ใหญ่/เล็ก✓ หัวข้อ 5A.3 (มีรูป, อ่านค่ายอดอนุพันธ์ 0.25 vs 1.0)
28Gradient Descent + เหตุผลว่าทำไม activation ที่ไม่ zero-centered เป็นปัญหา (ภาพซิกแซก)✓ หัวข้อ 5A.4 (มีรูป, อธิบายด้วยเครื่องหมายของ gradient จริงจากหัวข้อ 3)
29Comparison between sigmoid and tanh — accuracy 98.666667 vs 99.833333✓ หัวข้อ 5A.5 (มีรูป, ผลลัพธ์ใน <pre> + ตารางอธิบาย)
30ReLU and its Derivative✓ หัวข้อ 5B.1 (มีรูป, ค่าตัวอย่าง, เทียบ 0.25¹⁰ กับ 1¹⁰)
31Leaky ReLU and its Derivative✓ หัวข้อ 5B.2 (มีรูป, เทียบค่าที่ x=−5)
32ตารางเปรียบเทียบ Sigmoid/Tanh/ReLU/Leaky ReLU ครบ 5 แถว✓ หัวข้อ 5B.3 (มีรูป + ถอดตารางทั้งตารางเป็น HTML)
33What Activation to use for Hidden Layers — ReLU state of the art, Softplus, ELU/SELU/GELU✓ หัวข้อ 5B.4 (มีรูป, ค่า Softplus เทียบ ReLU 3 จุด)
34Comparison — sigmoid/tanh/relu, accuracy 100.000000 ที่ 4000 รอบ✓ หัวข้อ 5B.5 (มีรูป, ผลลัพธ์ใน <pre> + ตารางอธิบาย)
35Why not Linear Activation Function?✓ หัวข้อ 5C (มีรูป, พิสูจน์ด้วยตัวเลข 3 layer)
36Activation Function at the Output Layer — regression / binary / multiclass✓ หัวข้อ 6 (มีรูป + ตารางสรุปพร้อมเครื่องหมาย ***)
37Multi-class Classification (Sigmoid at Output Node) — one-hot encoding + cost✓ หัวข้อ 6 (มีรูป, ตาราง one-hot ทั้ง 4 แถวของสไลด์)
38Multi-class Classification (Softmax at Output Node) — เหตุผลของ exponential + loss✓ หัวข้อ 6 (มีรูป, คำนวณ softmax ด้วยมือ 4 ขั้น + เหตุผล 2 ข้อ)
39–40Model Evaluation (60-20-20, 70-15-15, k-fold, data leakage) · Model Improvement (bias/variance)✓ หัวข้อ 6A (มีรูปทั้งสองหน้า, เดิน 5-fold ด้วยตัวเลข, ตารางยาแก้สองโรค)
41Regularization — keep all features, constrains or regularizes, เทอม L2✓ หัวข้อ 7 (มีรูป, อธิบายผลต่อรูปร่างเส้นแบ่ง)
42Cost Function with Regularization — L2/Ridge vs L1/Lasso + โจทย์นับพารามิเตอร์✓ หัวข้อ 7 (มีรูป, ตารางเทียบ, เฉลยโจทย์ = 41)
43Gradient Descent with L2 Regularization — สูตรแยก j=0 กับ j≥1✓ หัวข้อ 7 (มีรูป, คำนวณผลต่อ gradient จริง 1 ตัว)
44Best Practice to Model Improvement — เริ่มเล็กแล้วค่อยขยายจนกว่า validation loss จะอิ่มตัว✓ หัวข้อ 7A (มีรูป, อ่านกราฟทั้งสามสถานะด้วยค่าจริง)
45Parameters and Hyper Parameter — นิยามและรายการ hyperparameter✓ หัวข้อ 7A (มีรูป, เส้นแบ่งสองคำ)
46Hyperparameter Tuning Guideline — #layer 1-5, #hidden 5-100, พีระมิดที่เลิกใช้, learning rate✓ หัวข้อ 7A (มีรูป, ตารางข้อดีข้อเสีย, เหตุผลเชิงจำนวน hyperparameter)
47–48Binary Classification Exercise — Forward และ Backward Computation (hidden 10 node)✓ หัวข้อ 8 (มีรูปทั้งสองหน้า, เฉลยสูตรครบทุกขั้น, ชี้ typo θ₁₃⁽²⁾)
49References — รายชื่อหนังสือ/คอร์สอ้างอิง (Chollet, Géron, Andrew Ng, Jeff Heaton)etc — หน้าบรรณานุกรมล้วน ไม่มีเนื้อหาวิชา

สงสัยตรงไหน ถามได้เลยในแชท — ผมเป็นผู้สอนของคุณ ถามซ้ำได้ ถามลึกได้ ไม่ต้องเกรงใจ.