Lecture2.pdf (หน้า 1-49) · 2603520 Deep Learning

Neural Network Basics: จาก Node เดียวสู่โครงข่าย

บทนี้ตอบคำถามว่า "ทำไมต้องมี Neural Network ทั้งที่มี Logistic Regression แล้ว" จากนั้นค่อย ๆ สร้างความเข้าใจตามลำดับสไลด์ของอาจารย์: นิวรอนจริงในสมอง → นิวรอนเทียม → ประวัติ 3 ยุค → สัญกรณ์ (\(\theta\), layer, node) → logic gate จาก neuron เดียว → พีชคณิตเชิงเส้น (vector/matrix) แบบเริ่มจากศูนย์ → การเขียนสมการให้เป็นเมทริกซ์ (vectorization) พร้อมโค้ด numpy ของสไลด์ทุกบล็อก → จบด้วยการคำนวณ Forward Computation ด้วยมือทั้งโครงข่าย.

หมายเหตุเรื่องสไลด์
Lecture2.pdf หน้า 50–98 คือสไลด์เดียวกับ Lecture3.pdf ทั้ง 49 หน้า (อาจารย์เปิด deck เดิมซ้ำเป็นการทวน) บทนี้จึงครอบคลุมหน้า 1–49 เท่านั้น ส่วน Cost Function / Backpropagation / Activation อยู่ใน Lesson 3 (ไม่ซ้ำเนื้อหาสองที่). เนื้อหาพีชคณิตเชิงเส้น (หน้า 20–37) กินพื้นที่ครึ่งหนึ่งของ deck นี้ — อาจารย์ตั้งใจปูพื้นให้ก่อนเข้าสมการของ NN ดังนั้นบทเรียนนี้จึงสอนมันเต็ม ๆ ไม่ข้าม.
อ่านเพิ่มก่อนเริ่ม (แนะนำ)
3Blue1Brown — "But what is a neural network?" วิดีโอ 19 นาทีที่อธิบาย node/layer/weight ด้วยภาพเคลื่อนไหว ตรงกับหัวข้อ 1–3 ของบทนี้เป๊ะ.

1. ทำไมต้อง Neural Network: ปัญหาของ Polynomial Feature

ใน Lesson 1 เราทำ decision boundary ที่ไม่เป็นเส้นตรงด้วยการสร้าง feature เพิ่มด้วยมือ เช่น \(x_1^2,\ x_1x_2\) แล้วโยนเข้า logistic regression (จำวงกลมรัศมี 2 ได้ไหม). วิธีนี้ใช้ได้สบายกับ feature 2–3 ตัว แต่พอ feature ตั้งต้นเยอะขึ้น จำนวนเทอมที่ต้องสร้างจะระเบิดเร็วมากจนทำไม่ไหว — นี่คือปัญหาที่อาจารย์ใช้เปิดบท.

Spiral dataset with two interleaved classes requiring a non-linear decision boundary, with the polynomial degree-2 expansion formula shown, and a calculation showing that with 100 input features, all degree-2 polynomial terms explode to 5,150 features
Slide: Complex Non-linear Tasks — polynomial expansion ระเบิดเป็น 5,150 features (Lecture2.pdf, p.2)

ข้อมูล spiral ในสไลด์มีจุดแดงกับจุดน้ำเงินพันกันเป็นเกลียว — เส้นตรงเส้นเดียวแยกไม่ได้แน่นอน อาจารย์จึงเขียนสมมติฐานแบบโพลิโนเมียลให้ดูว่าต้องใช้เทอมอะไรบ้าง: \(g(\theta_0+\theta_1x_1+\theta_2x_2+\theta_3x_1x_2+\theta_4x_1^2+\dots+\theta_9x_2^3)\) — แค่ 2 feature กับดีกรี 3 ก็มีถึง 9 เทอมแล้ว. จากนั้นคำถามสำคัญคือ "ถ้ามี \(x_1,x_2,\dots,x_{100}\) ล่ะ" คำตอบบนสไลด์คือ 5,150 features สำหรับดีกรี 2 เท่านั้น. ข้อสรุปที่อาจารย์ทำสีไว้คือ Explicit polynomial feature expansion becomes impractical as the number of input features and polynomial degree increase — แปลว่า "การแจกแจงเทอมโพลิโนเมียลออกมาตรง ๆ ใช้การไม่ได้จริงเมื่อจำนวน feature และดีกรีเพิ่มขึ้น" คำว่า explicit สำคัญ: ไม่ได้บอกว่า non-linear ทำไม่ได้ แต่บอกว่าการเขียนเทอมเองทีละตัวต่างหากที่พัง.

คำนวณ: polynomial ดีกรี 2 จาก \(n\) feature มีกี่เทอม (ที่มาของ 5,150 ในสไลด์)
ตัวอย่างสไลด์: \(n = 100\) feature \(x_1,\dots,x_{100}\); นับทุกเทอมที่ดีกรี 1 และ 2 (ไม่นับค่าคงที่ \(\theta_0\))
  1. ขั้นที่ 1 — เทอมดีกรี 1 (ตัวเดี่ยว) \(x_i\)

    มีตัวแปรกี่ตัวก็ได้เทอมเท่านั้น

    $$n = 100$$
  2. ขั้นที่ 2 — เทอมกำลังสองของตัวเอง \(x_i^2\)

    ตัวแปรแต่ละตัวยกกำลังสองได้ 1 เทอม

    $$n = 100$$
  3. ขั้นที่ 3 — เทอมไขว้ \(x_i x_j\) เมื่อ \(i<j\)

    คือ "เลือกตัวแปร 2 ตัวจาก 100 ตัว" = จำนวนคู่ที่ไม่สนลำดับ (เพราะ \(x_1x_2\) กับ \(x_2x_1\) คือเทอมเดียวกัน)

    $$\binom{100}{2} = \frac{100 \times 99}{2} = 4950$$
  4. ขั้นที่ 4 — รวมทั้งหมด
    $$100 + 100 + 4950 = 5150$$

สูตรทั่วไป: \(\;2n + \dfrac{n(n-1)}{2}\;\) และย้ำว่านี่คือดีกรี 2 เท่านั้น — เทอมไขว้ \(\binom{n}{2}\) โตแบบกำลังสองตาม \(n\) ถ้าขึ้นดีกรี 3 จะโตเป็นกำลังสาม.

Computer vision task slide: a 28x28 pixel grayscale face image with pixel values in range 0-255, a colour RGB version with three stacked channel grids, and a face-recognition neural network with an input layer, several hidden layers and three output nodes named Lee, Chris, Joe
Slide: Computer Vision Tasks — นับ feature ของภาพ 28×28 (Lecture2.pdf, p.3)

อาจารย์ถามต่อด้วยตัวเลขจริงของงาน computer vision: ภาพฝึกขนาด 28×28 พิกเซล แต่ละพิกเซลเก็บค่าความสว่างในช่วง [0–255] และ "1 พิกเซล = 1 feature" ดังนั้นภาพขาวดำ 1 ภาพให้ \(28\times28 = 784\) features; ถ้าเป็นภาพสี RGB จะมี 3 ค่าต่อพิกเซล (แดง/เขียว/น้ำเงิน) จึงได้ \(784\times3 = 2{,}352\) features. ทีนี้ลองเอา 2,352 ไปเข้าสูตรเมื่อกี้: \(2(2352)+\binom{2352}{2} = 4704 + 2{,}764{,}776 = 2{,}769{,}480\) เทอม — เกือบ 2.8 ล้านพารามิเตอร์เฉพาะดีกรี 2 ของภาพเล็ก ๆ ภาพเดียว. โครงข่ายทางขวาของสไลด์แสดงทางออก: ป้อนพิกเซลดิบเข้า input layer แล้วให้ hidden layers เรียน feature เอง (ขอบ → ชิ้นส่วนใบหน้า → ตัวบุคคล) ก่อนออกที่ node ชื่อ Lee / Chris / Joe — เราไม่ต้องบอกเครื่องเลยว่าให้คูณพิกเซลไหนกับพิกเซลไหน.

อ่านเป็นภาษาคน: "ยิ่ง feature เยอะ การสร้างเทอมไขว้เองยิ่งเป็นไปไม่ได้ ⇒ ให้โมเดลสร้าง feature ที่ไม่เชิงเส้นเองดีกว่า" — และโมเดลที่ทำแบบนั้นคือ neural network

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
จำนวนเทอมดีกรี ≤ 2 คือ \(2n + n(n-1)/2\) ซึ่งโตแบบกำลังสองตาม \(n\) การแจกแจงมือทุกเทอมจึงพังเร็ว. NN แก้โดยให้แต่ละ hidden node เรียนรู้ "ผลรวมเชิงเส้น 1 ชุด + nonlinearity" เอง แทนการแจกแจงทุก monomial ล่วงหน้า.
เปลี่ยนแล้วเกิดอะไร
ลอง \(n=50\) (ครึ่งหนึ่งของ 100): \(2(50) + \frac{50\cdot49}{2} = 100 + 1225 = 1{,}325\) เทียบกับ 5,150 — จำนวนเทอมไม่ได้ลดครึ่งเดียวแต่ลดเกือบ 4 เท่า (\(5150/1325 \approx 3.9\)) เพราะเทอมไขว้ครองสัดส่วนใหญ่และโตแบบกำลังสอง.
เชื่อมกับ
พารามิเตอร์ที่โตเร็วกว่าข้อมูลคือต้นตอของ overfitting (Lesson 1 §10–11) และเป็นเหตุผลเดียวกับที่ Lesson 4 เตือนว่าเครือข่ายลึกเสี่ยง overfit สูง.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 1Why ANN
ทำไม Explicit Polynomial Feature Expansion ถึง "impractical" เมื่อจำนวน input feature มาก (เช่น 100 features, degree 2)?

1A. Neural Network คืออะไร: จากสมองจริงสู่ "universal model"

ก่อนจะมีสูตร อาจารย์ปูเรื่องเล่าก่อนว่า ANN เกิดจากการเลียนแบบสมอง แล้วค่อยกลายเป็นเครื่องมือคณิตศาสตร์. สี่หน้าถัดไปคือเรื่องเล่านั้น และเป็นที่มาของคำศัพท์ที่จะใช้ทั้งเทอม.

Artificial Neural Networks slide: a drawing of a biological neuron with signal in through dendrites, cell body, axon and signal out at the axon terminal, placed beside an artificial node receiving x1 and x2 and emitting h(x)
Slide: Artificial Neural Networks (ANNs) — นิวรอนชีวภาพ vs node เทียม (Lecture2.pdf, p.4)

นิยามที่อาจารย์ให้คือ ANN เป็น "Mathematical model for computation which is based on a large collection of neural units (connectionist) inspired by biological brain" — อ่านทีละคำ: มันคือแบบจำลองทางคณิตศาสตร์สำหรับการคำนวณ ที่ประกอบจากหน่วยย่อยจำนวนมาก (คำว่า connectionist แปลว่า "ความฉลาดอยู่ที่การเชื่อมต่อระหว่างหน่วย ไม่ได้อยู่ที่หน่วยเดียว") และได้แรงบันดาลใจจากสมองจริง (inspired by ≠ จำลองสมองจริง — ข้อสอบชอบดักตรงนี้). เทียบภาพซ้าย-ขวาให้ตรงกันได้ทันที: dendrite ที่รับ "Signal In" ↔ ลูกศร \(x_1, x_2\) ที่เข้า node; cell body ที่รวมสัญญาณ ↔ การบวกถ่วงน้ำหนักในวงกลม; axon ที่ส่ง "Signal Out" ↔ ลูกศรออก \(h_\theta(x)\). อาจารย์เสริมว่าโมเดลนี้ถูกมองเป็น universal models ที่แก้ปัญหาได้ทุกประเภท โดยยกสองงานที่มันเด่นเป็นพิเศษ: งาน classification ที่ไม่เชิงเส้นซับซ้อน และงานที่มี input feature จำนวนมหาศาล (เช่น computer vision ที่เพิ่งนับได้ 2,352 features จากภาพเล็ก ๆ ในหน้า 3).

From Biological to Artificial Neural Network: a cross-section drawing of human cortex marked Layer 1 through Layer 6 next to a multi-layer artificial network where x1 and x2 feed successive rows of nodes ending in one output h(x)
Slide: From Biological to Artificial Neural Network — เปลือกสมอง 6 ชั้น (Lecture2.pdf, p.5)

ประโยคที่ทำสีไว้คือ Neurons in the human cortex create layers, crucial for intelligence. ภาพตัดขวางเปลือกสมอง (cortex) ถูกกำกับเป็น Layer 1 ถึง Layer 6 — อาจารย์ชี้ว่าเปลือกสมองมนุษย์มี 6 ชั้น และแต่ละชั้น "ประมวลผล input ให้กลายเป็นแนวคิด (concepts)" ทีละขั้น. นี่คือเหตุผลว่าทำไมโครงข่ายเทียมถึงถูกจัดเป็น "ชั้น" ตามกัน: ชั้นแรกรับ \(x_1,x_2\) ดิบ ชั้นถัด ๆ ไปรับผลลัพธ์ของชั้นก่อนหน้า ไม่ใช่รับ input ดิบอีก จนถึง node สุดท้ายที่ให้ \(h_\theta(x)\). คำว่า layer ที่จะเจอทั้งเทอมเกิดตรงนี้ และคำว่า "deep" ใน deep learning ก็คือ "มี layer หลายชั้น" นั่นเอง.

อย่าจำผิด
สมองมี 6 ชั้นไม่ได้แปลว่าโครงข่ายต้องมี 6 ชั้น — อาจารย์ยกมาเพื่ออธิบายแรงบันดาลใจของแนวคิด "ชั้น" เท่านั้น จำนวนชั้นของ NN เป็นสิ่งที่เราเลือกเอง (Lesson 4 จะเรียกว่า hyperparameter).
Neural Network Intuition slide defining dense (fully connected) layers, with a shallow neural network of n inputs feeding three hidden nodes and one output labelled one hidden layer, and a housing price prediction network with six inputs x1 to x6 fully connected to three hidden nodes then one output
Slide: Neural Network Intuition — dense layer และตัวอย่างทำนายราคาบ้าน (Lecture2.pdf, p.6)

หน้านี้คือหัวใจของบท: ในโครงข่ายที่ประกอบด้วย dense layers (หรืออีกชื่อว่า fully connected layers — ทุก node ของชั้นก่อนหน้าต่อเข้าทุก node ของชั้นถัดไป ไม่มีเส้นไหนขาด) แต่ละ node จะสร้าง output จาก inputs ของชั้นก่อนหน้า คูณกับ weight ของมัน แล้วส่งผ่าน activation function. สามคำนี้คือสามส่วนประกอบของ node ทุกตัวในวิชานี้ — จำลำดับให้แม่น: รับ input → คูณ weight แล้วบวกกัน → ผ่าน activation. ตัวอย่าง Housing Price Prediction ทางขวานับได้จริง: input 6 ตัว (\(x_1\) ถึง \(x_6\) เช่น ขนาดบ้าน จำนวนห้องนอน ทำเล ฯลฯ) ต่อแบบ fully connected เข้า hidden 3 node ⇒ เส้นเชื่อม \(6\times3 = 18\) เส้น บวก bias อีก 3 ตัว = 21 พารามิเตอร์ในชั้นที่ 1; แล้ว hidden 3 node ต่อเข้า output 1 node ⇒ \(3+1 = 4\) พารามิเตอร์ รวมทั้งโครงข่าย 25 ตัว ซึ่งน้อยกว่าการแตกโพลิโนเมียลมหาศาล. อาจารย์ยังกำกับไว้ว่าโครงข่ายที่มี #hidden layer = 1 เรียกว่า Shallow Neural Network และแปะลิงก์ Universal Approximation Theorem ไว้เป็นหลักฐานทางคณิตศาสตร์ว่าโครงข่ายตื้น ๆ แบบนี้ก็ประมาณฟังก์ชันต่อเนื่องได้กว้างมากแล้ว.

ต้องรู้ก่อน

"เชิงเส้น (linear)" กับ "ไม่เชิงเส้น (nonlinear)" ต่างกันยังไง และทำไม activation function ถึงจำเป็น

ฟังก์ชันเชิงเส้นคือฟังก์ชันหน้าตา \(f(x)=ax+b\) — วาดแล้วได้เส้นตรงเสมอ เช่น \(f(x)=2x+1\): ใส่ \(x=0\) ได้ 1, ใส่ \(x=1\) ได้ 3, ใส่ \(x=2\) ได้ 5 (เพิ่มทีละ 2 คงที่).

ทีนี้ลองต่อสองชั้นแบบไม่มี activation: ชั้นแรก \(a = 2x+1\) ชั้นสอง \(h = 3a-2\). แทนค่า: \(h = 3(2x+1)-2 = 6x+1\) — ยังเป็นเส้นตรงอยู่ดี! ตรวจด้วยตัวเลข \(x=2\): \(a = 5,\ h = 13\) และ \(6(2)+1 = 13\) ตรงกัน. นี่คือเหตุผลว่าต่อชั้นเชิงเส้นกี่ชั้นก็ยังได้เส้นตรงเส้นเดียว ไม่ได้อะไรเพิ่มเลย.

ถ้าใส่ฟังก์ชันโค้ง ๆ (nonlinear) คั่นระหว่างชั้น เช่น sigmoid \(g(z)=\frac{1}{1+e^{-z}}\) ผลลัพธ์จะไม่ยุบเป็นเส้นตรงอีก: \(h = 3\,g(2x+1)-2\) ที่ \(x=0\) ได้ \(3(0.731)-2 = 0.193\), ที่ \(x=1\) ได้ \(3(0.953)-2 = 0.858\), ที่ \(x=2\) ได้ \(3(0.993)-2 = 0.980\) — ส่วนต่างไม่คงที่ (0.665 แล้ว 0.122) นั่นคือ "โค้ง" จริง. ดังนั้น activation function ไม่ใช่ของประดับ แต่เป็นสิ่งเดียวที่ทำให้การซ้อนชั้นมีความหมาย.

Why can neural networks model complex patterns: an input space with spiral red and blue points, four hidden neurons each drawing one simple straight boundary, and a weighted combination at the output producing a smooth spiral decision region, annotated with the key idea that combining simple neurons represents very complex functions
Slide: Why Can Neural Networks Model Complex Patterns? (Lecture2.pdf, p.7)

หน้านี้ตอบคำถาม "ทำไมมันถึงเวิร์ก" ด้วย 5 ข้อ ซึ่งควรอ่านเป็นลำดับเหตุผลต่อกัน ไม่ใช่ 5 ข้อแยกกัน. (1) hidden neuron แต่ละตัวเรียน representation/pattern คนละแบบ จาก input เดียวกัน — ในภาพคือ Neuron 1 ถึง Neuron 4 ที่แต่ละตัวขีดเส้นแบ่งพื้นที่คนละมุมของ spiral เดียวกัน. (2) Nonlinear activation functions ทำให้นิวรอนสร้าง representation ที่ไม่เชิงเส้นได้ (ถ้าไม่มีมัน ทุกอย่างยุบเป็นเส้นตรงตามที่พิสูจน์ไปในกล่อง "ต้องรู้ก่อน"). (3) เอา hidden neuron หลาย ๆ ตัวมารวมกัน (weighted combination) จึงเกิด complex decision boundary — ในภาพคือพื้นที่แดง/น้ำเงินที่ม้วนเป็นเกลียวตามข้อมูลจริง. (4) ถ้ามี hidden unit เพียงพอ และ activation ไม่เชิงเส้นที่เหมาะสม โครงข่ายประมาณฟังก์ชันได้กว้างมาก (นี่คือใจความของ Universal Approximation Theorem ที่ลิงก์ไว้หน้า 6). (5) ถ้ามี layer เพียงพอ โครงข่ายจะเรียน hierarchical representations คือสร้าง feature ซับซ้อนจาก feature ง่าย ๆ ไล่ขึ้นทีละชั้น (ขอบ → ตา/จมูก → ใบหน้า) ซึ่งคือเหตุผลของคำว่า "deep". สังเกตคำเงื่อนไขที่อาจารย์ทำตัวหนา: sufficient (พอเพียง) และ appropriate (เหมาะสม) — ทฤษฎีไม่ได้รับประกันว่าโครงข่ายเล็ก ๆ หรือ activation อะไรก็ได้จะทำได้.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
ข้อ (4) กับ (5) ต่างกันตรง "กว้าง" กับ "ลึก": hidden unit เยอะในชั้นเดียวให้ความสามารถประมาณฟังก์ชัน, แต่หลายชั้นให้ความสามารถสร้างลำดับชั้นของ feature ซึ่งประหยัดพารามิเตอร์กว่ามากในงานจริงอย่างภาพ.
เปลี่ยนแล้วเกิดอะไร
ถอด activation ออกจากทุก hidden node ของโครงข่ายราคาบ้าน (6→3→1): ชั้นที่ 1 ให้ \(a = \Theta^{[1]}x\) ชั้นที่ 2 ให้ \(h = \theta^{[2]}a = (\theta^{[2]}\Theta^{[1]})x\) ซึ่งเท่ากับ linear regression ธรรมดาที่มีสัมประสิทธิ์ชุดเดียว — พารามิเตอร์ 25 ตัวถูกยุบเหลือกำลังอธิบายเท่ากับ 7 ตัว (6 weight + 1 bias) เปล่าประโยชน์ทันที.
เชื่อมกับ
เหตุผลนี้คือที่มาของหัวข้อ activation function ทั้งหมดใน Lesson 3 (sigmoid/tanh/ReLU) และปัญหา vanishing gradient ใน Lesson 5.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 2Dense Layer
ตามสไลด์ Neural Network Intuition แต่ละ node ใน dense layer (fully connected layer) สร้าง output ด้วยลำดับขั้นตอนใด?

2. ประวัติย่อของ ANN: จาก McCulloch-Pitts สู่ปัญหา XOR

ไอเดียหลัก: นักวิจัยพยายามสร้าง "นิวรอนเทียม" — หน่วยเล็ก ๆ ที่รับ input หลายตัว รวมแล้วตัดสินใจว่าจะ "ยิง (1)" หรือ "ไม่ยิง (0)". อาจารย์เล่าเป็น 3 ช่วงเวลา และแต่ละช่วงเพิ่มความสามารถทีละขั้น ซึ่งเป็นลำดับที่ข้อสอบชอบถามว่า "ใครทำอะไร ปีไหน แก้ปัญหาอะไรได้/ไม่ได้".

McCulloch and Pitts 1943 artificial neuron model diagrams showing four logical computations built from binary threshold neurons: C = A, C = A AND B, C = A OR B, and C = A AND NOT B
Slide: Logical Computation with Neurons (McCulloch & Pitts, 1943) (Lecture2.pdf, p.8)

1943 McCulloch–Pitts: อาจารย์เขียนว่าใช้ simplified model นี้ โครงข่ายนิวรอนเทียมสามารถคำนวณ logical proposition ใดก็ได้ที่เราต้องการ. คำว่า proposition (ประพจน์) คือประโยคที่มีค่าความจริงจริง/เท็จเท่านั้น เช่น "ฝนตก และ ถนนลื่น". นิยามของนิวรอนรุ่นนี้คือ Simple model ของ biological neuron ที่มีเงื่อนไขแค่ 3 ข้อ: input เป็นแบบ binary (เปิด/ปิด) หนึ่งตัวหรือมากกว่า, output เป็น binary หนึ่งตัว, และนิวรอนจะ activate เมื่อจำนวน input ที่ active มากกว่าเกณฑ์ที่กำหนด. ไล่ตามภาพสี่แบบที่สไลด์ยกมา: \(C = A\) คือนิวรอน C ที่ยิงเมื่อ A ยิง (ส่งต่อค่าเฉย ๆ); \(C = A \wedge B\) ต้องให้ทั้ง A และ B ยิงพร้อมกัน (เกณฑ์ = 2 input); \(C = A \vee B\) แค่ตัวใดตัวหนึ่งยิงก็พอ (เกณฑ์ = 1 input); และ \(C = A \wedge \neg B\) ใช้เส้นเชื่อมแบบ ยับยั้ง (inhibitory) จาก B ซึ่งบล็อกไม่ให้ C ยิงเมื่อ B ทำงาน. สังเกตว่ารุ่นนี้ ยังไม่มี weight เป็นตัวเลข — ปรับได้แค่ "เกณฑ์จำนวน input" เท่านั้น.

Rosenblatt 1957 Perceptron slide: a Threshold Logic Unit drawn with inputs x1 x2 x3, weights w1 w2 w3, a summation symbol, a step function block, and the output formula h(x) = step(x transpose w) with weighted sum z = x transpose w
Slide: Perceptron (Rosenblatt, 1957) — Threshold Logic Unit (TLU) เดี่ยว (Lecture2.pdf, p.9)

1957 Perceptron: ก้าวสำคัญคือหน่วยเดียวที่ชื่อ threshold logic unit (TLU) ใช้ทำ binary classification แบบเชิงเส้นง่าย ๆ ได้ อาจารย์เน้นหัวข้อย่อยว่าเป็น Binary Classification using TLU. รายละเอียดที่ต่างจากรุ่น 1943 มี 3 ข้อ: (ก) input เป็นค่าตัวเลขจริงได้แล้ว (จะ binary หรือ continuous ก็ได้) แต่ output ยังเป็น binary; (ข) เส้นเชื่อมแต่ละเส้นมี weight ของตัวเอง (\(w_1,w_2,w_3\) ในภาพ) — ปรับความสำคัญของ input ทีละตัวได้; (ค) TLU เอาผลรวมถ่วงน้ำหนัก \(z = \mathbf{x}^\top\mathbf{w}\) ไปผ่าน step function แล้วให้ผลเมื่อค่าเกิน threshold ตามสูตรบนสไลด์ \(h_w(\mathbf{x}) = \text{step}(\mathbf{x}^\top\mathbf{w})\):

$$z = \mathbf{x}^\top \mathbf{w} = w_1x_1 + w_2x_2 + w_3x_3,\qquad \text{step}(z)=\begin{cases}1 & z \ge 0\\ 0 & z<0\end{cases}$$

บรรทัดสรุปท้ายสไลด์คือข่าวร้ายที่ทำให้วงการหยุดชะงักไปสิบกว่าปี: Perceptron แก้ simple problems บางอย่างไม่ได้ เช่นปัญหา XOR ตามที่ Minsky และคณะแสดงไว้ในปี 1969 — คำว่า "simple" เป็นการประชด เพราะ XOR ดูง่ายมากสำหรับคน แต่ TLU ตัวเดียวทำไม่ได้จริง ๆ.

Multilayer Perceptron solving XOR: a plot of the four XOR points showing they are not separable by one straight line, beside a two layer network of threshold logic units whose four annotated connection weights are minus 1.5 and minus 0.5 from the lower bias unit, minus 1 from the left hidden unit to the output, and minus 0.5 from the upper bias unit
Slide: Multilayer Perceptron (MLP, Rosenblatt 1969) แก้ปัญหา XOR ได้ (Lecture2.pdf, p.10)

1969 MLP: คำตอบคือซ้อนชั้น. นิยามที่อาจารย์ทำสีทั้งประโยค: An MLP is composed of one input layer, one or more layers of TLUs, called hidden layers, and one final layer of TLUs called the output layer. — แปลว่า MLP = input layer 1 ชั้น + ชั้นของ TLU อีก "หนึ่งชั้นหรือมากกว่า" ที่เรียกว่า hidden layer + ชั้น TLU สุดท้าย 1 ชั้นที่เรียกว่า output layer. โครงข่ายในภาพใช้ weight เท่ากับ 1 ทุกเส้น ยกเว้น 4 เส้นที่กำกับตัวเลขไว้: \(-1.5\) และ \(-0.5\) จาก bias unit ล่างเข้าสู่ hidden สองตัว, \(-1\) จาก hidden ตัวซ้ายไปยัง output, และ \(-0.5\) จาก bias unit บนเข้าสู่ output. อีกบรรทัดที่มักถูกมองข้ามแต่สำคัญมากคือ "Loosely speaking we can call MLP even using not step function nowadays" — ทุกวันนี้เราเรียกโครงข่ายว่า MLP ได้แม้จะไม่ได้ใช้ step function แล้ว (เปลี่ยนไปใช้ sigmoid/ReLU) เพราะ step function มีอนุพันธ์เป็น 0 เกือบทุกที่ จึงเทรนด้วย gradient descent ไม่ได้ (เหตุผลเต็มอยู่ใน Lesson 3).

คำนวณ: MLP ในสไลด์ให้ผล XOR ครบทั้ง 4 กรณี
hidden ซ้าย \(A=\text{step}(x_1+x_2-1.5)\) (พฤติกรรมแบบ AND), hidden ขวา \(B=\text{step}(x_1+x_2-0.5)\) (พฤติกรรมแบบ OR), output \(=\text{step}(B - A - 0.5)\)
  1. ขั้นที่ 1 — \((x_1,x_2)=(0,0)\)
    $$A=\text{step}(-1.5)=0,\ B=\text{step}(-0.5)=0,\ \text{out}=\text{step}(0-0-0.5)=0$$
  2. ขั้นที่ 2 — \((0,1)\)
    $$A=\text{step}(1-1.5)=0,\ B=\text{step}(1-0.5)=1,\ \text{out}=\text{step}(1-0-0.5)=1$$
  3. ขั้นที่ 3 — \((1,0)\)

    สมมาตรกับกรณี \((0,1)\) ทุกประการ (สูตรใช้ผลบวก \(x_1+x_2\)) ⇒ out = 1

  4. ขั้นที่ 4 — \((1,1)\)
    $$A=\text{step}(2-1.5)=1,\ B=\text{step}(2-0.5)=1,\ \text{out}=\text{step}(1-1-0.5)=0$$

ผลลัพธ์ \([0,1,1,0]\) = XOR พอดี. กลไกคือ hidden ขวาตอบว่า "มีอย่างน้อยหนึ่งตัวเป็น 1 ไหม" ส่วน hidden ซ้ายตอบว่า "เป็น 1 ทั้งคู่ไหม" แล้ว output เอาอันแรกลบอันหลัง = "มีอย่างน้อยหนึ่งตัว แต่ไม่ใช่ทั้งคู่".

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
เกณฑ์จริงไม่ใช่ "XOR ยากเป็นพิเศษ" แต่คือ linear separability: TLU เดี่ยวตัดพื้นที่ด้วยเส้นตรง (ไฮเปอร์เพลน) เพียงเส้นเดียว. ถ้าจุดสองคลาสสลับมุมแบบกระดานหมากรุก ไม่มีเส้นเดียวแบ่งได้ ไม่ว่าจะปรับ weight อย่างไร — ต้องมี hidden layer ตัดพื้นที่หลายส่วนก่อนรวมผล.
เปลี่ยนแล้วเกิดอะไร
ลองโจทย์ "majority of 3" (output = 1 ถ้ามี input เป็น 1 อย่างน้อย 2 จาก 3): แยกได้ด้วยเส้นเดียว \(\text{step}(x_1+x_2+x_3-1.5)\) เพราะเรียงจุดตามผลบวกแล้วตัดที่ 1.5 ได้เลย ไม่มีการสลับมุม — TLU เดี่ยวจึงพอ ไม่ต้องมี hidden layer.
เชื่อมกับ
เกณฑ์เดียวกับ decision boundary ใน Lesson 1 (เส้นตรง vs วงกลม): "แยกด้วยเส้นตรงได้ไหม" คือคำถามที่ตัดสินว่าต้องเพิ่ม layer/feature ตลอดวิชา — และหัวข้อ 7 ของบทนี้จะสร้าง XNOR ด้วยหลักการเดียวกันแต่ใช้ sigmoid แทน step.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 3XOR Problem
เหตุผลเชิงคณิตศาสตร์ที่ Perceptron (TLU เดี่ยวตัวเดียว) แก้ปัญหา XOR classification ไม่ได้คืออะไร?

3. โครงสร้างและสัญกรณ์ของ Neural Network

ก่อนคำนวณอะไรได้ ต้องอ่านสัญลักษณ์ออกก่อน. สามหน้าถัดไปคือ "พจนานุกรม" ของวิชานี้ ถ้าตรงนี้ไม่แม่น ทุกสูตรใน Lesson 3–6 จะอ่านไม่ออก.

Neural Network Structure slide listing the roles of the input layer, hidden layer and output layer, with a block diagram Input Layer to Hidden Layers labelled black box to Output Layer, plus a one-node small neural network and a shallow neural network with three hidden nodes
Slide: Neural Network Structure — หน้าที่ของแต่ละ layer (Lecture2.pdf, p.11)

อาจารย์แบ่งหน้าที่ของ 3 ชั้นไว้ชัดเจน และนี่คือคำนิยามที่ต้องท่องได้: Input Layer ทำหน้าที่รับข้อมูลเข้า (receives the input data) — ไม่คำนวณอะไรเลย เป็นแค่ที่วางค่า \(x_1, x_2, \dots\); Hidden Layer ทำหน้าที่คำนวณเพื่อเรียน useful features และ patterns (representations) จากข้อมูล — คำว่า hidden มาจากการที่เราไม่ได้กำหนดว่ามันต้องเรียนอะไร จึงถูกเขียนกำกับในแผนภาพว่าเป็น black box; Output Layer ทำหน้าที่รวม representation ที่เรียนมาแล้วให้เป็นคำทำนายสุดท้าย. สองโครงข่ายตัวอย่างข้างล่างคือกรณีสุดขั้วสองแบบ: "Small Neural Network" ที่มี node เดียวรับ \(x_1,x_2\) แล้วออก \(h_\theta(x)\) เลย (ไม่มี hidden layer — ก็คือ regression ธรรมดา) กับ "Shallow Neural Network" ที่แทรก hidden 3 node คั่นก่อนถึง output.

Neural Network Notation slide: a fully connected network with inputs x1 x2, hidden nodes a1[1] a2[1] a3[1] in Layer 1 and output node a1[2] in Layer 2 producing h(x), plus a magnified box showing that the bracketed superscript means the layer and the subscript means the node in that layer
Slide: Neural Network Notation — layer เป็น superscript [l], node เป็น subscript (Lecture2.pdf, p.12)

สัญกรณ์กลางของวิชาคือ \(a_{\text{node}}^{[\text{layer}]}\). ในโครงข่ายตัวอย่าง hidden layer ถูกเรียกว่า Layer 1 มี 3 node ชื่อ \(a_1^{[1]}, a_2^{[1]}, a_3^{[1]}\) และ output layer คือ Layer 2 มี node เดียวชื่อ \(a_1^{[2]}\) ซึ่งค่าของมันก็คือ \(h_\theta(x)\) นั่นเอง. จำสองข้อนี้ให้ขึ้นใจ: ตัวเลขใน วงเล็บเหลี่ยม \([\,]\) คือเลขชั้น ไม่ใช่เลขยกกำลัง (\(a_1^{[2]}\) ไม่ได้แปลว่า \(a_1\) กำลังสอง) และ input layer ไม่ถูกนับเป็น layer ที่มีพารามิเตอร์ จึงเรียกโครงข่ายนี้ว่า "2 Layers NN" ทั้งที่วาดเห็น 3 คอลัมน์.

สัญลักษณ์อ่านว่าตัวอย่างจากสไลด์
\(a_j^{[l]}\)activation (ค่าที่ออกจาก node) ของ node ที่ \(j\) ใน layer ที่ \(l\)\(a_2^{[1]}\) = node ตัวที่ 2 ของ layer 1
\(\theta_{ij}^{[l]}\)weight ของเส้นที่วิ่งเข้า node \(i\) ใน layer \(l\) จาก node \(j\) ใน layer \(l-1\)\(\theta_{11}^{[1]}\): เข้า node 1 ของ layer 1 จาก \(x_1\)
\(x_0 = a_0^{[l]}\)bias unit ค่าคงที่ \(+1\) เสมอ (ทำหน้าที่เดียวกับ \(\theta_0\) ใน Lesson 1)\(\theta_{10}^{[1]}\) = weight ของ bias เข้า node 1

ลำดับ subscript คือ "ปลายทางก่อน ต้นทางทีหลัง" (\(i\) = ปลายทาง, \(j\) = ต้นทาง) — จุดที่คนสับสนบ่อยที่สุดและออกสอบบ่อยที่สุด

Neural Network Notation 2 slide: the logistic hypothesis h = g(z) = 1/(1+e^-z) highlighted in yellow with z = sum of theta_i x_i, a node showing the bias unit x0 fixed at +1 with weights theta_10, theta_11, theta_12 entering node a1[1], a magnified node splitting into the weighted sum z and the activation function g, and a legend for the weight symbol theta with destination layer, source node and line labels
Slide: Bias Unit x₀, Activation Function g และ Weight (Lecture2.pdf, p.13)

อาจารย์บอกชัดว่าใช้ hypothesis function ของ logistic regression as an illustration — คือยกมาเป็นตัวอย่างประกอบเท่านั้น ไม่ได้แปลว่า node ต้องเป็น sigmoid เสมอ (Lesson 3 จะเปลี่ยนไปใช้ ReLU ฯลฯ). กรอบเหลืองบนสไลด์คือสูตรที่คุ้นจาก Lesson 1 พอดี: \(h = g(z) = \frac{1}{1+e^{-z}}\) โดย \(z=\sum_{i=0}^{n}\theta_i x_i\). สิ่งใหม่ที่หน้านี้เพิ่มมี 3 คำ: Bias Unit 𝑥0 ซึ่งอาจารย์วงเล็บภาษาไทยไว้ว่า "เป็นค่าตัวปรับ มักกำหนดค่าเท่ากับ +1" (จึงทำให้ \(\theta_0 x_0 = \theta_0\) กลายเป็นค่าคงที่ที่เลื่อนเส้นแบ่งได้); Activation Function g คือฟังก์ชันที่ครอบ \(z\) อีกที; และ Weight ซึ่งอาจารย์อธิบายวิธีอ่านสัญลักษณ์ \(\theta\) แบบละเอียด: เลขในวงเล็บเหลี่ยมบอก Destination Layer (ชั้นปลายทาง), subscript ตัวหน้าบอก Node in a Layer (node ปลายทาง) และ subscript ตัวหลังบอก Node in a Source Layer (node ต้นทาง). ดูตัวอย่างจริงในภาพ: \(\theta_{12}^{[1]}\) คือเส้นจาก \(x_2\) เข้า node ที่ 1 ของ layer 1.

สูตรสองขั้นที่จะใช้ตลอดวิชา เขียนรวมได้เป็น:

$$z_j^{[l]} = \sum_{i=0}^{n} \theta_{ji}^{[l]}\, a_i^{[l-1]}\quad(\text{ผลรวมถ่วงน้ำหนัก, เริ่มนับที่ } i=0 \text{ คือ bias}),\qquad a_j^{[l]} = g\!\left(z_j^{[l]}\right)$$

สังเกตว่าดัชนีเริ่มที่ \(i=0\) ไม่ใช่ \(i=1\) เพราะรวม bias unit \(a_0=1\) ไว้ด้วย ดังนั้น จำนวนพารามิเตอร์ที่เข้า 1 node = (จำนวน node ต้นทาง) + 1 เสมอ.

คำนวณ: ขนาดของเมทริกซ์ \(\theta^{[l]}\) และจำนวนพารามิเตอร์
layer ก่อนหน้ามี 4 node (ไม่นับ bias), layer ปัจจุบันมี 2 node
  1. ขั้นที่ 1 — แถวของ \(\theta\) = จำนวน node ปลายทาง

    layer ปัจจุบันมี 2 node ⇒ 2 แถว (แถวละ 1 node)

  2. ขั้นที่ 2 — คอลัมน์ = จำนวน node ต้นทาง + 1 (เผื่อ bias)

    \(4 + 1 = 5\) คอลัมน์

  3. ขั้นที่ 3 — เขียนขนาดและนับพารามิเตอร์
    $$\theta^{[l]}\in\mathbb{R}^{2\times5},\qquad \text{จำนวนพารามิเตอร์} = 2\times5 = 10$$

กฎจำง่าย: \(\theta^{[l]}\) มีขนาด (จำนวน node ปลายทาง) × (จำนวน node ต้นทาง + 1) — เพราะเวกเตอร์ \(a^{[l-1]}\) ที่เอาไปคูณมี 5 สมาชิก (รวม bias) การคูณ \((2\times5)(5\times1)\) จึงได้ผลลัพธ์ \(2\times1\) พอดีหนึ่งค่าต่อหนึ่ง node.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
ลำดับ "ปลายทาง, ต้นทาง" ไม่ใช่แค่ธรรมเนียม: มันทำให้สูตร \(z = \theta\, a\) ตรงกับกฎการคูณ matrix–vector พอดี — แถวของ \(\theta\) คือ index ปลายทาง \(i\), คอลัมน์คือ index ต้นทาง \(j\) จำนวนคอลัมน์จึงเท่ากับจำนวนสมาชิกของ \(a\). ถ้าสลับ \(i,j\) มิติจะคูณกันไม่ได้.
เปลี่ยนแล้วเกิดอะไร
ถ้าจำสลับจะเขียน \(\theta\) เป็น \(5\times2\) แทน \(2\times5\) ซึ่งคูณกับ \(a\) (5 สมาชิก) ไม่ได้ ⇒ numpy โยน error เรื่อง shape ทันที (กฎมิติเต็ม ๆ อยู่ในหัวข้อ 5B).
เชื่อมกับ
กฎอ่าน index ของ matrix (แถวก่อน คอลัมน์หลัง) ในหัวข้อ 5B และ "dimension of parameters" ที่ Lesson 3 ทำให้เป็นทางการตอนสอน backpropagation.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 4Notation
ในสัญกรณ์ θ_ij^[l] ของอาจารย์ ตัวเลข i และ j หมายถึงอะไรตามลำดับ?

3A. Small Neural Network: Linear / Logistic Regression คือ NN ที่มี node เดียว

หน้านี้สั้นแต่เป็นสะพานเชื่อม Lesson 1 กับ Lesson 2 ที่สำคัญมาก — และเป็นคำตอบของคำถาม "แล้วที่เรียนมาทั้งเทอมที่แล้วไปไหน".

Small Neural Network slide: the same one-node network drawn twice, the upper one labelled Linear Regression with a straight-line graph under the node, the lower one labelled Logistic Regression with an S-shaped sigmoid curve under the node, both taking x1 and x2 and producing h(x)
Slide: Small Neural Network — linear และ logistic regression ในรูปของ node เดียว (Lecture2.pdf, p.14)

โครงข่ายสองอันบนหน้านี้หน้าตาเหมือนกันเป๊ะ: รับ \(x_1, x_2\) เข้า node เดียว แล้วออกเป็น \(h_\theta(x)\). สิ่งเดียวที่ต่างคือกราฟเล็ก ๆ ใต้ node ซึ่งบอกว่า node นั้นใช้ activation อะไร — อันบนเป็นเส้นตรง (linear regression: \(h_\theta(x)=\theta_0+\theta_1x_1+\theta_2x_2\) คือส่งค่า \(z\) ออกไปตรง ๆ) อันล่างเป็นเส้นโค้งรูปตัว S (logistic regression: \(h_\theta(x)=g(z)=\frac{1}{1+e^{-z}}\) บีบค่าให้อยู่ระหว่าง 0 ถึง 1). บทเรียนที่ต้องเก็บกลับบ้านคือ linear regression และ logistic regression ก็คือ neural network ที่มี node เดียวและไม่มี hidden layer — เราไม่ได้เรียนของใหม่ทั้งหมด แต่กำลังขยายของเดิมให้มีหลาย node หลายชั้น. ลองตัวเลขจริงเทียบให้เห็นภาพ: ให้ \(\theta=(-3,\,2,\,1)\) และ \(x=(2,1)\) ⇒ \(z = -3+2(2)+1(1) = 2\). ถ้าเป็น linear regression คำตอบคือ \(h=2\) (ใช้ทำนายราคา/ปริมาณ); ถ้าเป็น logistic regression คำตอบคือ \(h=g(2)=0.881\) (ใช้ตอบความน่าจะเป็นของคลาส 1 และเมื่อ \(>0.5\) จึงทำนายเป็นคลาส 1). ค่า \(z\) เดียวกัน แต่ activation ต่างกันทำให้ความหมายของคำตอบต่างกันคนละเรื่อง.

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

4. Logic Gates จาก Neuron เดียว: AND, OR, NOT

ถึงตรงนี้อาจารย์พาย้อนไปหาตรรกศาสตร์ เพื่อพิสูจน์ด้วยมือว่า node เดียวที่มี sigmoid "คิดแบบตรรกะ" ได้จริง — ถ้าเราเลือก \(\theta\) เป็น. นี่คือส่วนที่ออกสอบคำนวณบ่อยที่สุดของบท เพราะทำมือได้ในไม่กี่บรรทัด.

ต้องรู้ก่อน

ฟังก์ชัน sigmoid \(g(z)=\dfrac{1}{1+e^{-z}}\) — อ่านค่ายังไงโดยไม่ต้องกดเครื่องคิดเลข

\(e\) คือค่าคงที่ประมาณ 2.718 และ \(e^{-z}\) แปลว่า "2.718 ยกกำลังลบ \(z\)". ถ้า \(z\) เป็นบวกมาก ๆ เช่น \(z=10\): \(e^{-10}\approx 0.0000454\) ⇒ \(g(10)=\frac{1}{1+0.0000454}=0.99995\) ≈ 1. ถ้า \(z\) เป็นลบมาก ๆ เช่น \(z=-10\): \(e^{10}\approx 22026\) ⇒ \(g(-10)=\frac{1}{1+22026}=0.0000454\) ≈ 0. ถ้า \(z=0\): \(e^0=1\) ⇒ \(g(0)=\frac{1}{2}=0.5\) พอดี.

ค่าที่ควรจำไว้ใช้ในข้อสอบ: \(g(-30)\approx 0\), \(g(-10)\approx 0.0000454\approx 0\), \(g(0)=0.5\), \(g(10)\approx 0.99995\approx 1\), \(g(30)\approx 1\). กฎง่าย ๆ คือ "\(|z|\ge 10\) ⇒ ปัดเป็น 0 หรือ 1 ได้เลย" และ sigmoid เป็นฟังก์ชันเพิ่มเสมอ (z มากขึ้น ค่ามากขึ้น) โดยมีสมมาตร \(g(-z)=1-g(z)\).

Example on Computational Logic slide written in Thai, defining logic as the philosophical study of reasoning and a proposition as a statement that is either true or false, then showing the classical truth tables for AND, OR and NOT with T and F entries
Slide: Example on Computational Logic — ตารางค่าความจริง AND, OR, NOT (Lecture2.pdf, p.15)

อาจารย์นิยามไว้เป็นภาษาไทยว่า ตรรกศาสตร์ (Logic) คือการศึกษาเชิงปรัชญาว่าด้วยการให้เหตุผล และ ประพจน์ คือประโยคบอกเล่าหรือปฏิเสธที่มีค่าความจริงเป็นจริงหรือเท็จ (ไม่มีก้ำกึ่ง). จากนั้นตั้งเป้าหมายของหัวข้อไว้ว่า "ประยุกต์ Small Neural Network ในการหาค่าความจริงของประพจน์เชิงประกอบ เช่น and, or, not เปรียบเทียบกับการหาค่า Logic จากตรรกศาสตร์แบบเดิม". ตารางค่าความจริงคลาสสิกทั้งสามที่เป็นเกณฑ์ตรวจคำตอบของเราคือ: \(x \wedge y\) เป็นจริงแถวเดียวคือ T–T; \(x \vee y\) เป็นเท็จแถวเดียวคือ F–F; และ \(\sim x\) กลับค่า T↔F. ในสามหน้าถัดไปเราจะแทน T ด้วยเลข 1 และ F ด้วยเลข 0 แล้วดูว่า node เดียวให้ผลตรงตารางนี้ได้ไหม.

AND logic gate built from a single sigmoid neuron with theta = (-30, 20, 20), computing h(x) = g(-30 + 20x1 + 20x2) and listing all four binary input combinations with their results g(-30), g(-10), g(-10), g(10)
Slide: Logic Operator AND จาก neuron เดียว (Lecture2.pdf, p.16)

โจทย์คือ "ทำนาย \(y = x_1 \text{ AND } x_2\)" โดยให้เวกเตอร์ input เป็น \(x = [x_0, x_1, x_2]^\top\) (มี \(x_0\) เป็น bias) และตั้งค่า \(\theta = [-30, 20, 20]^\top\) พร้อมใช้ \(g=\) sigmoid ⇒ ได้ \(h_\theta(x) = g(-30+20x_1+20x_2)\). อาจารย์ไล่แทนค่า 0/1 ให้ดูครบทั้งสี่แถวบนสไลด์ และคำตอบที่ได้คือ \(g(-30), g(-10), g(-10), g(10)\) ตามลำดับ ซึ่งปัดเป็น 0, 0, 0, 1.

คำนวณ: AND gate ด้วย \(\theta_0=-30,\ \theta_1=20,\ \theta_2=20\)
\(h_\theta(x)=g(-30+20x_1+20x_2)\); ใช้ค่าจำ \(g(-30)\approx0,\ g(-10)\approx0,\ g(10)\approx1\)
  1. ขั้นที่ 1 — \((x_1,x_2)=(0,0)\): ไม่มีใครดัน \(z\) ขึ้นเลย
    $$z = -30 + 20(0) + 20(0) = -30 \Rightarrow g(-30)\approx 0$$
  2. ขั้นที่ 2 — \((0,1)\): มีตัวเดียวดันขึ้น 20 ยังไม่พอ
    $$z = -30 + 0 + 20 = -10 \Rightarrow g(-10)\approx 0$$
  3. ขั้นที่ 3 — \((1,0)\): สมมาตรกับขั้นที่ 2 เพราะ weight เท่ากัน
    $$z = -30 + 20 + 0 = -10 \Rightarrow g(-10)\approx 0$$
  4. ขั้นที่ 4 — \((1,1)\): ช่วยกันดัน \(20+20=40 > 30\)
    $$z = -30 + 20 + 20 = 10 \Rightarrow g(10)\approx 1$$

ได้ \([0,0,0,1]\) = ตาราง AND พอดี. เหตุผลเชิงกลไก: bias \(-30\) ตั้ง "ด่าน" ไว้สูง ต้องมี input ช่วยกันดันถึง 40 ถึงจะข้ามได้ ⇒ ต้องเป็น 1 ทั้งคู่เท่านั้น.

OR logic gate built from a single sigmoid neuron with theta = (-10, 20, 20), computing h(x) = g(-10 + 20x1 + 20x2), with the four result slots left blank for students to fill in
Slide: Logic Operator OR — ช่องคำตอบเว้นให้กรอกเอง (Lecture2.pdf, p.17)

หน้า OR ใช้โครงเดิมทุกอย่าง เปลี่ยนแค่ \(\theta = [-10, 20, 20]^\top\) ⇒ \(h_\theta(x) = g(-10+20x_1+20x_2)\) และอาจารย์เว้นคำตอบทั้งสี่แถวไว้ให้เติมเอง (ลูกศร -> หลังแต่ละบรรทัดว่างเปล่า). นี่คือเฉลยเต็ม:

คำนวณ: OR gate ด้วย \(\theta_0=-10,\ \theta_1=20,\ \theta_2=20\) (เฉลยช่องว่างบนสไลด์)
  1. ขั้นที่ 1 — \((0,0)\)
    $$z = -10 \Rightarrow g(-10)\approx 0$$
  2. ขั้นที่ 2 — \((0,1)\): ตัวเดียวก็พอข้ามด่าน 10 แล้ว
    $$z = -10 + 20 = 10 \Rightarrow g(10)\approx 1$$
  3. ขั้นที่ 3 — \((1,0)\)
    $$z = -10 + 20 = 10 \Rightarrow g(10)\approx 1$$
  4. ขั้นที่ 4 — \((1,1)\)
    $$z = -10 + 20 + 20 = 30 \Rightarrow g(30)\approx 1$$

ได้ \([0,1,1,1]\) = ตาราง OR พอดี. ต่างจาก AND แค่ bias เดียว (\(-30 \to -10\)) — bias ยิ่งเข้าใกล้ 0 ด่านยิ่งต่ำ นิวรอนยิ่ง "ยิงง่าย".

NOT logic gate built from a single sigmoid neuron with theta = (10, -20), computing h(x) = g(10 - 20x1) and listing the two input cases with results g(10) and g(-10)
Slide: Logic Operator NOT (Lecture2.pdf, p.18)

NOT มี input เดียว จึงใช้ \(x = [x_0, x_1]^\top\) และ \(\theta = [10, -20]^\top\) ⇒ \(h_\theta(x)=g(10-20x_1)\). จุดที่ต้องสังเกตคือ weight เป็นลบ ซึ่งทำให้ input ที่เป็น 1 ไป "ดึง" \(z\) ลงแทนที่จะดันขึ้น.

คำนวณ: NOT gate ด้วย \(\theta_0=10,\ \theta_1=-20\)
  1. ขั้นที่ 1 — \(x_1=0\): ไม่มีอะไรมาหักล้าง bias
    $$z = 10 - 20(0) = 10 \Rightarrow g(10)\approx 1$$
  2. ขั้นที่ 2 — \(x_1=1\): weight ลบดึงลง 20
    $$z = 10 - 20(1) = -10 \Rightarrow g(-10)\approx 0$$

ได้ \([1,0]\) = ตรงข้ามกับ input พอดี = NOT. สังเกตว่า \(|\theta_0|=10\) กับ \(|\theta_1|=20\) ถูกเลือกให้ \(|z|=10\) ทั้งสองกรณี ⇒ sigmoid อิ่มตัวทั้งคู่ ให้คำตอบเด็ดขาด.

แพทเทิร์นร่วมของทั้งสาม gate: ทุกอันคือ neuron เดียวที่เลือก \(\theta\) ให้ "เส้นตัดสิน" \(z=0\) ตกในตำแหน่งที่ตรงกับตารางค่าความจริง แล้วให้ขนาดของ \(\theta\) ใหญ่พอให้ sigmoid อิ่มตัว. และสิ่งที่ Lesson 3 จะเปลี่ยนคือ เราจะเลิกตั้ง \(\theta\) ด้วยมือ แล้วให้ gradient descent เรียน \(\theta\) จากข้อมูลแทน.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
\(\theta\) ต้องมีขนาดใหญ่พอ ไม่ใช่แค่ทิศทางถูก: sigmoid ต้องอิ่มตัว (เข้าใกล้ 0 หรือ 1 ชัด ๆ) gate จึงจะเด็ดขาด ถ้า \(|z|\) เล็ก คำตอบจะแกว่งอยู่แถว 0.5 ตัดสินไม่ได้.
เปลี่ยนแล้วเกิดอะไร
ย่อ \(\theta\) ของ AND ลง 20 เท่าเป็น \([-1.5, 1, 1]\) (ทิศทางและสัดส่วนเดิมเป๊ะ): ที่ \((1,1)\) ได้ \(z = -1.5+1+1 = 0.5\) ⇒ \(g(0.5)=0.622\) ไม่ใช่ ≈1 อีกต่อไป และที่ \((0,1)\) ได้ \(g(-0.5)=0.378\) ซึ่งไม่ใกล้ 0 — ทั้งที่ทิศทางถูกทุกตัว แต่ gate ไม่เด็ดขาดเพราะยังไม่เข้าเขตอิ่มตัว.
เชื่อมกับ
การอิ่มตัวของ sigmoid คือดาบสองคม: ดีสำหรับทำ gate ด้วยมือ แต่ทำให้อนุพันธ์เข้าใกล้ 0 ซึ่งคือต้นเหตุ vanishing gradient ใน Lesson 5.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 5Logic Gate Neuron
AND gate จาก neuron เดียวใช้ θ₀=−30, θ₁=20, θ₂=20 กับ h(x)=g(θ₀+θ₁x₁+θ₂x₂) ที่ x₁=1, x₂=0 ได้ผลลัพธ์ประมาณเท่าใด?
คำถาม 6AND vs OR
ถ้าเปลี่ยน bias ของ neuron จาก θ₀=−30 เป็น θ₀=−10 โดยคง θ₁=θ₂=20 ไว้เหมือนเดิม gate ที่ได้จะเปลี่ยนเป็นอะไรและเพราะอะไร?

5. Vectorization: เขียนให้เป็นเวกเตอร์แทนการวน loop

ตั้งแต่หัวข้อนี้ไปจนถึงหัวข้อ 6 อาจารย์เปลี่ยนโหมดจาก "แนวคิดของโครงข่าย" มาเป็น "เครื่องมือคณิตศาสตร์ + โค้ด" ที่ต้องใช้เขียนสูตรพวกนั้นให้สั้นและรันได้เร็ว. เริ่มจากคำถามภาคปฏิบัติ: ถ้าต้องบวกเลข 5,000 คู่ เราควรเขียน for loop หรือมีวิธีที่ดีกว่า?

Vectorization slide with numpy code comparing a non-vectorized function that builds a list with a for loop against a vectorized function that adds two numpy arrays directly, plus a printed result reading vectorize version is 54.39492753623188 faster
Slide: Vectorization — เทียบเวลาระหว่าง for loop กับ numpy (Lecture2.pdf, p.19)

นิยามของอาจารย์: vectorization คือสไตล์การคำนวณที่ operations ถูกกระทำกับ vector/matrix ทั้งก้อน แทนที่จะวนทีละสมาชิก — บรรทัดรองขยายว่า "replacing explicit loops with vectorized array operations (efficient computation)". อีกคำที่อาจารย์เขียนไว้ในกรอบเหลืองคือ Element-wise operations = การดำเนินการที่ทำกับแต่ละช่องของ array อย่างอิสระ เช่นการบวกในตัวอย่างนี้: \([0,1,2,\dots]+[0,1,2,\dots]\) ให้ \([0,2,4,\dots]\) ช่องต่อช่อง ไม่ใช่การรวมเป็นค่าเดียว. ผลลัพธ์ที่อาจารย์รันโชว์บนสไลด์คือ "vectorize version is 54.39492753623188 faster" — เร็วกว่า 54 เท่าจากงานเดียวกันเป๊ะ.

import time; import numpy as np
vector_size = 5000

def non_vectorize():
  t1 = time.time()
  X = range(vector_size)
  Y = range(vector_size)
  Z = [X[i] + Y[i] for i in range(len(X))]
  return time.time() - t1

def vectorize():
  t1 = time.time()
  X = np.arange(vector_size)
  Y = np.arange(vector_size)
  Z = X + Y
  return time.time() - t1

t1 = non_vectorize(); t2 = vectorize()
print("vectorize version is " + str(t1/t2) + " faster")
โค้ดทำอะไร
import time; import numpy as npเรียกใช้โมดูล time (สำหรับจับเวลา) และ numpy โดยตั้งชื่อย่อว่า np ตามธรรมเนียม; เครื่องหมาย ; ใช้เขียนสองคำสั่งในบรรทัดเดียว
vector_size = 5000ขนาดของข้อมูลที่จะทดสอบ = 5,000 ตัว ใช้ร่วมกันทั้งสองฟังก์ชันเพื่อให้เทียบกันได้อย่างยุติธรรม
def non_vectorize():นิยามฟังก์ชันเวอร์ชัน "ไม่ vectorize" ซึ่งจะคืนค่าเวลาที่ใช้ (หน่วยวินาที)
t1 = time.time()บันทึกเวลาเริ่มต้น (เป็นจำนวนวินาทีนับจาก 1970) เพื่อเอาไปลบตอนจบ
X = range(vector_size)
Y = range(vector_size)
สร้างลำดับเลข 0,1,2,…,4999 สองชุดแบบ Python ล้วน (ยังไม่ใช่ numpy array)
Z = [X[i] + Y[i] for i in range(len(X))]list comprehension: วนทีละ index \(i\) แล้วบวกทีละคู่ — ได้ list ยาว 5,000 ช่อง; นี่คือ "explicit loop" ที่นิยามของ vectorization บอกให้เลิกใช้
return time.time() - t1คืนเวลาที่ใช้ = เวลาปัจจุบัน − เวลาเริ่มต้น
def vectorize():ฟังก์ชันเวอร์ชัน vectorize ทำงานเดียวกันทุกประการ
X = np.arange(vector_size)np.arange = เวอร์ชัน numpy ของ range ให้ผลเป็น ndarray รูปร่าง (5000,) ชนิด int — ต่างจาก range ตรงที่มันคือ array จริงในหน่วยความจำ
Z = X + Yบวกทั้ง array ในคำสั่งเดียว (element-wise) ได้ array รูปร่าง (5000,) — ไม่มี loop ในระดับ Python เลย งานถูกส่งไปทำใน C
t1 = non_vectorize(); t2 = vectorize()เรียกทั้งสองฟังก์ชัน เก็บเวลาไว้เทียบ; ระวังว่า t1 ตัวนี้เป็นระยะเวลา คนละตัวกับ t1 ที่อยู่ในฟังก์ชัน
print("vectorize version is " + str(t1/t2) + " faster")หารเวลาสองแบบเพื่อดูว่าเร็วกว่ากี่เท่า; str(...) แปลงตัวเลขเป็นข้อความก่อนเชื่อมด้วย + (ถ้าไม่แปลงจะ TypeError)

ผลลัพธ์ที่คาด: บรรทัดข้อความรูปแบบ vectorize version is <ตัวเลข> faster โดยบนสไลด์ได้ 54.39492753623188. เมื่อรันซ้ำบนเครื่องอื่นตัวเลขจะไม่เท่าเดิม (ทดสอบซ้ำ 5 ครั้งได้ราว 8–96 เท่า) เพราะขึ้นกับ CPU และภาระงานขณะนั้น — สิ่งที่ต้องจำคืออันดับความเร็ว ไม่ใช่ตัวเลขเป๊ะ ๆ.

ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 7Vectorization Code
ในโค้ดหน้า 19 ถ้าเปลี่ยน X, Y จาก np.arange(5000) เป็น list ของ Python คือ list(range(5000)) แล้วยังเขียน Z = X + Y เหมือนเดิม จะเกิดอะไรขึ้น?

5A. พีชคณิตเชิงเส้น ตอนที่ 1: เวกเตอร์ (เริ่มจากศูนย์)

ถ้าคุณไม่เคยเรียนพีชคณิตเชิงเส้นมาก่อน หัวข้อนี้กับ 5B คือส่วนที่ต้องอ่านช้า ๆ. อาจารย์ใช้สไลด์ถึง 18 หน้า (หน้า 20–37) ปูพื้นเรื่องนี้ก่อนเข้าสูตรของ NN เพราะทุกสูตรหลังจากนี้เขียนด้วยภาษาเวกเตอร์/เมทริกซ์ทั้งหมด.

Linear Algebra slide: the definition as the branch of mathematics dealing with systems of linear equations, matrices, vector spaces and linear transformations, with the example system x + 2y = 4 and 2x - y = 2, and a note that data science uses it to represent quantities such as 3D images
Slide: Linear Algebra — นิยามและระบบสมการเชิงเส้นตัวอย่าง (Lecture2.pdf, p.20)

อาจารย์นิยามว่า linear algebra คือสาขาคณิตศาสตร์ที่ว่าด้วยทฤษฎีของระบบสมการเชิงเส้น, เมทริกซ์, ปริภูมิเวกเตอร์ และการแปลงเชิงเส้น แล้วยกระบบสมการสองบรรทัดเป็นตัวอย่าง: \(x+2y=4\) และ \(2x-y=2\). ลองแก้จริงให้เห็นว่าทำไมมันเกี่ยวกับเรา — จากสมการที่สอง \(y = 2x-2\) แทนลงสมการแรก: \(x+2(2x-2)=4 \Rightarrow 5x-4=4 \Rightarrow x=1.6\) แล้ว \(y = 2(1.6)-2 = 1.2\) (ตรวจ: \(1.6+2(1.2)=4\) ✓, \(2(1.6)-1.2=2\) ✓). สังเกตหน้าตาของสมการ: "สัมประสิทธิ์คูณตัวแปร บวกกัน เท่ากับค่าหนึ่ง" — เหมือน \(z=\theta_0+\theta_1x_1+\theta_2x_2\) ของเราทุกประการ ต่างกันแค่ในโลก ML เรารู้ \(x\) แต่ต้องหา \(\theta\). อาจารย์ปิดท้ายว่าในงาน data science เราใช้ของพวกนี้แทนปริมาณจริง เช่นภาพ 3 มิติ (ภาพสี = ตัวเลขเรียงเป็น 3 แกน: สูง × กว้าง × 3 สี ซึ่งก็คือ 2,352 ตัวเลขของภาพ 28×28 ในหน้า 3 นั่นเอง).

Vector slide: a vector defined as an object with both magnitude and direction, drawn as arrows from A to B labelled AB or a, with the note that computers view it as an ordered list of numbers to perform operations on, beside a small landscape painting captioned Housing Price Prediction
Slide: Vector — นิยาม magnitude และ direction (Lecture2.pdf, p.21)

นิยามที่ทำสีไว้: เวกเตอร์คือสิ่งที่มีทั้ง magnitude (ขนาด) และ direction (ทิศทาง). ภาพลูกศรจาก A ไป B ที่เขียนแทนด้วย \(\overline{AB}\) หรือ \(\vec{a}\) สื่อว่า "ลูกศรที่ยาวเท่ากันและชี้ทางเดียวกันคือเวกเตอร์เดียวกัน ไม่ว่าจะวาดเริ่มจากจุดไหน" — นั่นคือเหตุผลที่สไลด์วาดลูกศร \(\mathbf{a}\) สองอันคู่ขนานกัน. อาจารย์เสริมมุมของคนทำคอมพิวเตอร์ว่า โดยทั่วไปคอมพิวเตอร์มองเวกเตอร์เป็น "ordered list of numbers" (รายการตัวเลขที่เรียงลำดับ — สลับตำแหน่งไม่ได้) ที่เราเอาไป "ทำ operations" ได้ และเราใช้เวกเตอร์แทนข้อมูลได้ เช่นบ้าน 1 หลังในงานทำนายราคาบ้านเขียนเป็น \([\,100,\ 3\,]\) หมายถึงขนาด 100 ตร.ว. 3 ห้องนอน — ลำดับสำคัญ ถ้าสลับเป็น \([3, 100]\) ความหมายเปลี่ยนทันที.

Vector Operations slide: arrows a and b combined head-to-tail into a + b, the same sum drawn as the diagonal of a parallelogram, a note that subtracting a minus b means a plus negative b, and an arrow a beside a three-times-longer arrow labelled 3a
Slide: Vector Operations — การบวกเวกเตอร์และการคูณด้วยสเกลาร์ (Lecture2.pdf, p.22)

สองการกระทำพื้นฐานที่ต้องทำเป็น. (1) การบวก \(\mathbf{a}+\mathbf{b}\): ในเชิงเรขาคณิตคือต่อหางลูกศร \(\mathbf{b}\) เข้ากับหัวของ \(\mathbf{a}\) แล้วลากจากจุดเริ่มต้นไปยังปลายสุด (จึงได้รูปสี่เหลี่ยมด้านขนานตามที่สไลด์วาด) ส่วนในเชิงตัวเลขคือบวกทีละช่อง: \([1,2]+[2,1]=[1{+}2,\ 2{+}1]=[3,3]\). อาจารย์วงเล็บไว้ว่าการลบ \(\mathbf{a}-\mathbf{b}\) แปลว่า \(\mathbf{a}+(-\mathbf{b})\) คือกลับทิศลูกศร \(\mathbf{b}\) ก่อนแล้วค่อยบวก: \([1,2]-[2,1]=[-1,1]\). (2) การคูณด้วยสเกลาร์: สเกลาร์คือตัวเลขธรรมดาหนึ่งตัว (ไม่มีทิศทาง) การคูณจะยืด/หดความยาวแต่ไม่เปลี่ยนทิศ — ลูกศร \(3\mathbf{a}\) ในสไลด์จึงยาวเป็น 3 เท่าของ \(\mathbf{a}\) และชี้ทางเดิม ในเชิงตัวเลข \(3[1,2]=[3,6]\). (ถ้าคูณด้วยจำนวนลบ ทิศจะกลับหัว และถ้าคูณด้วยเลขระหว่าง 0 ถึง 1 จะหดสั้นลง)

Vector Operations Properties slide: commutative law a plus b equals b plus a demonstrated with column vectors [1,2] plus [2,1] equals [2,1] plus [1,2], the associative law for addition, and the distributive law c times (a plus b) equals ca plus cb demonstrated with 3 times ([1,2] plus [2,1]) equals [3,6] plus [6,3]
Slide: Vector Operations Properties — สมบัติสลับที่ เปลี่ยนหมู่ และแจกแจง (Lecture2.pdf, p.23)

ให้ \(\mathbf{a}, \mathbf{b}, \mathbf{d}\) เป็นเวกเตอร์ และ \(c\) เป็นสเกลาร์ อาจารย์ยก 3 สมบัติพร้อมชื่อไทยกำกับ. Commutative (สมบัติการสลับที่): \(\mathbf{a}+\mathbf{b} = \mathbf{b}+\mathbf{a}\) ตัวอย่างบนสไลด์คือ \(\begin{bmatrix}1\\2\end{bmatrix}+\begin{bmatrix}2\\1\end{bmatrix} = \begin{bmatrix}2\\1\end{bmatrix}+\begin{bmatrix}1\\2\end{bmatrix}\) ซึ่งทั้งสองข้างได้ \(\begin{bmatrix}3\\3\end{bmatrix}\) เท่ากัน. Associative (สมบัติการเปลี่ยนหมู่): \(\mathbf{a}+(\mathbf{b}+\mathbf{d}) = (\mathbf{a}+\mathbf{b})+\mathbf{d}\) — จับคู่บวกก่อนหลังไม่สำคัญ. Distribution (สมบัติการแจกแจง): \(c(\mathbf{a}+\mathbf{b}) = c\mathbf{a}+c\mathbf{b}\) ตัวอย่างสไลด์: \(3\left(\begin{bmatrix}1\\2\end{bmatrix}+\begin{bmatrix}2\\1\end{bmatrix}\right) = \begin{bmatrix}3\\6\end{bmatrix}+\begin{bmatrix}6\\3\end{bmatrix}\). ตรวจสองข้าง: ซ้าย \(=3\begin{bmatrix}3\\3\end{bmatrix}=\begin{bmatrix}9\\9\end{bmatrix}\), ขวา \(=\begin{bmatrix}3+6\\6+3\end{bmatrix}=\begin{bmatrix}9\\9\end{bmatrix}\) — เท่ากันจริง. จำไว้ว่าทั้งสามข้อนี้เป็นของ "การบวกเวกเตอร์" และ "สเกลาร์คูณ" เท่านั้น อีกเดี๋ยวในหัวข้อ 5B เราจะเจอว่าการคูณเมทริกซ์ไม่มีสมบัติสลับที่ — จุดนี้ออกสอบแน่นอน.

ต้องรู้ก่อน

รากที่สองและทฤษฎีพีทาโกรัส — เครื่องมือเดียวที่ใช้วัด "ขนาด" ของเวกเตอร์

รากที่สอง \(\sqrt{k}\) คือ "เลขที่ยกกำลังสองแล้วได้ \(k\)" เช่น \(\sqrt{25}=5\) เพราะ \(5^2=25\); \(\sqrt{9}=3\); ส่วน \(\sqrt{14}\) ไม่ลงตัวจึงตอบเป็นทศนิยมประมาณ 3.742 (ตรวจได้: \(3.742^2 = 14.00\)).

ทฤษฎีพีทาโกรัสบอกว่าในสามเหลี่ยมมุมฉาก ด้านตรงข้ามมุมฉากยกกำลังสอง = ผลรวมกำลังสองของอีกสองด้าน: \(c^2=a^2+b^2\). ตัวอย่างเป็นตัวเลข: เดินไปทางขวา 3 ก้าว แล้วเดินขึ้น 4 ก้าว ระยะตรงจากจุดเริ่มถึงจุดจบคือ \(\sqrt{3^2+4^2}=\sqrt{9+16}=\sqrt{25}=5\) ก้าว (ไม่ใช่ 7 ก้าวซึ่งเป็นระยะที่เดินจริง).

สิ่งที่ต้องยอมรับเพิ่มคือ สูตรนี้ใช้ได้กับกี่มิติก็ได้ แม้วาดรูปไม่ออก: ขนาดของ \([1,2,3]\) คือ \(\sqrt{1^2+2^2+3^2}=\sqrt{14}\) และของ \([3,4,12]\) คือ \(\sqrt{9+16+144}=\sqrt{169}=13\) พอดี.

Geometric Interpretation of Vector slide: point u = (3,4) drawn on x-y axes from origin O, the length or norm of u computed by Pythagoras as the square root of 3 squared plus 4 squared equals 5, the unit direction vector w = (3/5, 4/5), and a boxed question asking for the size of the vector [1,2,3]
Slide: Geometric Interpretation of Vector — norm และ unit vector (Lecture2.pdf, p.24)

อาจารย์อธิบายว่าการเขียนเวกเตอร์แบบพื้นฐานที่สุดคือลูกศรที่มี coordinates on the axis เช่นจุดในระบบพิกัดคาร์ทีเซียน 2 มิติ: จุด \(u=(u_1,u_2) \in \mathbb{R}^2\) กำหนดเวกเตอร์ที่เริ่มจากจุดอ้างอิง O แล้วไปจบที่ \(u\) (เขียนได้ว่า \(\overline{OU}\)). จากนั้นนิยามสองคำที่ทำสีไว้: length (or norm) of vector u เขียนแทนด้วย \(\|u\|\) และวัดด้วย Euclidean magnitude ตามพีทาโกรัส; กับ unit vector คือเวกเตอร์ที่มีความยาวเท่ากับ 1 ซึ่งใช้บอกทิศทางล้วน ๆ. ตัวเลขจริงบนสไลด์คือ \(u=(3,4)\): \(\|u\| = \sqrt{3^2+4^2} = 5\) และทิศทางของมันคือ \(w=\left(\frac{3}{5},\frac{4}{5}\right) = (0.6, 0.8)\) ซึ่งตรวจได้ว่ายาว 1 จริง \(\big(\sqrt{0.36+0.64}=1\big)\) — วิธีหา unit vector คือ "เอาเวกเตอร์หารด้วยความยาวของตัวเอง" เสมอ.

คำนวณ: โจทย์ในกรอบท้ายสไลด์ — ขนาดของเวกเตอร์ \([1,2,3]\)
ใช้สูตร \(\|u\| = \sqrt{u_1^2+u_2^2+\dots+u_n^2}\) (พีทาโกรัสขยายเป็น \(n\) มิติ)
  1. ขั้นที่ 1 — ยกกำลังสองทีละช่อง
    $$1^2 = 1,\qquad 2^2 = 4,\qquad 3^2 = 9$$
  2. ขั้นที่ 2 — บวกกันให้หมด
    $$1+4+9 = 14$$
  3. ขั้นที่ 3 — ถอดรากที่สอง
    $$\|[1,2,3]\| = \sqrt{14} \approx 3.742$$

ตอบ \(\sqrt{14}\approx 3.742\). อย่าเผลอตอบ 6 (ซึ่งคือ \(1+2+3\) การบวกเฉย ๆ) หรือ 3 (จำนวนช่อง) — สองค่านี้คือตัวลวงมาตรฐานในข้อสอบ.

และค่านี้มีความหมายกับเราจริง ๆ: \(\|\theta\|^2 = \sum_j \theta_j^2\) ก็คือเทอม regularization ใน Lesson 1 — การทำ regularization คือ "บีบขนาดของเวกเตอร์ \(\theta\) ให้เล็กลง" นั่นเอง.

Exercise slide asking to calculate the distance between vector a = [1,2,3] and vector b = [3,4,3], with the Euclidean distance formula d(p,q) = square root of the sum of squared differences of each coordinate printed at the bottom
Slide: Exercise — Euclidean distance ระหว่างเวกเตอร์สองตัว (Lecture2.pdf, p.25)

สไลด์นี้เป็นแบบฝึกหัดที่อาจารย์ไม่ได้เฉลยไว้: หาระยะห่างระหว่าง \(a=[1,2,3]\) กับ \(b=[3,4,3]\) โดยใช้สูตร Euclidean distance ที่ให้มา \(d(p,q)=d(q,p)=\sqrt{(q_1-p_1)^2+(q_2-p_2)^2+\dots+(q_n-p_n)^2}\). สังเกตว่าสูตรนี้คือ "ขนาดของเวกเตอร์ผลต่าง" นั่นเอง คือ \(d(a,b) = \|b-a\|\) และการที่ \(d(p,q)=d(q,p)\) ก็เพราะกำลังสองทำให้เครื่องหมายลบหายไป.

คำนวณ: เฉลยแบบฝึกหัดหน้า 25 — ระยะห่างระหว่าง \(a=[1,2,3]\) และ \(b=[3,4,3]\)
\(d(a,b)=\sqrt{(b_1-a_1)^2+(b_2-a_2)^2+(b_3-a_3)^2}\)
  1. ขั้นที่ 1 — ลบทีละช่องให้ได้เวกเตอร์ผลต่าง
    $$b-a = [3-1,\ 4-2,\ 3-3] = [2,\ 2,\ 0]$$
  2. ขั้นที่ 2 — ยกกำลังสองแล้วบวก
    $$2^2+2^2+0^2 = 4+4+0 = 8$$
  3. ขั้นที่ 3 — ถอดราก
    $$d(a,b) = \sqrt{8} = 2\sqrt{2} \approx 2.828$$

ตอบ \(\sqrt{8}\approx 2.828\). ข้อสังเกตที่ออกสอบได้: ช่องที่สาม (3 กับ 3) เท่ากันจึงไม่ส่งผลต่อระยะเลย — feature ที่มีค่าเท่ากันในสองตัวอย่างไม่ช่วยแยกพวกมัน ซึ่งเป็นหลักการเดียวกับที่ใช้ในอัลกอริทึมวัดความคล้าย เช่น k-NN.

The Dot Product slide: definition x dot y = x1y1 + x2y2 giving a scalar in R, a boxed question asking for the dot product of [1,2,3] and [3,2,2], numpy code creating two arrays and printing np.dot(x,y), and the identity that the squared norm of u equals u dot u
Slide: The Dot Product (Inner Product / Scalar Product) (Lecture2.pdf, p.26)

นิยาม: ให้เวกเตอร์ \(\mathbf{x}=(x_1,x_2)\) และ \(\mathbf{y}=(y_1,y_2)\) ผลของ dot product คือ \(\mathbf{x}\cdot\mathbf{y} = x_1y_1 + x_2y_2\) ซึ่งเขียนรวมเป็น \(\sum_i x_iy_i\) และผลลัพธ์เป็นสเกลาร์ (\(\mathbf{x}\cdot\mathbf{y} \in \mathbb{R}\)) ไม่ใช่เวกเตอร์ — นี่คือจุดต่างสำคัญจากการบวกเวกเตอร์หรือ element-wise multiply ที่ให้ผลเป็นเวกเตอร์. อาจารย์เพิ่มความสัมพันธ์สำคัญอีกข้อ: ขนาดของเวกเตอร์เท่ากับรากที่สองของ dot product ของมันกับตัวเอง ⇒ \(\|u\|^2 = u\cdot u\) (ลองกับ \(u=(3,4)\): \(u\cdot u = 9+16 = 25\) และ \(\|u\|=\sqrt{25}=5\) ✓ ตรงกับหน้า 24).

คำนวณ: โจทย์ในกรอบ — dot product ของ \([1,2,3]\) กับ \([3,2,2]\)
  1. ขั้นที่ 1 — คูณทีละคู่ตามตำแหน่ง (ต้องมีจำนวนช่องเท่ากัน)
    $$1\times3 = 3,\qquad 2\times2 = 4,\qquad 3\times2 = 6$$
  2. ขั้นที่ 2 — บวกผลคูณทั้งหมดให้เหลือค่าเดียว
    $$3+4+6 = 13$$

ตอบ 13 (เป็นสเกลาร์). และนี่คือเหตุผลที่ dot product สำคัญกับเรา: \(z=\theta_0x_0+\theta_1x_1+\theta_2x_2\) ของทุก node ก็คือ dot product ระหว่างเวกเตอร์ \(\theta\) กับเวกเตอร์ \(x\) พอดี.

import numpy as np
# For 1-D arrays, it is the dot product of the vectors.
x = np.array([1,2])
y = np.array([1,2])
print(np.dot(x,y));#or#print(x.dot(y))
#1x1 + 2x2
โค้ดทำอะไร
import numpy as npโหลด numpy ซึ่งเป็นไลบรารีสำหรับ array ตัวเลข (ทุกโค้ดของบทนี้เริ่มด้วยบรรทัดนี้)
# For 1-D arrays, it is the dot product of the vectors.คอมเมนต์จากเอกสาร numpy: ถ้า argument เป็น array 1 มิติ np.dot จะให้ dot product ของเวกเตอร์ (ถ้าเป็น 2 มิติจะกลายเป็นการคูณเมทริกซ์ ซึ่งจะเจอในหน้า 34)
x = np.array([1,2])สร้าง ndarray 1 มิติ รูปร่าง (2,) เก็บค่า 1 และ 2 — วงเล็บเหลี่ยมชั้นเดียวหมายถึง 1 มิติ
y = np.array([1,2])เวกเตอร์ตัวที่สอง ต้องมีจำนวนช่องเท่ากับ x ไม่งั้น np.dot จะ error เรื่องมิติไม่ตรงกัน
print(np.dot(x,y))คำนวณ \(1\times1 + 2\times2 = 5\) แล้วพิมพ์ออกมา ผลเป็นสเกลาร์ (numpy int) ไม่ใช่ array
#or#print(x.dot(y))รูปแบบเขียนอีกแบบที่ให้ผลเหมือนกัน: เรียก .dot() เป็นเมธอดของ array โดยตรง — ข้อสอบชอบถามว่าสองแบบนี้ต่างกันไหม (คำตอบ: ไม่ต่าง)
#1x1 + 2x2คอมเมนต์ที่อาจารย์เขียนกำกับวิธีคิดด้วยมือของบรรทัดบน

ผลลัพธ์ที่คาด: 5 (มาจาก \(1\cdot1+2\cdot2 = 1+4 = 5\)) พิมพ์ออกมาบรรทัดเดียว และถ้าเปลี่ยนไปใช้ print(x.dot(y)) ก็ได้ 5 เท่ากัน.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
"ผลรวมถ่วงน้ำหนัก" ที่อยู่ในทุก node คือนิยามของ dot product เป๊ะ ๆ สูตรของ NN (\(z=\theta\cdot x\), cost, \(\sum\theta_j^2\)) จึงเขียนด้วยภาษาเวกเตอร์ได้หมด ไม่ต้องลาก \(\Sigma\) ทีละพจน์.
เปลี่ยนแล้วเกิดอะไร
ถ้าสองเวกเตอร์ยาวไม่เท่ากัน เช่น \([1,2,3]\cdot[3,2]\) จะไม่มีนิยาม (numpy โยน ValueError) เพราะมีช่องที่หาคู่คูณไม่ได้ — กฎ "จำนวนช่องต้องเท่ากัน" นี้จะขยายเป็นกฎมิติของเมทริกซ์ในหัวข้อ 5B.
เชื่อมกับ
\(\|u\|^2 = u\cdot u\) เชื่อม norm (หน้า 24) กับ dot product (หน้า 26) เข้าด้วยกัน และเป็นรูปแบบที่ Lesson 3 ใช้เขียน cost function แบบ vectorized.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 8Dot Product
ให้ x = np.array([1,2]) และ y = np.array([1,2]) ผลของ print(np.dot(x,y)) กับ print(x*y) ต่างกันอย่างไร?
คำถาม 9Vector Length
เวกเตอร์ [1,2,3] มีขนาด (length/norm) เท่ากับเท่าใด ตามสูตร Euclidean magnitude ที่สไลด์หน้า 24 ให้ไว้?

5B. พีชคณิตเชิงเส้น ตอนที่ 2: เมทริกซ์ (เริ่มจากศูนย์)

เวกเตอร์เก็บข้อมูลได้ 1 ตัวอย่าง (บ้าน 1 หลัง) แต่ชุดข้อมูลจริงมีหลายตัวอย่าง และโครงข่ายมี weight หลายเส้น — เราจึงต้องการตารางตัวเลขสองมิติ นั่นคือ เมทริกซ์. สิบเอ็ดหน้าถัดไปของอาจารย์คือกฎการคำนวณของมันทั้งหมด และทุกกฎจะถูกใช้ซ้ำในหัวข้อ 6 กับ 8.

Matrix slide: a matrix defined as a rectangular array of numbers with example A = [[2,3],[5,2],[4,4]] labelled 3x2 meaning 3 rows and 2 columns, and the general element notation a_mn meaning the element in the m-th row and n-th column
Slide: Matrix — นิยาม มิติ และการเรียกสมาชิก (Lecture2.pdf, p.27)

นิยามสั้น ๆ: เมทริกซ์คือ array ของตัวเลขที่เป็นรูป rectangular — คำนี้สำคัญเพราะหมายความว่าทุกแถวต้องมีจำนวนคอลัมน์เท่ากัน (ตารางที่แถวยาวไม่เท่ากันไม่ใช่เมทริกซ์). ตัวอย่างบนสไลด์คือ \(A=\begin{bmatrix}2&3\\5&2\\4&4\end{bmatrix}_{3\times 2}\) ซึ่งอาจารย์กำกับว่า "matrix A has 3 rows and 2 columns" และให้กฎเรียกมิติว่า dimension = #rows × #columns เขียนแทนด้วย \(m \times n\) — ต้องอ่านว่า "สามคูณสอง" เสมอ ไม่ใช่ "สองคูณสาม". ส่วนการเรียกสมาชิกใช้ \(a_{mn}\) = สมาชิกในแถวที่ \(m\) คอลัมน์ที่ \(n\) เช่นในเมทริกซ์นี้ \(a_{21}=5\) (แถว 2 คอลัมน์ 1) และ \(a_{12}=3\) (แถว 1 คอลัมน์ 2) — สองค่านี้ไม่เท่ากัน ตอกย้ำว่าลำดับ "แถวก่อน คอลัมน์หลัง" ห้ามสลับ.

Example slide: given matrix A with first row 3, 4, 38 and second row 8, 46, 54, students must fill in the values of m and n, the element a23, and the indices i and j of the element whose value is 38
Slide: Example — แบบฝึกหัดอ่าน index ของเมทริกซ์ (Lecture2.pdf, p.28)

สไลด์นี้เว้นช่องคำตอบไว้ทั้งหมดให้เราเติม จากเมทริกซ์ \(A=\begin{bmatrix}3&4&38\\8&46&54\end{bmatrix}\) — เฉลยทีละข้อ:

คำนวณ: เฉลยแบบฝึกหัดหน้า 28
\(A = \begin{bmatrix}3 & 4 & 38\\ 8 & 46 & 54\end{bmatrix}_{m\times n}\)
  1. ขั้นที่ 1 — หา \(m\) และ \(n\): นับแถวก่อน แล้วค่อยนับคอลัมน์

    มี 2 แถว (3 4 38 / 8 46 54) และแต่ละแถวมี 3 ตัว

    $$m = 2,\qquad n = 3 \quad(\text{เขียนว่าเมทริกซ์ } 2\times3)$$
  2. ขั้นที่ 2 — หา \(a_{23}\): แถวที่ 2 คอลัมน์ที่ 3

    แถวที่ 2 คือ (8, 46, 54) ตัวที่ 3 ของแถวนี้คือ 54

    $$a_{23} = 54$$
  3. ขั้นที่ 3 — เลข 38 อยู่ตำแหน่ง \(a_{ij}\) ใด

    38 อยู่ในแถวที่ 1 และเป็นตัวที่ 3 ของแถวนั้น

    $$i = 1,\qquad j = 3 \quad\Rightarrow\quad 38 = a_{13}$$

ตอบ \(m=2,\ n=3,\ a_{23}=54,\ 38=a_{13}\). กับดักคลาสสิกคือสลับเป็น \(a_{31}\) (ซึ่งไม่มีอยู่จริง เพราะเมทริกซ์นี้มีแค่ 2 แถว) — วิธีกันพลาดคือถามตัวเองทุกครั้งว่า "ตัวแรกคือแถวใช่ไหม" ก่อนเขียนคำตอบ.

กฎ "แถวก่อน คอลัมน์หลัง" นี้ตรงกับ \(\theta_{ij}\) ของหัวข้อ 3 พอดี: \(i\) (ปลายทาง) = แถว, \(j\) (ต้นทาง) = คอลัมน์.

Matrix Operations slide: addition and subtraction defined element by element for two matrices of the same m by n size, with the worked example [[1,2],[2,4]] plus [[3,-5],[0,1]] left blank for the student
Slide: Matrix Operations — การบวกและลบเมทริกซ์ (Lecture2.pdf, p.29)

กฎการบวก/ลบเขียนเป็นทางการว่า ถ้า \(A=[a_{ij}]_{m\times n}\) และ \(B=[b_{ij}]_{m\times n}\) แล้ว \(A+B = [a_{ij}+b_{ij}]_{m\times n}\) — อ่านเป็นภาษาคน: "บวกช่องที่ตรงกัน ได้ผลลัพธ์ขนาดเท่าเดิม" และเงื่อนไขที่ซ่อนอยู่ในสัญลักษณ์คือ ทั้งสองเมทริกซ์ต้องมีขนาด \(m\times n\) เท่ากันเป๊ะ ไม่งั้นบวกไม่ได้เลย (ต่างจากการคูณที่ขอแค่มิติ "ใน" ตรงกัน). ตัวอย่างที่สไลด์ทิ้งช่องว่างไว้ เฉลยคือ:

$$\begin{bmatrix}1&2\\2&4\end{bmatrix}+\begin{bmatrix}3&-5\\0&1\end{bmatrix}=\begin{bmatrix}1+3&2+(-5)\\2+0&4+1\end{bmatrix}=\begin{bmatrix}4&-3\\2&5\end{bmatrix}$$

อ่านเป็นภาษาคน: บวกเมทริกซ์ = บวกทีละช่อง ขนาดต้องเท่ากัน ผลลัพธ์ขนาดเดิม (เป็น element-wise operation แบบเดียวกับ X + Y ของ numpy ในหน้า 19)

Matrix Multiplication slide on scalar multiplication: the rule k times [a_ij] equals [k a_ij], with two blank exercises, 2 times the 3x2 matrix [[2,3],[5,2],[4,4]] and the same matrix divided by 2
Slide: Scalar Multiplication — คูณและหารเมทริกซ์ด้วยตัวเลขเดียว (Lecture2.pdf, p.30)

กฎคือ ถ้า \(A=[a_{ij}]_{m\times n}\) และ \(k\in\mathbb{R}\) แล้ว \(kA = [k\,a_{ij}]_{m\times n}\) — คูณทุกช่องด้วยตัวเลขเดียวกัน ขนาดไม่เปลี่ยน (แนวคิดเดียวกับการคูณสเกลาร์ของเวกเตอร์ในหน้า 22 เป๊ะ). สไลด์ให้สองโจทย์เว้นคำตอบไว้ เฉลยคือ:

$$2\begin{bmatrix}2&3\\5&2\\4&4\end{bmatrix}=\begin{bmatrix}4&6\\10&4\\8&8\end{bmatrix},\qquad \begin{bmatrix}2&3\\5&2\\4&4\end{bmatrix}\Big/\,2=\begin{bmatrix}1&1.5\\2.5&1\\2&2\end{bmatrix}$$

สังเกตว่าการหารด้วย 2 ก็คือการคูณด้วย \(k=\tfrac12\) และช่องที่เป็นเลขคี่ (3, 5) กลายเป็นทศนิยม 1.5 และ 2.5 — เมทริกซ์ไม่จำเป็นต้องเก็บจำนวนเต็ม. ในงานจริงเราใช้การคูณสเกลาร์ตลอดเวลา เช่น \(\frac{\alpha}{m}\) ที่คูณ gradient ทั้งก้อนในสูตร gradient descent ของหัวข้อ 6.

Matrix Multiplication slide: matrix-vector product where an m by n matrix times an n by 1 column vector gives an m by 1 vector, with y_i described as the sum of the pairwise products of A's i-th row with x, and a green note that A and x must have compatible dimensions
Slide: Matrix-vector multiplication — กฎมิติและวิธีคิดทีละแถว (Lecture2.pdf, p.31)

ก่อนอื่นนิยามศัพท์: column vector คือเมทริกซ์ที่มีคอลัมน์เดียว ขนาด \(n\times 1\) (ตัวเลขเรียงลงมาในแนวตั้ง) และสมาชิกตัวที่ \(n\) เขียนว่า \(x_n\). กฎการคูณคือ เอาเมทริกซ์ \(A\) ขนาด \(m\times n\) คูณเวกเตอร์ \(x\) ขนาด \(n\times1\) ได้ผลลัพธ์ \(y\) ขนาด \(m\times1\) โดยที่ \(y_i\) = ผลรวมของผลคูณทีละคู่ระหว่างแถวที่ \(i\) ของ \(A\) กับ \(x\) — พูดอีกแบบคือ \(y_i\) = dot product ของแถวที่ \(i\) กับเวกเตอร์ \(x\) (นี่คือเหตุผลที่ต้องเรียน dot product ก่อน). ข้อความสีเขียวที่อาจารย์เน้นใต้ภาพคือ A and x must have compatible dimensions. ซึ่งหมายความว่า จำนวนคอลัมน์ของ \(A\) ต้องเท่ากับจำนวนแถวของ \(x\) (ตัว \(n\) ที่อาจารย์ทำสีไว้ทั้งสองที่คือตัวเดียวกัน) ไม่งั้นคูณไม่ได้.

สูตรมิติที่ต้องท่องได้: \((m\times \mathbf{n})\cdot(\mathbf{n}\times 1) = (m\times 1)\) — ตัวเลขที่ติดกันตรงกลางต้องเท่ากันและมันจะ "หายไป" เหลือแค่ขอบนอก

Example slide showing the multiplication of the 2x2 matrix [[1,2],[3,4]] by the column vector [1,0] with the answer boxes left empty
Slide: Example — โจทย์ matrix-vector ที่เว้นคำตอบไว้ (Lecture2.pdf, p.32)
คำนวณ: เฉลยหน้า 32 — \(\begin{bmatrix}1&2\\3&4\end{bmatrix}\begin{bmatrix}1\\0\end{bmatrix}\)
\(A\) ขนาด \(2\times2\), \(x\) ขนาด \(2\times1\)
  1. ขั้นที่ 1 — เช็กมิติก่อนเสมอ

    คอลัมน์ของ \(A\) = 2 เท่ากับแถวของ \(x\) = 2 ⇒ คูณได้ และผลลัพธ์จะมีขนาด \(2\times1\)

  2. ขั้นที่ 2 — แถวที่ 1 ของ \(A\) dot กับ \(x\)
    $$y_1 = 1(1) + 2(0) = 1$$
  3. ขั้นที่ 3 — แถวที่ 2 ของ \(A\) dot กับ \(x\)
    $$y_2 = 3(1) + 4(0) = 3$$

ได้ \(\begin{bmatrix}1\\3\end{bmatrix}\) ซึ่งก็คือคอลัมน์แรกของ \(A\) พอดี — เพราะเวกเตอร์ \([1,0]^\top\) ทำหน้าที่ "เลือกคอลัมน์ที่ 1" ออกมา. ความเข้าใจนี้จะอธิบายเรื่อง identity matrix ในหน้า 37 ได้ทันที.

Matrix Multiplication slide: matrix-matrix product where an m by n matrix times an n by p matrix gives an m by p matrix, with the note that the j-th column of C comes from multiplying A's rows with B's j-th column, and a highlighted reminder that A and B must have compatible dimensions
Slide: Matrix-matrix multiplication — กฎมิติ \((m\times n)(n\times p) = (m\times p)\) (Lecture2.pdf, p.33)

ขยายจากหน้าก่อน: ให้ \(A\) ขนาด \(m\times n\) และ \(B\) ขนาด \(n\times p\) ผลคูณ \(C=AB\) จะมีขนาด \(m\times p\) โดยอาจารย์อธิบายวิธีคิดว่า "คอลัมน์ที่ \(j\) ของ \(C\) ได้จากการเอาแถวของ \(A\) คูณกับคอลัมน์ที่ \(j\) ของ \(B\)" (ทำทีละคอลัมน์ \(j=1,2,\dots,p\)) — เท่ากับทำ matrix-vector ของหน้า 31 ซ้ำ \(p\) รอบนั่นเอง. เงื่อนไขที่ทำสีไว้อีกครั้งคือ n A and B must have compatible dimensions. โดยตัว n ที่เขียนนำหน้าคือฉลากชี้ไปที่มิติที่ต้องตรงกัน: จำนวนคอลัมน์ของ \(A\) ต้องเท่ากับจำนวนแถวของ \(B\). ตัวอย่างการเช็กเร็ว: \((3\times2)(2\times2)\) ⇒ ได้ \(3\times2\) (คูณได้เพราะ 2 ตรงกับ 2) แต่ \((2\times3)(2\times2)\) ⇒ คูณไม่ได้ เพราะ 3 ไม่เท่ากับ 2.

Example slide: exercises multiplying the 3x2 matrix [[1,2],[2,0],[4,4]] by the column vectors [1,0] and [0,1] and then by the 2x2 identity matrix, beside numpy code creating 2x2, 2x1 and 1-D arrays and printing np.dot results with their shapes, and a boxed output list showing [[19 22] [43 50]], (2,2), [[5] [11]], (2,1), [5 11], (2,)
Slide: Example — โจทย์คูณเมทริกซ์ พร้อมโค้ด numpy และผลลัพธ์จริง (Lecture2.pdf, p.34)
คำนวณ: เฉลยโจทย์สามข้อบนหน้า 34 (ทั้งหมดใช้ \(A=\begin{bmatrix}1&2\\2&0\\4&4\end{bmatrix}\) ขนาด \(3\times2\))
  1. ขั้นที่ 1 — \(A\begin{bmatrix}1\\0\end{bmatrix}\): แต่ละแถว dot กับ \([1,0]\)
    $$\begin{bmatrix}1(1)+2(0)\\ 2(1)+0(0)\\ 4(1)+4(0)\end{bmatrix}=\begin{bmatrix}1\\2\\4\end{bmatrix}\quad(\text{คือคอลัมน์ที่ 1 ของ } A)$$
  2. ขั้นที่ 2 — \(A\begin{bmatrix}0\\1\end{bmatrix}\)
    $$\begin{bmatrix}1(0)+2(1)\\ 2(0)+0(1)\\ 4(0)+4(1)\end{bmatrix}=\begin{bmatrix}2\\0\\4\end{bmatrix}\quad(\text{คือคอลัมน์ที่ 2 ของ } A)$$
  3. ขั้นที่ 3 — \(A\begin{bmatrix}1&0\\0&1\end{bmatrix}\): เอาผลสองข้อบนมาเรียงเป็นคอลัมน์
    $$\begin{bmatrix}1&2\\2&0\\4&4\end{bmatrix}\begin{bmatrix}1&0\\0&1\end{bmatrix}=\begin{bmatrix}1&2\\2&0\\4&4\end{bmatrix} = A$$

เช็กมิติ: \((3\times2)(2\times1)=3\times1\) สำหรับสองข้อแรก และ \((3\times2)(2\times2)=3\times2\) สำหรับข้อสุดท้าย. ผลข้อสุดท้ายคือ \(A\) เองเป๊ะ ๆ เพราะเมทริกซ์ \(\begin{bmatrix}1&0\\0&1\end{bmatrix}\) คือ identity matrix ที่แต่ละคอลัมน์ "ดึงคอลัมน์เดิมของ \(A\) ออกมา" ตามที่เห็นในขั้นที่ 1–2.

import numpy as np
x = np.array([[1,2],[3,4]])
print(x.shape)#2x2
y = np.array([[5,6],[7,8]])
print(y.shape)#2x2
z = np.array([[1],[2]])
print(z.shape)#2x1
w = np.array([1,2])
print(w.shape)#(2,)
print(np.dot(x,y));#or#print(x.dot(y))
#[[1*5+2*7, 1*6+2*8],[3*5+4*7, 3*6+4*8]]
print(np.dot(x,y).shape)
print(np.dot(x,z));#or#print(x.dot(z))
#[[1*1+2*2],[3*1+4*2]]
print(np.dot(x,z).shape)
print(np.dot(x,w));#or#print(x.dot(w))
#[1*1+2*2, 3*1+4*2]
print(np.dot(x,w).shape)
โค้ดทำอะไร
x = np.array([[1,2],[3,4]])สร้างเมทริกซ์ \(2\times2\) — วงเล็บเหลี่ยมสองชั้นแปลว่า 2 มิติ โดยแต่ละ list ชั้นในคือ 1 แถว
print(x.shape).shape คืนรูปร่างเป็น tuple: ได้ (2, 2) อ่านว่า 2 แถว 2 คอลัมน์ (อาจารย์คอมเมนต์กำกับว่า 2x2)
z = np.array([[1],[2]])column vector ขนาด \(2\times1\) — สังเกตว่าแต่ละแถวมีสมาชิกเดียว จึงเป็นเมทริกซ์ 2 มิติที่ผอมเป็นแนวตั้ง
w = np.array([1,2])array 1 มิติ ซึ่ง .shape ให้ (2,) — ไม่เหมือน z เลย: มันไม่ใช่ทั้งแถวและคอลัมน์ นี่คือจุดที่สไลด์หน้า 38 เตือนว่า Python ไม่ได้กำหนดว่าเวกเตอร์ปริยายเป็นแถวหรือคอลัมน์
np.dot(x,y)คูณเมทริกซ์ \((2\times2)(2\times2)\) ⇒ ได้ \(2\times2\): ช่อง (1,1) คือ \(1(5)+2(7)=19\), (1,2) คือ \(1(6)+2(8)=22\), (2,1) คือ \(3(5)+4(7)=43\), (2,2) คือ \(3(6)+4(8)=50\)
np.dot(x,z)คูณ \((2\times2)(2\times1)\) ⇒ ได้ \(2\times1\): \([1(1)+2(2)] = 5\) และ \([3(1)+4(2)] = 11\) คืนค่าเป็นเมทริกซ์คอลัมน์ [[5],[11]]
np.dot(x,w)คูณเมทริกซ์กับ array 1 มิติ ⇒ numpy ถือว่า w เป็นเวกเตอร์ธรรมดา ผลลัพธ์จึงเป็น 1 มิติ [5 11] shape (2,) ไม่ใช่ (2,1)
#or#print(x.dot(y))เขียนแบบเมธอดก็ได้ผลเท่ากัน (อาจารย์กำกับไว้ทุกบรรทัด) — สองสไตล์นี้ใช้แทนกันได้เสมอสำหรับ ndarray

ผลลัพธ์ที่คาด (ตรงกับกรอบผลลัพธ์ที่อาจารย์แปะไว้ข้างโค้ด): (2, 2) / (2, 2) / (2, 1) / (2,) จากสี่บรรทัดแรก, แล้ว [[19 22] [43 50]] ตามด้วย (2, 2), [[ 5] [11]] ตามด้วย (2, 1), และ [ 5 11] ตามด้วย (2,). ข้อสังเกตที่ออกสอบได้: ตัวเลขใน \(x\cdot z\) กับ \(x\cdot w\) เหมือนกัน (5 และ 11) แต่รูปร่างต่างกัน — ขึ้นกับว่า argument ตัวที่สองเป็น 2 มิติหรือ 1 มิติ.

Multiplication Properties slide: matrices are not commutative, shown by [[1,2],[2,0]] times [[2,0],[1,1]] = [[4,2],[4,0]] while [[2,0],[1,1]] times [[1,2],[2,0]] = [[2,4],[3,2]], and the associative law A times (B times C) equals (A times B) times C
Slide: Multiplication Properties — การคูณเมทริกซ์สลับที่ไม่ได้ (Lecture2.pdf, p.35)

นี่คือหน้าที่นักเรียนพลาดบ่อยที่สุด เพราะกฎต่างจากเลขคณิตที่คุ้นเคย. Commutative (สมบัติการสลับที่) ใช้ไม่ได้: \(A\times B \ne B\times A\) โดยทั่วไป และอาจารย์พิสูจน์ด้วยตัวเลขจริงสองชุด — สลับลำดับแล้วได้คนละคำตอบเลย:

$$\begin{bmatrix}1&2\\2&0\end{bmatrix}\begin{bmatrix}2&0\\1&1\end{bmatrix}=\begin{bmatrix}4&2\\4&0\end{bmatrix},\qquad \begin{bmatrix}2&0\\1&1\end{bmatrix}\begin{bmatrix}1&2\\2&0\end{bmatrix}=\begin{bmatrix}2&4\\3&2\end{bmatrix}$$

ลองตรวจช่องซ้ายบนของทั้งสองฝั่งให้เห็นว่าทำไมถึงต่าง: ฝั่งแรกคือแถว \((1,2)\) dot คอลัมน์ \((2,1)\) = \(1(2)+2(1)=4\); ฝั่งหลังคือแถว \((2,0)\) dot คอลัมน์ \((1,2)\) = \(2(1)+0(2)=2\) — คนละคู่ตัวเลขกันตั้งแต่ต้น. ส่วน Associative (สมบัติการเปลี่ยนหมู่) ใช้ได้: \(A\times(B\times C) = (A\times B)\times C\) แปลว่าจับคู่คูณก่อนหลังได้ตามสะดวก ขอแค่อย่าสลับลำดับซ้ายขวา. สมบัติข้อนี้มีประโยชน์จริงในการลดงานคำนวณ และเป็นเหตุผลที่เราเขียน \(\theta^{[2]}g(\theta^{[1]}x)\) ต่อกันเป็นทอด ๆ ได้ใน forward computation.

Matrix Transpose slide: definition B = A transpose with b_ij = a_ji swapping an m by n matrix into n by m, the example matrix [[2,3],[5,2],[4,4]] whose transpose is asked for, and numpy code printing x and np.transpose(x) with outputs [[1 2] [3 4]] and [[1 3] [2 4]], plus a 1-D array y whose transpose is unchanged
Slide: Matrix Transpose — สลับแถวกับคอลัมน์ (Lecture2.pdf, p.36)

นิยาม: ถ้า \(A = [a_{ij}]_{m\times n}\) แล้ว \(B = A^{T} = [b_{ij}]_{n\times m}\) โดยที่ \(b_{ij} = a_{ji}\) — สังเกตดัชนีที่สลับกัน: ช่องแถว \(i\) คอลัมน์ \(j\) ของตัวใหม่ ดึงค่ามาจากช่องแถว \(j\) คอลัมน์ \(i\) ของตัวเดิม และขนาดพลิกจาก \(m\times n\) เป็น \(n\times m\). โจทย์บนสไลด์ให้หา \(A^T\) ของ \(A=\begin{bmatrix}2&3\\5&2\\4&4\end{bmatrix}_{3\times2}\) เฉลยคือ

$$A^{T}=\begin{bmatrix}2&5&4\\3&2&4\end{bmatrix}_{2\times3}$$

ตรวจทีละช่อง: \(a_{21}=5\) (แถว 2 คอลัมน์ 1 ของเดิม) จึงต้องไปอยู่ที่ \(b_{12}\) (แถว 1 คอลัมน์ 2 ของใหม่) ✓. วิธีจำง่ายคือ "แถวเดิมกลายเป็นคอลัมน์ใหม่". การ transpose จำเป็นมากเวลาต้องทำให้มิติเข้ากันได้ก่อนคูณ เช่น \(\theta^\top X\) กับ \(X^\top\theta\) ในหน้า 38.

import numpy as np
x = np.array([[1,2],[3,4]])
print(x)
print(np.transpose(x))#or #print(x.T)
#no effect on the transpose of a 1 dimensional array
y = np.array([1,2,3,4])
print(y)
print(np.transpose(y))
โค้ดทำอะไร
x = np.array([[1,2],[3,4]])เมทริกซ์ \(2\times2\) ที่มีแถวแรก 1 2 และแถวสอง 3 4
print(x)พิมพ์ของเดิมออกมาก่อนเพื่อเทียบ: [[1 2] [3 4]]
print(np.transpose(x))สลับแถวกับคอลัมน์: ช่อง (1,2) ที่เดิมเป็น 2 ถูกแทนด้วย \(a_{21}=3\) ⇒ ได้ [[1 3] [2 4]]
#or #print(x.T)x.T คือทางลัดของ np.transpose(x) ให้ผลเหมือนกันทุกประการ (เขียนสั้นกว่า นิยมใช้ในสูตร)
# no effect on the transpose of a 1 dimensional arrayคำเตือนสำคัญ: array 1 มิติ transpose แล้วไม่เปลี่ยนอะไรเลย เพราะ shape (4,) ไม่มีแกนที่สองให้สลับ
y = np.array([1,2,3,4])
print(np.transpose(y))
ทั้งสองบรรทัดพิมพ์ [1 2 3 4] เหมือนกันเป๊ะ — ถ้าอยากได้ column vector จริง ๆ ต้องเขียน y.reshape(-1,1) หรือประกาศเป็น 2 มิติตั้งแต่ต้น

ผลลัพธ์ที่คาด (ตรงกับกรอบที่อาจารย์แปะบนสไลด์): [[1 2] [3 4]], แล้ว [[1 3] [2 4]], แล้ว [1 2 3 4] และ [1 2 3 4] อีกครั้ง — สองบรรทัดสุดท้ายเหมือนกันคือหลักฐานของคำเตือนเรื่อง 1 มิติ.

Identity Matrix slide: a square matrix with ones on the diagonal and zeros elsewhere, the 3x3 example I3 = [[1,0,0],[0,1,0],[0,0,1]], and the property that for any matrix A, A times I equals I times A equals A
Slide: Identity Matrix — เมทริกซ์เอกลักษณ์ (Lecture2.pdf, p.37)

นิยาม: identity matrix คือเมทริกซ์จัตุรัส (แถว = คอลัมน์) ที่สมาชิกบนเส้นทแยงมุมเท่ากับ "1" ทั้งหมด ส่วนช่องอื่นเป็น 0 ตัวอย่างขนาด \(3\times3\) บนสไลด์คือ \(I_3=\begin{bmatrix}1&0&0\\0&1&0\\0&0&1\end{bmatrix}\). สมบัติที่อาจารย์เน้นคือ สำหรับเมทริกซ์ \(A\) ใด ๆ จะได้ \(A\times I = I\times A = A\) — มันคือ "เลข 1 ของโลกเมทริกซ์" คูณแล้วไม่เปลี่ยนอะไร. เหตุผลเห็นได้จากหน้า 32/34 ที่เราเพิ่งทำ: คอลัมน์ที่ \(j\) ของ \(I\) คือเวกเตอร์ที่มี 1 อยู่ตำแหน่งที่ \(j\) เท่านั้น เวลาคูณมันจึงไป "ดึงคอลัมน์ที่ \(j\) ของ \(A\)" ออกมาวางที่เดิมพอดี ทำครบทุกคอลัมน์ก็ได้ \(A\) กลับมาเหมือนเดิม. ข้อสังเกตที่ออกสอบได้: \(A\times I = I\times A\) เป็นข้อยกเว้นของกฎ "คูณเมทริกซ์สลับที่ไม่ได้" ในหน้า 35 — แต่ขนาดของ \(I\) ทั้งสองข้างอาจต่างกัน เช่น \(A\) ขนาด \(3\times2\) ต้องใช้ \(I_2\) คูณข้างขวา และ \(I_3\) คูณข้างซ้าย จึงจะมิติเข้ากันได้.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
กฎ "มิติในต้องตรงกัน" ไม่ได้ตั้งขึ้นมาลอย ๆ: ผลลัพธ์แต่ละช่องคือ dot product ของแถวกับคอลัมน์ ซึ่งต้องมีจำนวนตัวเลขเท่ากันถึงจะจับคู่คูณได้ครบ — เป็นกฎเดียวกับ "เวกเตอร์สองตัวต้องยาวเท่ากัน" ในหน้า 26.
เปลี่ยนแล้วเกิดอะไร
สลับลำดับ \(A\) กับ \(B\) ในตัวอย่างหน้า 35 ผลเปลี่ยนจาก \(\begin{bmatrix}4&2\\4&0\end{bmatrix}\) เป็น \(\begin{bmatrix}2&4\\3&2\end{bmatrix}\) — ทุกช่องเปลี่ยนหมด และในกรณีที่มิติไม่จัตุรัส การสลับอาจทำให้คูณไม่ได้เลย เช่น \((3\times2)(2\times4)\) ทำได้ แต่ \((2\times4)(3\times2)\) ทำไม่ได้.
เชื่อมกับ
หัวข้อ 6 จะใช้กฎมิตินี้ตัดสินว่าต้องเขียน \(\theta^\top X\) หรือ \(X\theta\) และหัวข้อ 8 จะใช้ตัดสินว่า \(\theta^{[1]}\) ต้องมีขนาดเท่าไรจึงคูณกับ \(a^{[0]}\) ได้.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 10Matrix Indexing
จากเมทริกซ์ A = [[3,4,38],[8,46,54]] (2 แถว 3 คอลัมน์) สมาชิก a₂₃ มีค่าเท่าใด?
คำถาม 11Matrix Dimensions
ถ้า A มีขนาด 3×2 และ B มีขนาด 2×4 ข้อใดถูกต้องเกี่ยวกับการคูณสองเมทริกซ์นี้?
คำถาม 12Identity & Commutativity
ข้อใดกล่าวถูกต้องเกี่ยวกับสมบัติการคูณเมทริกซ์ตามสไลด์หน้า 35 และ 37?

6. Vectorized Linear Regression: จาก For Loop สู่ Matrix

ตอนนี้เรามีเครื่องมือครบแล้ว (เวกเตอร์ เมทริกซ์ dot product กฎมิติ) อาจารย์จึงเอามาประกอบร่างกับสิ่งที่เรารู้อยู่แล้วจาก Lesson 1 คือ linear regression เพื่อแสดงให้เห็นว่า "สมการยาว ๆ ที่มี \(\Sigma\)" เขียนใหม่เป็นการคูณเมทริกซ์ครั้งเดียวได้อย่างไร — และนี่คือรูปแบบที่ Lesson 3 จะใช้เขียน forward/backward ของทั้งโครงข่าย.

Vectorization for Linear Regression slide: the hypothesis h(x) = theta0 x0 + theta1 x1 + ... + theta_n xn with x0 highlighted in red and defined as 1, then the same hypothesis written as a row vector of thetas times a column vector of x, or a row vector of x times a column vector of thetas, equal to theta transpose X or X transpose theta
Slide: Vectorization for Linear Regression (One Example) — เขียน hypothesis เป็นเมทริกซ์ (Lecture2.pdf, p.38)

เริ่มจาก hypothesis สำหรับหลาย feature ที่คุ้นเคย: \(h_\theta(x) = \theta_0 x_0 + \theta_1x_1+\theta_2x_2+\dots+\theta_nx_n\) โดยอาจารย์ทำสีแดงที่ \(x_0\) พร้อมกำกับว่า \(x_0 = 1\) — เทคนิคนี้สำคัญมาก: การแอบใส่ feature ปลอมที่มีค่า 1 เข้าไปทำให้เทอม bias \(\theta_0\) กลายเป็น "เทอมคูณปกติ" เทอมหนึ่ง เราจึงเขียนทุกอย่างเป็น dot product เดียวได้โดยไม่ต้องบวก \(\theta_0\) แยก. จากนั้นอาจารย์เขียนสองแบบที่ให้ผลเท่ากัน: ถ้าให้ \(\theta\) เป็นแถวแล้ว \(x\) เป็นคอลัมน์ ก็คือ \(\theta^{\top}X\); ถ้าให้ \(x\) เป็นแถวแล้ว \(\theta\) เป็นคอลัมน์ ก็คือ \(X^{\top}\theta\) — ทั้งคู่ให้สเกลาร์ตัวเดียวกัน. อาจารย์ยังเตือนในวงเล็บว่า "in python – no pre-defined argument whether a row or a column vector is default vector" คือ Python ไม่ได้กำหนดว่าเวกเตอร์ 1 มิติเป็นแถวหรือคอลัมน์ (ตรงกับที่เราเห็นในโค้ดหน้า 34: w.shape เป็น (2,) ไม่ใช่ (2,1) หรือ (1,2)) ดังนั้นเวลาเขียนโค้ดจริงต้องดู shape ทุกครั้ง ไม่ใช่เดาจากสูตรบนกระดาษ.

Vectorization for Linear Regression slide: a one-row table with x1 = 0, x2 = 1 and y = 1, the hypothesis h(x) = 2 + x1 + x2, and the matrix form h(x) = X theta written as the row vector [x0 x1 x2] times the column vector of theta0, theta1, theta2 with the result left blank
Slide: ตัวอย่าง one example — \(h_\theta(x)=2+x_1+x_2\) (Lecture2.pdf, p.39)

ตัวอย่างนี้มีข้อมูลทดสอบแถวเดียว: \(x_1=0,\ x_2=1\) และค่าจริง \(y=1\) พร้อมสมมติฐาน \(h_\theta(x) = 2+x_1+x_2\) ซึ่งอ่านค่า \(\theta\) ได้ทันทีว่า \(\theta_0=2,\ \theta_1=1,\ \theta_2=1\). อาจารย์วงเล็บไว้ว่าในทางปฏิบัติเรามักเก็บ 1 training example เป็น row vector จึงเขียนเป็น \(h_\theta(x) = X\theta\) โดย \(X = [x_0\ x_1\ x_2] = [1\ 0\ 1]\) (อย่าลืมเติม \(x_0=1\) เป็นช่องแรก) คูณกับ \(\theta\) ที่เป็นคอลัมน์ \([2,1,1]^\top\) ⇒ เช็กมิติ \((1\times3)(3\times1) = 1\times1\) ได้สเกลาร์ตัวเดียว:

$$h_\theta(x) = \begin{bmatrix}1&0&1\end{bmatrix}\begin{bmatrix}2\\1\\1\end{bmatrix} = 1(2)+0(1)+1(1) = 3$$

ผลทำนายคือ 3 ขณะที่ค่าจริง \(y=1\) ⇒ คลาดเคลื่อน \(h-y = 2\) ซึ่งจะกลายเป็นวัตถุดิบของ cost function ในหน้า 42. จุดที่ต้องระวังคือคอลัมน์แรกของ \(X\) ต้องเป็น 1 เสมอ ถ้าลืมใส่ ผลจะเหลือ \(0(1)+1(1)=1\) ซึ่งผิด เพราะ bias \(\theta_0=2\) หายไปทั้งก้อน.

Vectorization for Linear Regression with more than one example: the hypothesis h(x) = X theta where X is a matrix whose rows are training examples 1 to m and whose columns are features x0 to xn, multiplied by the column vector of parameters theta0 to theta_n
Slide: Vectorization for Linear Regression (>One Example) — หลายตัวอย่างพร้อมกัน (Lecture2.pdf, p.40)

พอมีหลายตัวอย่าง อาจารย์ขยาย \(X\) จาก 1 แถวเป็น \(m\) แถว โดยใช้สัญกรณ์ superscript ในวงเล็บกลมแทนหมายเลขตัวอย่าง: แถวที่ 1 คือ \([x_0^{(1)}\ x_1^{(1)}\ \dots\ x_n^{(1)}]\) ไปจนถึงแถวที่ \(m\) คือ \([x_0^{(m)}\ \dots\ x_n^{(m)}]\) — 1 แถว = 1 training example, 1 คอลัมน์ = 1 feature (คอลัมน์แรกเป็น \(x_0=1\) ทั้งแถว). คูณด้วย \(\theta\) ที่เป็นคอลัมน์ \((n+1)\times1\) ⇒ \(h_\theta(x) = X\theta\) มีขนาด \((m\times(n{+}1))\cdot((n{+}1)\times1) = m\times1\) คือคำทำนายของทุกตัวอย่างเรียงเป็นคอลัมน์เดียว ได้มาในการคูณครั้งเดียว. อย่าสับสนสองสัญกรณ์: \(x^{(i)}\) (วงเล็บกลม) = ตัวอย่างที่ \(i\), \(x_j\) (ห้อย) = feature ที่ \(j\), และ \(a^{[l]}\) (วงเล็บเหลี่ยม) = layer ที่ \(l\) — ข้อสอบชอบสลับสามอันนี้.

Example slide: given h(x) = 1 + 2x1 + 3x2 and three training examples in a table where x1 is 0 for all rows, x2 is 1, 2 and 3, and y is 1, 2 and 3, find the predicted values in matrix form
Slide: Example — หา \(h_\theta\) ของ 3 ตัวอย่างในรูปเมทริกซ์ (Lecture2.pdf, p.41)
คำนวณ: เฉลยหน้า 41 — \(h_\theta(x)=1+2x_1+3x_2\) กับ 3 ตัวอย่างในตาราง
ตารางบนสไลด์: \((x_1,x_2,y) = (0,1,1),\ (0,2,2),\ (0,3,3)\) ⇒ \(\theta=[1,2,3]^\top\)
  1. ขั้นที่ 1 — สร้างเมทริกซ์ \(X\) โดยเติมคอลัมน์ \(x_0=1\) ไว้หน้าสุด
    $$X = \begin{bmatrix}1&0&1\\1&0&2\\1&0&3\end{bmatrix}_{3\times3},\qquad \theta = \begin{bmatrix}1\\2\\3\end{bmatrix}_{3\times1}$$
  2. ขั้นที่ 2 — เช็กมิติก่อนคูณ

    \((3\times3)(3\times1) = 3\times1\) ⇒ ได้คำทำนาย 3 ค่า หนึ่งค่าต่อหนึ่งตัวอย่าง ✓

  3. ขั้นที่ 3 — คูณทีละแถว (แถวของ \(X\) dot กับ \(\theta\))
    $$\begin{bmatrix}1(1)+0(2)+1(3)\\ 1(1)+0(2)+2(3)\\ 1(1)+0(2)+3(3)\end{bmatrix}=\begin{bmatrix}4\\7\\10\end{bmatrix}$$
  4. ขั้นที่ 4 — ตรวจด้วยวิธี for loop ทีละตัวอย่าง
    $$h_1 = 1+2(0)+3(1)=4,\quad h_2 = 1+0+3(2)=7,\quad h_3 = 1+0+3(3)=10$$

ได้ \([4,7,10]^\top\) เท่ากันทั้งสองวิธี แต่แบบเมทริกซ์ทำเสร็จในคำสั่งเดียว. สังเกตว่า \(x_1=0\) ทุกแถว ⇒ \(\theta_1=2\) ไม่มีผลต่อคำทำนายเลยในชุดข้อมูลนี้ — feature ที่ค่าคงที่เหมือนกันหมดไม่ให้ข้อมูลอะไรกับโมเดล.

From For Loop to Vectorization slide: the cost function J = (1/m) sum of squared errors rewritten with the inner sum over theta_i x_i, a housing table with sizes 100, 200, 300, bedrooms 3, 2, 3 and prices 1,000,000 2,000,000 3,000,000, the assumption theta0 = 1, theta1 = 2, theta2 = 3, and a nested for loop implementation of computeCost
Slide: From For Loop to Vectorization — ตัวอย่างราคาบ้านและ cost function (Lecture2.pdf, p.42)

อาจารย์เอา cost function ของ linear regression มาเขียนสองแบบให้เห็นว่าเป็นสิ่งเดียวกัน: \(J(\theta) = \frac{1}{m}\sum_{i=1}^{m}\left(h_\theta(x^{(i)})-y^{(i)}\right)^2\) แล้วแทน \(h_\theta\) ด้วยผลรวมข้างในเป็น \(J(\theta) = \frac{1}{m}\sum_{i=1}^{m}\left(\sum_{i=0}^{n}\theta_i x_i - y^{(i)}\right)^2\) — คือ "ผลรวมซ้อนผลรวม" ซึ่งเวลาเขียนโค้ดตรง ๆ จะกลายเป็น for loop ซ้อน for loop พอดี. ข้อมูลตัวอย่างคือบ้าน 3 หลัง: ขนาด \(x_1\) = 100, 200, 300; จำนวนห้องนอน \(x_2\) = 3, 2, 3; ราคา \(y\) = 1,000,000 / 2,000,000 / 3,000,000 และให้ลองใช้ \(\theta_0=1, \theta_1=2, \theta_2=3\).

คำนวณ: cost ของข้อมูลราคาบ้านที่ \(\theta=(1,2,3)\)
\(X=\begin{bmatrix}1&100&3\\1&200&2\\1&300&3\end{bmatrix}\) (เติม \(x_0=1\)), \(y=[10^6,\ 2{\times}10^6,\ 3{\times}10^6]^\top\), \(m=3\)
  1. ขั้นที่ 1 — ทำนายทีละหลัง \(h = X\theta\)
    $$h_1 = 1+2(100)+3(3) = 210,\quad h_2 = 1+2(200)+3(2)=407,\quad h_3 = 1+2(300)+3(3)=610$$
  2. ขั้นที่ 2 — หาค่าคลาดเคลื่อน \(h-y\)
    $$210-10^6 = -999{,}790,\quad 407-2{\times}10^6 = -1{,}999{,}593,\quad 610-3{\times}10^6 = -2{,}999{,}390$$
  3. ขั้นที่ 3 — ยกกำลังสอง บวกกัน แล้วหารด้วย \(m=3\)
    $$J = \tfrac{1}{3}\left[(-999790)^2+(-1999593)^2+(-2999390)^2\right] \approx 4.66\times10^{12}$$

\(J \approx 4{,}664{,}764{,}193{,}950\) — มหาศาล เพราะ \(\theta\) ชุดนี้ทำนายหลักร้อยขณะที่ราคาจริงเป็นหลักล้าน. บทเรียนสองข้อ: (1) ค่าของ cost ไม่มีความหมายในตัวเอง มันมีไว้ให้ ลดลง; (2) เมื่อ feature มีสเกลต่างกันมาก (100–300 เทียบกับราคาหลักล้าน) ตัวเลขจะระเบิดง่าย ซึ่งเป็นเหตุผลของการทำ feature scaling ที่สอนใน Lesson 1.

โค้ดในภาพฝั่งขวาของหน้านี้คือเวอร์ชัน for loop ของ cost function ที่อาจารย์เขียนสด (โค้ดนี้อยู่ในภาพ ไม่ใช่ข้อความ):

def computeCost(X, y, theta):
  # initialize some useful values
  J = 0
  m = X.shape[0]
  n = X.shape[1]
  error = np.zeros(m)

  for i in range(m):
    h = 0
    for j in range(n):
      h = h + X[i,j] * theta[j]
    error[i] = h - y[i]
    #print(error)

  J = (1/(m)) * np.sum(np.square(error))
  return J
โค้ดทำอะไร
def computeCost(X, y, theta):รับเมทริกซ์ข้อมูล X (m แถว × n คอลัมน์ รวม \(x_0\)), เวกเตอร์เป้าหมาย y และพารามิเตอร์ theta แล้วคืนค่า cost หนึ่งค่า
m = X.shape[0]
n = X.shape[1]
shape[0] = จำนวนแถว = จำนวน training example; shape[1] = จำนวนคอลัมน์ = จำนวน feature (รวม bias) — ลำดับ index นี้คือกฎ "แถวก่อน คอลัมน์หลัง" ของหน้า 27
error = np.zeros(m)จองที่เก็บค่าคลาดเคลื่อนของทุกตัวอย่าง เริ่มต้นด้วยศูนย์ m ช่อง (ต้องจองก่อนเพราะจะเขียนทีละช่องในลูป)
for i in range(m):ลูปนอก: ไล่ทีละ training example \(i = 0,1,\dots,m-1\)
h = 0
for j in range(n):
  h = h + X[i,j] * theta[j]
ลูปใน: สะสมผลรวมถ่วงน้ำหนักของตัวอย่างที่ \(i\) ทีละ feature — นี่คือ dot product ที่เขียนมือ เทียบเท่ากับ \(\sum_j \theta_j x_j\) หนึ่งบรรทัด
error[i] = h - y[i]เก็บส่วนต่างระหว่างคำทำนายกับค่าจริงของตัวอย่างนั้น (ยังไม่ยกกำลังสอง)
#print(error)บรรทัด debug ที่อาจารย์ปิดไว้ — เปิดเมื่ออยากดูว่าค่าคลาดเคลื่อนแต่ละตัวเป็นเท่าไร
J = (1/(m)) * np.sum(np.square(error))np.square ยกกำลังสองทุกช่อง, np.sum รวมเป็นค่าเดียว, แล้วหารด้วย m ได้ค่าเฉลี่ย — ตรงกับสูตร \(J=\frac{1}{m}\sum(h-y)^2\) บนสไลด์

ผลลัพธ์ที่คาด: เรียก computeCost(X, y, np.array([1,2,3])) ด้วยข้อมูลราคาบ้าน 3 หลังข้างบน จะได้ค่าเดียวกับที่คำนวณมือไว้คือประมาณ 4664764193949.67. สังเกตว่าลูปซ้อนสองชั้นนี้ทำงาน \(m\times n = 3\times3 = 9\) รอบสำหรับข้อมูลจิ๋ว ๆ — ถ้าเป็นภาพ 2,352 feature กับตัวอย่าง 10,000 รูป จะกลายเป็น 23 ล้านรอบในภาษา Python ซึ่งช้ามาก จึงต้องแปลงเป็น vectorized ในหน้าถัดไป.

From For Loop to Vectorization slide: on the left the nested-loop implementations of computeCost and gradientDescent, on the right the vectorized versions using np.dot and np.sum, and at the bottom the gradient descent update rule theta_j := theta_j - alpha times the partial derivative, rewritten as theta_j := theta_j - (alpha/m) times the sum of (h - y) times x_j
Slide: For Loop vs Vectorization — โค้ดทั้งสี่บล็อกพร้อมสูตร update (Lecture2.pdf, p.43)

หน้านี้วางโค้ดสี่บล็อกเทียบกัน: ซ้ายคือ cost function และ gradient descent แบบ for loop, ขวาคือของเดิมที่เขียนใหม่ด้วย numpy. กรอบเหลืองล่างคือสูตรที่ทุกบล็อกกำลังทำตาม — เริ่มจากรูปทั่วไป \(\theta_j := \theta_j - \alpha\frac{\partial J(\theta_j)}{\partial \theta_j}\) โดย \(\alpha\) คือ learning rate แล้วแทนอนุพันธ์ด้วยรูปที่คำนวณได้จริง \(\theta_j := \theta_j - \frac{\alpha}{m}\sum_{i=1}^{m}\left(h_\theta(x^{(i)})-y^{(i)}\right)x_j^{(i)}\). อ่านสูตรนี้เป็นภาษาคน: "ปรับ \(\theta_j\) ลงตามสัดส่วนของ ความผิดพลาดเฉลี่ย ที่ถ่วงน้ำหนักด้วย feature ตัวที่ \(j\) ของตัวอย่างนั้น" — feature ที่ค่ามากจะดึง \(\theta\) แรงกว่า และตัวอย่างที่ทำนายพลาดมากจะมีอิทธิพลมากกว่า.

ก่อนดูเวอร์ชัน vectorized มาดูเวอร์ชัน for loop ของ gradient descent ที่อาจารย์เขียนไว้ฝั่งซ้ายก่อน (โค้ดนี้อยู่ในภาพเช่นกัน) เพื่อจะได้เห็นว่ามีลูปซ้อนกันถึงสี่ชั้น:

def gradientDescent(X, y, theta, alpha, num_iters):
  m = y.shape[0] # number of training examples
  n = X.shape[1] # number of input features
  theta = theta.copy() # avoid changing the original array
  theta1 = np.zeros(n) # theta to be returned
  J_history = [] # save cost in every iteration
  error_x = np.zeros(m)
  result = np.zeros(n)

  for i in range(num_iters):
    if i>0:
      theta = theta1.copy()
    for j in range(n):
      for k in range(m):
        h = 0
        for p in range(n):
          h = h + X[k,p] * theta[p]
        error_x[k] = (h - y[k]) * X[k,j]
      result[j] = np.sum(error_x)
      theta1[j] = theta[j] - (alpha / m) * result[j]
    J_history.append(computeCost(X, y, theta))

  return theta1, J_history
โค้ดทำอะไร
theta = theta.copy()คัดลอกก่อนแก้ เพื่อไม่ให้ array ต้นฉบับของผู้เรียกถูกเปลี่ยนตาม (numpy ส่ง array แบบอ้างอิง ไม่ใช่สำเนา)
theta1 = np.zeros(n)ที่เก็บ \(\theta\) ชุดใหม่ — แยกจากชุดเก่าเพราะต้องอัปเดตทุก \(\theta_j\) พร้อมกันจาก \(\theta\) เดิม (simultaneous update) ไม่ใช่ทยอยใช้ค่าที่เพิ่งเปลี่ยน
J_history = []list เปล่าไว้เก็บ cost ของทุกรอบ ใช้พล็อตดูว่า cost ลดลงจริงไหม
for i in range(num_iters):ลูปชั้นที่ 1: จำนวนรอบการอัปเดต (iteration) ที่เรากำหนด
if i>0: theta = theta1.copy()ตั้งแต่รอบที่สองเป็นต้นไป ให้ใช้ \(\theta\) ที่ได้จากรอบก่อนเป็นจุดตั้งต้น
for j in range(n):ลูปชั้นที่ 2: ไล่ปรับพารามิเตอร์ทีละตัว \(\theta_j\)
for k in range(m): … for p in range(n):ลูปชั้นที่ 3 และ 4: สำหรับตัวอย่างที่ \(k\) คำนวณ \(h\) ด้วยการวนคูณทีละ feature \(p\) — คือ dot product ที่เขียนมืออีกครั้ง
error_x[k] = (h - y[k]) * X[k,j]ความผิดพลาดของตัวอย่าง \(k\) คูณกับ feature ตัวที่ \(j\) ของตัวอย่างนั้น = เทอมข้างในผลรวมของสูตร update
result[j] = np.sum(error_x)รวมทุกตัวอย่างให้เป็น gradient ของ \(\theta_j\)
theta1[j] = theta[j] - (alpha / m) * result[j]ก้าวลงเขาหนึ่งก้าวตามสูตร \(\theta_j := \theta_j - \frac{\alpha}{m}\sum(h-y)x_j\)
return theta1, J_historyคืนพารามิเตอร์ชุดสุดท้ายและประวัติ cost ทั้งหมด

ผลลัพธ์ที่คาด: ฟังก์ชันนี้ให้ค่าเท่ากับเวอร์ชัน vectorized ทุกประการ (เช่นทดสอบกับข้อมูลหน้า 41: \(X=\begin{bmatrix}1&0&1\\1&0&2\\1&0&3\end{bmatrix}\), \(y=[4,7,10]\), \(\theta\) เริ่มที่ศูนย์, \(\alpha=0.1\) รอบแรกได้ \(\theta=[0.7,\ 0,\ 1.6]\)) แต่ใช้ลูป Python ถึง \(\text{num\_iters}\times n\times m\times n\) รอบ ขณะที่เวอร์ชันข้างล่างใช้ \(\text{num\_iters}\) รอบเท่านั้น.

def gradientDescent(X, y, theta, alpha, num_iters):
  m = y.shape[0] # number of training examples
  theta = theta.copy()
  J_history = []
  # Use a python list to save cost in every iteration
  for i in range(num_iters):
    theta = theta - (alpha/m) * (np.dot(X, theta) - y).dot(X)
    J_history.append(computeCost(X, y, theta))
  return theta, J_history

def computeCost(X, y, theta):
  # initialize some useful values
  m = y.size # number of training examples
  J = 0
  h = np.dot(X, theta)
  J = (1/(m)) * np.sum(np.square(h - y))
  return J
โค้ดทำอะไร
m = y.shape[0]จำนวน training example อ่านจากความยาวของ y (ใน computeCost ใช้ y.size ซึ่งให้ผลเท่ากันสำหรับ array 1 มิติ)
h = np.dot(X, theta)คำทำนายของทุกตัวอย่างพร้อมกัน: \((m\times(n{+}1))\cdot((n{+}1)\times1)\) ⇒ เวกเตอร์ยาว m — แทนลูปสองชั้นของหน้า 42 ทั้งก้อน
J = (1/(m)) * np.sum(np.square(h - y))h - y ลบทีละช่องได้เวกเตอร์ความผิดพลาด, np.square ยกกำลังสองทีละช่อง, np.sum ยุบเป็นค่าเดียว แล้วเฉลี่ยด้วย m
(np.dot(X, theta) - y).dot(X)หัวใจของการ vectorize: เวกเตอร์ความผิดพลาด \((h-y)\) ขนาด \((m,)\) dot กับ \(X\) ขนาด \((m\times(n{+}1))\) ⇒ ได้เวกเตอร์ขนาด \((n{+}1,)\) ซึ่งแต่ละช่องคือ \(\sum_i (h^{(i)}-y^{(i)})x_j^{(i)}\) ของ \(\theta_j\) นั้นพอดี — คือ gradient ครบทุกตัวในคำสั่งเดียว
theta = theta - (alpha/m) * (...)คูณ gradient ด้วยสเกลาร์ \(\alpha/m\) แล้วลบออกจาก \(\theta\) ทั้งเวกเตอร์ — อัปเดตทุกพารามิเตอร์พร้อมกันโดยอัตโนมัติ (ไม่ต้องทำ theta1 แยกเหมือนเวอร์ชันลูป)
J_history.append(computeCost(X, y, theta))เก็บ cost หลังอัปเดตของรอบนั้นไว้ดูแนวโน้ม; ถ้า cost ไม่ลดลงแปลว่า \(\alpha\) ใหญ่เกินไป
return theta, J_historyคืน \(\theta\) ที่เรียนได้ และประวัติ cost — รูปแบบเดียวกับที่ Lesson 3 จะใช้เทรนโครงข่ายจริง
คำนวณ: gradient descent รอบแรกด้วยมือ (ข้อมูลหน้า 41, \(\theta\) เริ่มที่ 0, \(\alpha=0.1\))
\(X=\begin{bmatrix}1&0&1\\1&0&2\\1&0&3\end{bmatrix},\ y=\begin{bmatrix}4\\7\\10\end{bmatrix},\ \theta=\begin{bmatrix}0\\0\\0\end{bmatrix},\ m=3\)
  1. ขั้นที่ 1 — ทำนายและหาความผิดพลาด
    $$h = X\theta = \begin{bmatrix}0\\0\\0\end{bmatrix},\qquad h-y = \begin{bmatrix}-4\\-7\\-10\end{bmatrix}$$
  2. ขั้นที่ 2 — \((h-y)\cdot X\) ทีละคอลัมน์ของ \(X\)
    $$\text{คอลัมน์ }x_0:\ -4(1)-7(1)-10(1) = -21$$ $$\text{คอลัมน์ }x_1:\ -4(0)-7(0)-10(0) = 0$$ $$\text{คอลัมน์ }x_2:\ -4(1)-7(2)-10(3) = -48$$
  3. ขั้นที่ 3 — อัปเดต \(\theta \leftarrow \theta - \frac{\alpha}{m}(\text{gradient})\)
    $$\theta = \begin{bmatrix}0\\0\\0\end{bmatrix} - \frac{0.1}{3}\begin{bmatrix}-21\\0\\-48\end{bmatrix} = \begin{bmatrix}0.7\\0\\1.6\end{bmatrix}$$
  4. ขั้นที่ 4 — cost หลังรอบแรก
    $$h = \begin{bmatrix}2.3\\3.9\\5.5\end{bmatrix},\quad J = \tfrac{1}{3}\left[(-1.7)^2+(-3.1)^2+(-4.5)^2\right] = \tfrac{32.75}{3} \approx 10.92$$

cost ลดจาก \(J=55.0\) (ตอน \(\theta=0\)) เหลือ \(10.92\) หลังก้าวเดียว และถ้าวนต่ออีกสองรอบจะได้ 2.17 แล้ว 0.44 — เห็นได้ว่า \(\theta_1\) ยังเป็น 0 ตลอดเพราะคอลัมน์ \(x_1\) เป็นศูนย์ทั้งหมด จึงไม่มี gradient มาดัน.

จุดที่สไลด์ไม่ตรงกันเป๊ะ (ต้องรู้ไว้ตอบข้อสอบ)
สูตร cost บนสไลด์คือ \(J=\frac{1}{m}\sum(h-y)^2\) ถ้าหาอนุพันธ์จริง ๆ จะได้ \(\frac{2}{m}\sum(h-y)x_j\) ซึ่งมีเลข 2 นำหน้า แต่ทั้งสูตร update และโค้ดบนสไลด์ใช้ \(\frac{1}{m}\sum(h-y)x_j\) (ไม่มี 2). นี่ไม่ใช่ความผิดพลาดที่ทำให้อัลกอริทึมพัง เพราะค่าคงที่ 2 ถูกกลืนเข้าไปใน learning rate \(\alpha\) ได้ (เทรนด้วย \(\alpha\) ครึ่งหนึ่งให้ผลเท่ากัน) และตำราจำนวนมากจึงนิยามคอสต์เป็น \(\frac{1}{2m}\sum(h-y)^2\) เพื่อให้ 2 ตัดกันพอดี. คำตอบที่ปลอดภัยในห้องสอบ: ใช้สูตรตามที่สไลด์เขียน และถ้าถูกถามว่าทำไมไม่มี 2 ให้ตอบว่าค่าคงที่ถูกดูดซับเข้ากับ \(\alpha\).
Exercise slide: implement the numpy vectorized version of L1 loss (mean absolute error, hint use abs) and L2 loss (mean square error), with their formulas, and starter code defining h = np.array([1,2,3,4,5]) and y = np.array([2,2,3,3,4]) with two function bodies marked Fill your code
Slide: Exercise — เขียน L1 และ L2 loss แบบ vectorized (Lecture2.pdf, p.44)

แบบฝึกหัดสุดท้ายของส่วนนี้: ให้เขียน numpy เวอร์ชัน vectorized ของ L1 loss และ L2 loss โดยอาจารย์ให้สูตรมาแล้วคือ Mean Absolute Error (L1) \(J(\theta)=\frac{1}{m}\sum_{i=1}^{m}\left|h_\theta(x^{(i)})-y^{(i)}\right|\) พร้อมใบ้ว่าให้ใช้ abs(...) และ Mean Square Error (L2) \(J(\theta)=\frac{1}{m}\sum_{i=1}^{m}\left(h_\theta(x^{(i)})-y^{(i)}\right)^2\). โค้ดตั้งต้นให้ \(h=[1,2,3,4,5]\) กับ \(y=[2,2,3,3,4]\) และเว้นบรรทัด loss = #Fill your code ไว้ให้เติม:

import numpy as np
h = np.array([1,2,3,4,5])
print(h.shape)
y = np.array([2,2,3,3,4])
print(y.shape)

def L1(h, y):
  loss = #Fill your code
  return loss

def L2(h, y):
  loss = #Fill your code
  return loss
โค้ดทำอะไร
h = np.array([1,2,3,4,5])เวกเตอร์คำทำนายของโมเดล 5 ตัวอย่าง shape (5,)
print(h.shape)พิมพ์ (5,) — อาจารย์ให้พิมพ์ก่อนเพื่อยืนยันว่าทั้ง h และ y เป็น array 1 มิติขนาดเท่ากัน (ถ้าไม่เท่ากัน การลบจะ broadcast ผิดหรือ error)
y = np.array([2,2,3,3,4])ค่าจริง 5 ตัว — คู่กับ h ตำแหน่งต่อตำแหน่ง
def L1(h, y): / def L2(h, y):ฟังก์ชันที่ต้องเขียนเอง คืนค่า loss เป็นตัวเลขตัวเดียว (สเกลาร์) ไม่ใช่ array
loss = #Fill your codeช่องว่างที่เป็นโจทย์ — ต้องเขียนให้ "ลบ → แปลงเป็นค่าบวก (abs หรือยกกำลังสอง) → รวม → หารด้วยจำนวนตัวอย่าง" ในบรรทัดเดียวโดยไม่ใช้ for loop

เฉลยที่ถูกต้อง เขียนแบบ vectorized ล้วน ไม่มีลูป:

def L1(h, y):
  loss = (1/h.size) * np.sum(np.abs(h - y))
  return loss

def L2(h, y):
  loss = (1/h.size) * np.sum(np.square(h - y))
  return loss

print(L1(h, y))
print(L2(h, y))
โค้ดทำอะไร
h - yลบทีละช่อง (element-wise) ได้ [-1 0 0 1 1] — ยังมีทั้งบวกและลบ จึงห้ามรวมทันที ไม่งั้นค่าลบจะหักล้างค่าบวก
np.abs(h - y)ทำให้ทุกช่องเป็นบวก ได้ [1 0 0 1 1] ตรงกับสัญลักษณ์ \(|\cdot|\) ในสูตร L1 (ตามที่อาจารย์ใบ้ให้ใช้ abs)
np.square(h - y)ยกกำลังสองทุกช่อง ได้ [1 0 0 1 1] เช่นกันในกรณีนี้ เพราะส่วนต่างเป็น 0 หรือ ±1 พอดี — แต่โดยทั่วไปสองอันนี้ไม่เท่ากัน
np.sum(...)รวมทุกช่องเป็นค่าเดียว ได้ 3 ทั้งสองกรณี
(1/h.size) * ...หารด้วยจำนวนตัวอย่าง \(m=5\) ตามที่สูตรมี \(\frac{1}{m}\) นำหน้า (h.size = 5; เขียน len(h) หรือ y.shape[0] ก็ได้ผลเท่ากัน)
return lossคืนค่าสเกลาร์ — ถ้าลืม np.sum ฟังก์ชันจะคืน array 5 ช่องซึ่งผิดโจทย์

ผลลัพธ์ที่คาด: 0.6 ทั้งสองบรรทัด เพราะส่วนต่าง \(h-y = [-1,0,0,1,1]\) ⇒ L1 \(= \frac{1+0+0+1+1}{5} = 0.6\) และ L2 \(= \frac{1+0+0+1+1}{5} = 0.6\) (บังเอิญเท่ากันเพราะ \(1^2 = |1|\); ถ้าเปลี่ยน \(h_5\) เป็น 6 ส่วนต่างจะเป็น 2 ⇒ L1 \(=\frac{4}{5}=0.8\) แต่ L2 \(=\frac{1+0+0+1+4}{5}=1.2\) ต่างกันทันที).

ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 13Fill the Code
บรรทัด loss = #Fill your code ของฟังก์ชัน L1(h, y) ควรเติมด้วยข้อใด ให้ตรงกับสูตร Mean Absolute Error ที่สไลด์ให้ไว้?
คำถาม 14Vectorized Cost
ในฟังก์ชัน computeCost เวอร์ชัน vectorized บรรทัด h = np.dot(X, theta) ให้ผลลัพธ์รูปร่างแบบใด เมื่อ X มีขนาด m×(n+1) และ theta มีขนาด (n+1)

7. Shallow Neural Network และการสร้าง XNOR จาก AND, OR, NOT

กลับมาที่โครงข่ายอีกครั้ง คราวนี้ด้วยเครื่องมือครบมือ. อาจารย์วางแผนผังเต็มของ shallow network ให้ดูก่อน แล้วค่อยพิสูจน์ด้วยตัวอย่าง XNOR ว่า "หลาย node หลายชั้น" ทำสิ่งที่ node เดียวทำไม่ได้จริง.

Shallow Neural Network slide: a single hidden layer network labelled 2 Layers NN with inputs x1 x2 plus a red bias x0 feeding hidden nodes a1[1] a2[1] a3[1] through weights theta_10 to theta_32, a red bias a0[1] feeding the output node a1[2] through theta_10[2], and a magnified node showing z = sum of theta_i x_i and a = g(z)
Slide: Shallow Neural Network — โครงข่าย 1 hidden layer พร้อม weight ทุกเส้น (Lecture2.pdf, p.45)

อาจารย์เรียกโครงข่ายนี้ว่า "Single hidden layer (2 Layers NN)" — นับเฉพาะชั้นที่มีพารามิเตอร์ คือ layer 1 (hidden 3 node) และ layer 2 (output 1 node) ส่วน input ไม่นับ. สิ่งที่ต้องอ่านให้ออกคือ bias มีสองตัว ไม่ใช่ตัวเดียว: \(x_0\) (สีแดงด้านซ้าย) เป็น bias ของ layer 1 ที่วิ่งเข้าทุก hidden node ผ่าน \(\theta_{10}^{[1]}, \theta_{20}^{[1]}, \theta_{30}^{[1]}\) และ \(a_0^{[1]}\) (สีแดงด้านบน ซึ่งอาจารย์ทำสีเน้นไว้) เป็น bias ของ layer 2 ที่วิ่งเข้า output node ผ่าน \(\theta_{10}^{[2]}\) — ทั้งคู่มีค่าคงที่ \(+1\) เสมอ (สไลด์เขียนกำกับ "+1" ไว้ในกรอบขยายด้วย). นับพารามิเตอร์ทั้งหมดของโครงข่ายนี้: layer 1 มี \(3\times(2+1) = 9\) ตัว (\(\theta_{10}^{[1]}\) ถึง \(\theta_{32}^{[1]}\)) และ layer 2 มี \(1\times(3+1) = 4\) ตัว (\(\theta_{10}^{[2]}, \theta_{11}^{[2]}, \theta_{12}^{[2]}, \theta_{13}^{[2]}\)) รวม 13 ตัว. กรอบขยายทางขวาย้ำสูตรของทุก node อีกครั้ง: \(z = \sum_{i=0}^{n}\theta_i x_i\) แล้ว \(a = g(z)\).

XNOR using AND OR NOT slide: the classical AND, OR and NOT truth tables, a logic gate diagram computing Q = (A.B) + (notA.notB), and a coloured table with columns x1, x2, x1 AND x2, not x1, not x2, (not x1) AND (not x2), and h(x) whose values are 1, 0, 0, 1
Slide: XNOR using AND, OR and NOT — ตารางค่าความจริงเต็ม (Lecture2.pdf, p.46)

เป้าหมายคือสร้าง XNOR ซึ่งให้ผลเป็น 1 เมื่อ input ทั้งสองเหมือนกัน (ทั้งคู่เป็น 0 หรือทั้งคู่เป็น 1) — มันคือสิ่งตรงข้ามกับ XOR ที่ Perceptron เดี่ยวแก้ไม่ได้ในหน้า 9. วิธีของอาจารย์คือประกอบจาก gate ที่เรามีแล้ว ตามสูตรในแผนผังวงจร \(Q = (A\cdot B) + (\bar{A}\cdot\bar{B})\) อ่านว่า "(ทั้งคู่เป็น 1) หรือ (ทั้งคู่เป็น 0)". ตารางสีบนสไลด์ไล่ค่าครบทั้ง 4 แถว:

\(x_1\)\(x_2\)\(x_1\wedge x_2\)\(\sim x_1\)\(\sim x_2\)\(\sim x_1 \wedge \sim x_2\)\(h_\theta(x)\)
0001111
0101000
1000100
1110001

อ่านตารางทีละแถวให้เข้าใจกลไก: แถว \((0,0)\) คอลัมน์ AND ได้ 0 แต่คอลัมน์ \(\sim x_1 \wedge \sim x_2\) ได้ 1 (เพราะ NOT ของ 0 คือ 1 ทั้งคู่) ⇒ เมื่อเอาสองคอลัมน์นี้มา OR กันจึงได้ \(h=1\); แถว \((0,1)\) ทั้งสองคอลัมน์ได้ 0 ⇒ \(h=0\); แถว \((1,1)\) คอลัมน์ AND ได้ 1 ⇒ \(h=1\). ผลรวมคือ \([1,0,0,1]\) = XNOR พอดี. จุดสำคัญคือ เราต้องมีสองเงื่อนไขทำงานคู่ขนานกัน (ตรวจ "1 ทั้งคู่" กับตรวจ "0 ทั้งคู่") ซึ่งก็คือเหตุผลที่ต้องมี hidden layer ที่มี 2 node.

XNOR using AND OR and NOT slide part 2: three single-neuron diagrams stacked, the first with bias -30 and weights 20, 20 labelled AND, the second with bias -10 and weights 20, 20 labelled OR, and the third with bias 10 and weights -20, -20 labelled (NOT x1) AND (NOT x2)
Slide: XNOR using AND, OR and NOT (2) — ชุด \(\theta\) ของสาม gate ที่ใช้ประกอบ (Lecture2.pdf, p.47)

หน้านี้ให้ \(\theta\) ครบทั้งสาม gate ที่จะเอามาต่อกัน: AND \((\theta_0,\theta_1,\theta_2)=(-30,20,20)\), OR \((-10,20,20)\), และ gate ใหม่ที่เพิ่งต้องใช้คือ (NOT \(x_1\)) AND (NOT \(x_2\)) ซึ่งใช้ \((10,-20,-20)\). ลองตรวจ gate ตัวที่สามด้วยตัวเลข: ที่ \((0,0)\) ได้ \(z=10\) ⇒ \(g(10)\approx1\) ✓ (ตรงเงื่อนไข "0 ทั้งคู่"), ที่ \((0,1)\) หรือ \((1,0)\) ได้ \(z=10-20=-10\) ⇒ \(\approx0\), และที่ \((1,1)\) ได้ \(z=10-40=-30\) ⇒ \(\approx0\). สังเกตโครงสร้างของ \(\theta\): bias เป็นบวก (\(+10\)) ส่วน weight เป็นลบทั้งคู่ (\(-20\)) — ตรงข้ามกับ AND ทุกเครื่องหมาย ซึ่งสมเหตุสมผลเพราะมันคือ "AND ของค่าที่ถูกกลับด้าน". ทีนี้ประกอบเป็นโครงข่าย 2 ชั้น: hidden node ตัวที่ 1 = AND, hidden node ตัวที่ 2 = (NOT \(x_1\)) AND (NOT \(x_2\)), และ output node = OR ของสอง hidden นั้น ⇒ \(z^{[2]} = -10 + 20a_1^{[1]} + 20a_2^{[1]}\).

คำนวณ: forward ทั้งโครงข่าย XNOR ครบ 4 กรณี (ใช้ \(g(\pm10)\approx1/0\), \(g(\pm30)\approx1/0\))
hidden 1: \(a_1^{[1]}=g(-30+20x_1+20x_2)\); hidden 2: \(a_2^{[1]}=g(10-20x_1-20x_2)\); output: \(h=g(-10+20a_1^{[1]}+20a_2^{[1]})\)
  1. ขั้นที่ 1 — \((0,0)\)
    $$a_1^{[1]} = g(-30) \approx 0,\quad a_2^{[1]} = g(10) \approx 1$$ $$z^{[2]} = -10 + 20(0) + 20(1) = 10 \Rightarrow h = g(10) \approx 1$$
  2. ขั้นที่ 2 — \((0,1)\)
    $$a_1^{[1]} = g(-30+20) = g(-10)\approx0,\quad a_2^{[1]} = g(10-20) = g(-10) \approx 0$$ $$z^{[2]} = -10 + 0 + 0 = -10 \Rightarrow h = g(-10) \approx 0$$
  3. ขั้นที่ 3 — \((1,0)\)

    สมมาตรกับขั้นที่ 2 ทุกประการ (weight ของ \(x_1, x_2\) เท่ากันในทั้งสอง gate) ⇒ \(h \approx 0\)

  4. ขั้นที่ 4 — \((1,1)\)
    $$a_1^{[1]} = g(-30+40) = g(10)\approx1,\quad a_2^{[1]} = g(10-40) = g(-30)\approx0$$ $$z^{[2]} = -10 + 20(1) + 20(0) = 10 \Rightarrow h = g(10)\approx1$$

\(h = [1,0,0,1]\) ตรงกับตารางความจริง XNOR ในหน้า 46 เป๊ะ. หัวใจคือ hidden สอง node "ตอบคนละคำถาม" (ทั้งคู่เป็น 1 ไหม / ทั้งคู่เป็น 0 ไหม) แล้ว output แค่ OR ผลของทั้งสอง.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
ตัวอย่างนี้พิสูจน์ compositionality: AND และ \((\neg x_1)\wedge(\neg x_2)\) ต่างก็แยกได้ด้วยเส้นตรงเส้นเดียวทั้งคู่ แต่พอรวมด้วย OR อีกชั้นกลับได้ฟังก์ชันที่เส้นตรงเดียวทำไม่ได้ (XNOR) — แต่ละ hidden node ตัดพื้นที่คนละมุม แล้ว output รวมผลที่ตัดแล้ว.
เปลี่ยนแล้วเกิดอะไร
เปลี่ยน output gate จาก OR เป็น AND (เก็บ hidden เดิม): hidden 1 เป็น 1 เฉพาะ \((1,1)\) และ hidden 2 เป็น 1 เฉพาะ \((0,0)\) — สองตัวนี้ไม่มีวันเป็น 1 พร้อมกัน ⇒ AND ให้ 0 เสมอ โครงข่ายกลายเป็นตัวตอบ 0 คงที่ทั้งที่โครงสร้างยังเป็น 2 ชั้นเหมือนเดิม.
เชื่อมกับ
หลักการ "แต่ละ hidden unit ตัดสินคนละเงื่อนไข แล้ว output รวมผล" คือกลไกเดียวกับ 5 ข้อในหน้า 7 และเป็นฐานของ backpropagation ใน Lesson 3 ที่จะหา \(\theta\) พวกนี้จากข้อมูลแทนการตั้งมือ.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 15XNOR Construction
จากโครงข่าย XNOR ของอาจารย์ ที่ (x₁,x₂)=(0,1) ค่า h(x) สุดท้ายเป็นเท่าใด และเพราะเหตุใด?

8. Forward Computation: คำนวณทั้งโครงข่ายด้วยมือ

นี่คือปลายทางของบท และเป็นทักษะที่ต้องทำได้ในห้องสอบภายในไม่กี่นาที: ให้ \(\theta\) กับ \(x\) มา แล้วเดินคำนวณจาก input จนถึง \(h_\theta(x)\).

Forward Computation slide: the same shallow network with 2 inputs, 3 hidden nodes and 1 output, with the headings Computation on layer 1 and Computation on layer 2 left completely blank for students to fill in during class
Slide: Forward Computation — หัวข้อเว้นว่างให้กรอกในห้อง (Lecture2.pdf, p.48)

หน้า 48 คือโจทย์: โครงข่ายเดียวกับหน้า 45 (input \(x_1,x_2\) + bias \(x_0\) → hidden 3 node → output 1 node พร้อม bias \(a_0^{[1]}\)) โดยอาจารย์เว้นที่ว่างไว้ใต้หัวข้อ "Computation on layer 1" และ "Computation on layer 2" ให้เราเขียนสมการเอง. ก่อนดูเฉลยลองนึกกฎสองข้อที่ใช้: (1) ทุก node ทำสองขั้นเสมอคือ \(z\) แล้ว \(a\); (2) index ของ \(\theta\) อ่านว่า "ปลายทางก่อน ต้นทางหลัง" ดังนั้นสมการของ node ที่ 2 ใน layer 1 ต้องใช้ \(\theta_{2\ast}^{[1]}\) ทั้งหมด.

Forward Computation Solution slide: layer 1 equations z1[1] = theta10[1] + theta11[1] x1 + theta12[1] x2 with a1[1] = g(z1[1]), and similarly for nodes 2 and 3, then layer 2 with z1[2] = theta10[2] + theta11[2] a1[1] + theta12[2] a2[1] + theta13[2] a3[1] and h(x) = a1[2] = g(z1[2])
Slide: Forward Computation (Solution) — เฉลยเต็มทั้งสองชั้น (Lecture2.pdf, p.49)

เฉลยของอาจารย์เขียนครบทุกบรรทัด และนี่คือชุดสมการที่ต้องจำรูปแบบให้ได้ — layer 1 ใช้ \(x\) ดิบเป็น input:

$$\begin{aligned} z_1^{[1]} &= \theta_{10}^{[1]} + \theta_{11}^{[1]}x_1 + \theta_{12}^{[1]}x_2, & a_1^{[1]} &= g(z_1^{[1]})\\ z_2^{[1]} &= \theta_{20}^{[1]} + \theta_{21}^{[1]}x_1 + \theta_{22}^{[1]}x_2, & a_2^{[1]} &= g(z_2^{[1]})\\ z_3^{[1]} &= \theta_{30}^{[1]} + \theta_{31}^{[1]}x_1 + \theta_{32}^{[1]}x_2, & a_3^{[1]} &= g(z_3^{[1]}) \end{aligned}$$

layer 2 ใช้ activation ของ layer 1 เป็น input (ไม่ใช่ \(x\) อีกแล้ว) และมี 4 เทอมเพราะรับจาก 3 node บวก bias:

$$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)$$

รูปแบบที่ซ้ำทุกชั้น: "คูณ weight บวก bias ได้ \(z\) → ผ่าน \(g\) ได้ \(a\)" แล้วส่ง \(a\) เป็น input ของชั้นถัดไป

เขียนย่อเป็นเมทริกซ์ด้วยกฎจากหัวข้อ 5B (ทำทั้ง 3 node ของ layer 1 พร้อมกัน) โดย \(\theta^{[1]}\) มีขนาด \(3\times3\) และ \(a^{[0]}=[1,\ x_1,\ x_2]^\top\):

$$z^{[1]} = \theta^{[1]}a^{[0]},\quad a^{[1]} = g(z^{[1]}),\qquad z^{[2]} = \theta^{[2]}\begin{bmatrix}1\\ a^{[1]}\end{bmatrix},\quad h = g(z^{[2]})$$
คำนวณตัวอย่างเต็ม (ค่าสมมติเพื่อฝึกมือ): \(x=(1,2)\)
\(\theta^{[1]}=\begin{bmatrix}0&1&0\\1&-1&1\\-1&0.5&0.5\end{bmatrix}\) (แถว = node 1,2,3; คอลัมน์ = bias, \(x_1\), \(x_2\))  |  \(\theta^{[2]}=[-1,\ 1,\ 1,\ -1]\) (bias, \(a_1,a_2,a_3\))  |  ใช้ sigmoid
  1. ขั้นที่ 1 — นับพารามิเตอร์ (เช็กว่าเข้าใจขนาดเมทริกซ์)
    $$\theta^{[1]}:\ 3\times3 = 9,\quad \theta^{[2]}:\ 1\times4 = 4\quad\Rightarrow\quad 13\text{ ตัว}$$
  2. ขั้นที่ 2 — layer 1: หา \(z^{[1]}\) ทีละ node (bias + weight×input)
    $$\begin{aligned} z_1^{[1]} &= 0 + 1(1) + 0(2) = 1\\ z_2^{[1]} &= 1 + (-1)(1) + 1(2) = 2\\ z_3^{[1]} &= -1 + 0.5(1) + 0.5(2) = 0.5 \end{aligned}$$
  3. ขั้นที่ 3 — layer 1: ผ่าน sigmoid ทีละตัว
    $$a^{[1]} = \big[g(1),\ g(2),\ g(0.5)\big] = [0.731,\ 0.881,\ 0.622]$$
  4. ขั้นที่ 4 — layer 2: ใช้ \(a^{[1]}\) เป็น input (ไม่ใช่ \(x\))
    $$z^{[2]} = -1 + 1(0.731) + 1(0.881) + (-1)(0.622) = -0.011$$
  5. ขั้นที่ 5 — output
    $$h_\theta(x) = g(-0.011) = 0.497$$

\(h_\theta(x) \approx 0.497\) ⇒ ถ้าใช้เกณฑ์ 0.5 จะทำนาย \(y=0\) (พลาดไปนิดเดียว). ทั้งกระบวนการคือ "คูณ+บวก" สลับกับ "sigmoid" อย่างละ 2 รอบ — ถ้าทำได้ 13 พารามิเตอร์นี้ ก็ทำได้กับโครงข่ายที่มีล้านพารามิเตอร์เช่นกัน เพราะสูตรไม่เปลี่ยน.

กลไกที่ต้องอธิบายได้
ทำไมต้องมี
สูตรแบ่งเป็น "\(z\) แล้ว \(a\)" ไม่ใช่คำนวณรวดเดียว เพราะ backpropagation (Lesson 3) ต้องแยกอนุพันธ์เป็น 2 ขั้นตามลำดับนี้: \(\partial a/\partial z = g'\) และ \(\partial z/\partial\theta = a^{[l-1]}\) — ถ้าไม่แยกจะไม่มี "จุดต่อ" ให้ chain rule ไล่ทีละขั้น.
เปลี่ยนแล้วเกิดอะไร
ถ้า hidden layer มี 5 node แทน 3: \(z_1^{[2]}\) เปลี่ยนจาก 4 พจน์เป็น 6 พจน์ (\(\theta_{10}^{[2]}+\sum_{k=1}^{5}\theta_{1k}^{[2]}a_k^{[1]}\)), \(\theta^{[2]}\) เปลี่ยนจาก \(1\times4\) เป็น \(1\times6\) และ \(\theta^{[1]}\) จาก \(3\times3\) เป็น \(5\times3\) ⇒ พารามิเตอร์รวม \(15+6=21\) ตัว (จากเดิม 13).
เชื่อมกับ
"z แล้ว a" คือ 2 ใน 4 เทอมของสูตร backprop ที่ Lesson 3 พิสูจน์ และขยายเป็น \(L\) ชั้นใน Lesson 4.
ออกสอบสูง — ข้อความที่อาจารย์ทำสี
คำถาม 16Forward Computation
ในการคำนวณ z₁⁽²⁾ ของโครงข่าย 2 layer ที่มี hidden layer 3 node ตัวแปรที่ถูกนำมาคูณกับ θ⁽²⁾ คืออะไร?


ชัยชนะของบทเรียนนี้
คุณควรอธิบายได้ว่าทำไมต้องมี Neural Network (นับเทอม polynomial ได้: \(2n+n(n-1)/2\) ⇒ 5,150), เล่าประวัติ 3 ยุคพร้อมชื่อ-ปี-ข้อจำกัดได้, อ่านสัญกรณ์ \(\theta_{ij}^{[l]}\), \(a_j^{[l]}\) และคำนวณขนาด \(\theta^{[l]}\) ได้ถูก, คำนวณ logic gate จาก neuron เดียว (AND/OR/NOT) และอธิบายได้ว่าทำไม XOR/XNOR ต้องมี hidden layer, ทำพีชคณิตเชิงเส้นพื้นฐานได้ทุกข้อ (norm, dot product, คูณเมทริกซ์, transpose, identity, กฎมิติ), อ่านและเติมโค้ด numpy ของสไลด์ได้ทุกบล็อก (vectorization, dot, transpose, computeCost, gradientDescent, L1/L2) และทำ Forward Computation เต็มโครงข่ายด้วยมือได้ตั้งแต่ input จนถึง \(h_\theta(x)\) — สูตรชุดเดียวกับที่ Lesson 3 จะสอน backpropagation ย้อนกลับ.

ภาคผนวก: Slide หน้า 1-49 ของ Lecture2.pdf — เช็คว่าอ่านครบ

ไล่ทุกหน้าที่เป็นเนื้อหาของบทนี้ (หน้า 1-49) — หน้า 50-98 ของ Lecture2.pdf คือ Lecture3.pdf ทั้งชุด (สไลด์เดียวกันเป๊ะ) ดูภาคผนวกของ Lesson 3 แทน.

หน้าเนื้อหาสถานะ
1ปก Part 1-Neural Network: Deep Learning (รหัสวิชา เวลาเรียน)etc — สไลด์ปก/ข้อมูลบริหารวิชา ไม่มีเนื้อหาวิชาการ
2Complex Non-linear Tasks — spiral dataset, polynomial ระเบิดเป็น 5,150 features✓ หัวข้อ 1 (รูป + คำนวณจำนวนเทอมเต็ม)
3Computer Vision Tasks — 28×28 ขาวดำ/RGB นับ feature✓ หัวข้อ 1 (รูป + คำนวณ 784 / 2,352)
4–7ANNs (computation, biological brain, universal models), From Biological to Artificial NN (6 layers), Neural Network Intuition (dense layer, housing price), Why Can NN Model Complex Patterns (5 เหตุผล)✓ หัวข้อ 1A (รูปครบทุกหน้า + กล่องต้องรู้ก่อนเรื่อง nonlinearity)
8–10Brief History of ANNs 1–3: McCulloch & Pitts (1943), Perceptron/TLU (1957), MLP แก้ XOR (1969)✓ หัวข้อ 2 (รูปครบ + คำนวณ XOR ทั้ง 4 กรณี)
11–13Neural Network Structure (หน้าที่ของ 3 layer), Notation (layer/node), Notation 2 (bias unit, activation function g, weight)✓ หัวข้อ 3 (รูปครบ + ตารางสัญกรณ์ + คำนวณขนาด θ)
14Small Neural Network — linear/logistic regression เป็น NN node เดียว✓ หัวข้อ 3A (รูป + ตัวอย่างตัวเลขเทียบสอง activation)
15–18Example on Computational Logic (ตรรกศาสตร์/ประพจน์ + truth table), Logic Operator AND, OR, NOT✓ หัวข้อ 4 (รูปครบ + เฉลยช่องว่างของ OR และ NOT)
19Vectorization — นิยาม element-wise + โค้ดเทียบเวลา for loop กับ numpy✓ หัวข้อ 5 (รูป + โค้ดอธิบายทีละบรรทัด)
20–26Linear Algebra, Vector (magnitude/direction), Vector Operations, Properties, Geometric Interpretation (norm/unit vector), Exercise (Euclidean distance), The Dot Product + โค้ด✓ หัวข้อ 5A (รูปครบ + เฉลยแบบฝึกหัดหน้า 24, 25, 26)
27–37Matrix, Example (indexing), Matrix Operations (บวก/ลบ), Scalar multiplication, Matrix-vector, Example, Matrix-matrix, Example + โค้ด, Multiplication Properties, Transpose + โค้ด, Identity Matrix✓ หัวข้อ 5B (รูปครบทุกหน้า + เฉลยโจทย์ที่เว้นว่างทั้งหมด)
38–44Vectorization for Linear Regression (one example / >one example), Example, From For Loop to Vectorization (ราคาบ้าน + โค้ดในภาพ), โค้ด cost/gradient descent สองเวอร์ชัน, Exercise L1/L2✓ หัวข้อ 6 (รูปครบ + โค้ด 4 บล็อกพร้อมเฉลย L1/L2)
45–47Shallow Neural Network (diagram เต็ม), XNOR using AND OR NOT (truth table), XNOR (2) — θ ของสาม gate✓ หัวข้อ 7 (รูปครบ + forward ของ XNOR ทั้ง 4 กรณี)
48–49Forward Computation (โจทย์เว้นว่าง) และ Forward Computation (Solution)✓ หัวข้อ 8 (รูปครบ + ตัวอย่างคำนวณเต็มด้วยตัวเลขจริง)

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