กลับไปหน้ารวมไฟล์
neural-network-backpropagation-7d9fc0.md

ชื่อโปรเจกต์: Neural Network Backpropagation (ฉบับรุ่นพี่สอนน้อง)

Backpropagation: มาดูหัวใจของงานนี้กันน้อง Backpropagation คือโครงข่ายแบบ Feedforward ที่ไม่มีการป้อนกลับซ้อนทับกันวุ่นวาย แต่มันจะใช้ค่าความผิดพลาด (Errors) ระหว่างการ Training มาคำนวณเพื่อลดค่า Squared error ระหว่างค่า Output กับค่า Target ที่เราตั้งไว้ให้เหลือน้อยที่สุด โดย Error ที่เกิดขึ้นตรง Output จะเป็นตัวสะท้อนกลับไปบอกว่า Hidden layer ทำพลาดไปเท่าไหร่ เพื่อเอาไปปรับค่า Connection Weights ระหว่าง Input layer และ Hidden layer ต่อไป การปรับ Weights ทั้งสองชุดและการคำนวณ Output ใหม่เนี่ยมันเป็นกระบวนการทำซ้ำ (Iterative process) ที่ต้องปั่นไปเรื่อยๆ จนกว่า Error จะต่ำลงจนเราพอใจ (Tolerance level) นอกจากนี้เรายังมีตัวแปร Learning rate มาคอยคุมระยะการปรับ Weights และมี Momentum มาช่วยเร่งหรือประคองการปรับค่าจากการรันรอบที่แล้วมาบวกเพิ่มในรอบปัจจุบันด้วย สรุปสั้นๆ คือมันสร้างแผนผังจาก Input vectors ไปหา Output vectors นั่นแหละ พอเราเทรนจน Weights มันนิ่งแล้ว ทีนี้จะใส่ Input ใหม่เข้าไป มันก็คำนวณหาคำตอบให้เราได้หล่อๆ เลย ส่วนจำนวน Neurons ในแต่ละ Layer ก็ขึ้นอยู่กับมิติของ Input และ Output ที่เราใช้นะ ส่วนโครงสร้างหลักๆ ก็มี Input units, Hidden units และ Output units เชื่อมกันด้วย Weights ตามสูตรเลยวัยรุ่น

Training: การเทรนเจ้า Backpropagation ตัวนี้เป็นแบบ Supervised training (แบบมีคนสอน) โดยเราต้องเตรียม Input กับ Output ที่อยากได้ไว้ให้มัน พอเราป้อน Input เข้าไปที่ Input layer ปุ๊บ Neurons ตรงนี้จะส่งค่าไปให้ Hidden layer ต่อ ซึ่งใน Hidden layer จะมีการใช้ Bias และ Threshold function มาช่วยคำนวณร่วมกับ Weights และ Input จนได้ Output ของ Hidden layer ออกมา แล้วไอ้ค่าพวกนี้แหละที่จะกลายเป็น Input ของ Output neurons ต่อไป พอคำนวณเสร็จจนได้ค่าสุดท้ายของโครงข่าย เราก็เอามาเทียบกับค่าที่เราอยากได้ (Desired output) เพื่อดูว่า Error เยอะไหม จากนั้นก็ทำการปรับ Weights ระหว่าง Hidden กับ Output layer และทำแบบเดียวกันย้อนกลับไปที่ Input กับ Hidden layer ด้วย กระบวนการวนลูปแบบนี้จนครบทุกชุดข้อมูลเราเรียกว่าหนึ่ง Cycle หรือหนึ่ง EPOCH ทำวนไปจนกว่า Error จะเหลือนิดเดียวตามที่เรากำหนดไว้ สู้งานหน่อยนะน้อง!

----------------------------------------------------------------------------------

การปรับ Weights ของการเชื่อมต่อจาก Neuron ใน Hidden Layer

----------------------------------------------------------------------------------

input pattern: \t[ 1.1, 2.4, 3.2, 5.1, 3.9 ]

target output: \t[ 0.52, 0.25, 0.75, 0.97 ]

ค่า Weights สำหรับ Neuron ตัวที่สองใน Hidden layer คือ:

[ –0.33, 0.07, –0.45, 0.13, 0.37 ]

ค่า Activation ที่ได้คือ:

(−0.33 * 1.1) + (0.07 * 2.4) + (−0.45 * 3.2) + (0.13 * 5.1) + (0.37 * 3.9) = 0.471

บวกค่า Bias เข้าไปสัก 0.679 จะได้ 1.15 ทีนี้ถ้าเราใช้ Sigmoid function ตามสูตรนี้:

1 / ( 1+ exp(−x)), โดยที่ x = 1.15, เราจะได้ Output ของ Hidden layer neuron ตัวนี้เท่ากับ: 0.7595

----------------------------------------------------------------------------------

มาดูค่า Output pattern ที่คำนวณได้กันบ้าง

actual: \t[ 0.61, 0.41, 0.57, 0.53 ]

desired:\t[ 0.52, 0.25, 0.75, 0.97 ]

ส่วนต่างของแต่ละตัว (Desired − Actual) จะได้ตามนี้:

[ −0.09, −0.16, 0.18, 0.44 ]

เราเอาค่าพวกนี้มาสร้าง Vector ใหม่ โดยแต่ละตัวเกิดจาก Error คูณกับค่าที่คำนวณได้ และคูณกับส่วนเติมเต็มของมัน (1 - Actual):

error-vector:\t

[ (1 - 0.61), (1 - 0.41), (1 - 0.57), (1 - 0.53) ] =>\t

[ 0.39, 0.59, 0.43, 0.47 ] =>\t

[ (0.61 * 0.39 * −0.09), (0.41 * 0.59 * −0.16), (0.57 * 0.43 * 0.18), (0.53 * 0.47 * 0.44) ] =>

output:\t\t

[ -0.02, -0.04, 0.04, 0.11 ]

ไอ้เจ้า Vector (Desired–Actual) ที่คูณกับ Actual output ตัวนี้จะบอกค่า Error ที่สะท้อนกลับไปหา Hidden layer ซึ่งจะถูกสเกลด้วยค่า (1 − output vector) เพื่อความเสถียรในการคำนวณ (First derivative) ต่อไปเราต้องใช้ Weights ระหว่าง Neuron ตัวที่สองใน Hidden layer กับ Output neurons ตัวต่างๆ ซึ่งมีค่าดังนี้:

[ 0.85, 0.62, –0.10, 0.21 ]

ค่า Error ของ Neuron ตัวที่สองใน Hidden layer คำนวณได้แบบนี้:

error:\t

0.7595 * (1 − 0.7595) * ((0.85 * −0.02) + (0.62 * −0.04) + ( −0.10 * 0.04) + (0.21 * 0.11)) = −0.0041

ย้ำอีกที เราเอา Error (-0.02) จาก Output layer คูณกับค่า Output (0.7595) และ (1 − 0.7595) โดยใช้ Weights เป็นตัวเชื่อมเพื่อย้อนกลับไปในระบบ ทีนี้กำหนด Learning rate ให้เลเยอร์นี้หน่อย:

ลองตั้งเป็น: 0.2

learning rate:\t 0.7595 * 0.2 = 0.1519

เอาค่านี้ไปคูณกับแต่ละคอมโพเนนต์ของ Output จาก Neuron ตัวที่สองใน Hidden layer:

vector:

[ –0.02, –0.04, 0.04, 0.11] 

[ –0.02, –0.04, 0.04, 0.11]

[ (–0.003 * 0.1519), (–0.006 * 0.1519), (0.006 * 0.1519), (0.017 * 0.1519)]

ผลที่ได้คือ Vector สำหรับปรับค่า Weights ที่ลากจาก Hidden neuron ตัวที่สองไปหา Output neurons นั่นเอง

[ –0.003, –0.006, 0.006, 0.017 ]

[ (0.85 + –0.003), (0.62 + –0.006), (–0.10 + 0.006), (0.21 + 0.017) ]

พอปรับเสร็จ Weights ที่จะเอาไปใช้ในรอบหน้า (Cycle) ก็จะเป็นค่าตามนี้:

[ 0.847, 0.614, –0.094, 0.227 ]

----------------------------------------------------------------------------------

การปรับ Weights ของการเชื่อมต่อจาก Neuron ใน Input Layer

----------------------------------------------------------------------------------

ถ้าจะหาค่าปรับ Weights ระหว่าง Input และ Hidden layers เราต้องใช้ Error ของ Hidden layer neurons, Learning rate และค่า Activation ของ Input neurons (ซึ่งก็คือค่า Input ที่เราป้อนเข้าไปนั่นแหละน้อง)

learning rate: 

0.15\t[ (0.15 * 1.1 * −0.0041),

(0.15 * 2.4 * −0.0041),

(0.15 * 3.2 * −0.0041),

(0.15 * 5.1 * −0.0041),

(0.15 * 3.9 * −0.0041) ]

[ -0.001, -0.001, –0.002, -0.003, -0.002 ]

[ (–0.33 + -0.001), (0.07 + -0.001),

(–0.45 + –0.002), (0.13 + -0.003), (0.37 + -0.002) ]



weight adjustments:\t\t

[ -0.331, 0.069, -0.452, 0.127, 0.368 ]

----------------------------------------------------------------------------------\t

การปรับค่า Threshold หรือ Bias

---------------------------------------------------------------------------------\t

การปรับ Threshold ของ Neuron ใน Output layer ก็แค่เอา Error ที่คำนวณได้คูณกับ Learning rate ของเลเยอร์นั้นๆ สำหรับ Output neurons ทั้ง 4 ตัวจะได้ค่าปรับตามนี้:

[ error vector\t] * [ learning rate ]\t[ –0.02, –0.04, 0.04, 0.11 ] * [ 0.2 ] =>\t\t

[ –0.004, –0.008, 0.008, 0.022 ]

เอาไปบวกกับ Threshold เดิมได้เลย ส่วนของ Hidden layer ก็ทำเหมือนกัน คือเอา Learning rate คูณกับ Error ที่คำนวณได้ของ Hidden neuron ตัวนั้น อย่างตัวที่สองของเราเนี่ย ก็จะได้ 0.15 * –0.0041 ซึ่งเท่ากับ –0.0006

0.15 * –0.0041 = –0.0006\t\t

บวกเข้าไปกับ Threshold เดิม 0.679 จะได้ค่าใหม่คือ 0.6784 เอาไว้ใช้เทรนในรอบต่อไป หล่อเท่เลยงานนี้!

0.679 + –0.0006 = 0.6784

Image Processing (การประมวลผลภาพ):\t

บอกเลยว่า Image processing คือการใช้เครื่องมือหรือเทคนิคมาวิเคราะห์เงา สี และความสัมพันธ์ในภาพที่ตาเปล่าอาจจะมองไม่เห็น หรือเอามาปรับปรุงภาพเพื่อแก้ปัญหาการระบุตัวตน เช่น นิติเวช, การติดตามใบหน้า (Facial tracking) หรือการทำแผนที่อากาศจากดาวเทียม ซึ่งส่วนใหญ่ก็มาในรูปแบบ Bitmap จากกล้องดิจิทัลนั่นแหละ

Face Detection (การตรวจจับใบหน้า):\t

หน้าที่หลักคือหาว่ามี "หน้าคน" ในรูปไหม และถ้ามี มันอยู่ตรงไหน การระบุพิกัดใบหน้าเป็นพื้นฐานสำคัญของการทำ Face recognition หรือวิเคราะห์อารมณ์เลยนะ ระบบต้องจับภาพจากกล้องมา Process แล้วหาฟีเจอร์สำคัญเพื่อระบุตำแหน่ง ซึ่งอัลกอริทึมยอดฮิตก็คือการใช้ "สีผิว" (Skin color) เพราะมันเร็วกว่าการหาฟีเจอร์อื่นเยอะ แถมในสภาพแสงบางอย่าง สีผิวมันค่อนข้างคงที่ ทำให้การทำ Motion estimation ง่ายขึ้นเยอะ แต่ก็นะน้อง สีมันไม่ใช่ปรากฏการณ์ทางกายภาพโดยตรง แต่มันอยู่ที่การรับรู้ของเรตินาเราด้วย การใช้สีผิวเลยมีปัญหาบ้าง เช่น แสงเปลี่ยน หรือกล้องต่างรุ่นกันก็ให้ค่าสีไม่เหมือนกัน วิธีแก้ปัญหาเรื่องความสว่างคือการแปลงจาก RGB ไปเป็นพื้นที่สีอื่นที่แยกค่าความสว่าง (Luminance) กับค่าสี (Chromaticity) ออกจากกัน ซึ่งในโปรเจกต์นี้พี่จัดเต็ม เปรียบเทียบอัลกอริทึมดังๆ 3 ตัว และเสนอตัวใหม่ที่ใช้ RGB ร่วมกับ YCbCr ไปเลย

RGB MODEL:\t

RGB ประกอบด้วยแม่สีหลักคือ แดง เขียว น้ำเงิน ผสมกันจนได้สีต่างๆ ดำคือ 0 (ไม่มีสี) ขาวคือ 255 (จัดเต็มทุกสี) ส่วนเทาก็อยู่ตามเส้นตรงระหว่างขาวดำนั่นแหละ ระบบ 24-bit ทั่วไปก็คือ 8-bit ต่อช่องสี รุ่นพี่บอกเลยว่า RGB ออกแบบมาเพื่อกราฟิกคอมพิวเตอร์ แต่มันไม่ได้เทพทุกงาน เพราะค่าสีมันสัมพันธ์กันเกินไปจนทำให้ Image processing บางอย่างทำยาก

YCbCr MODEL:\t

ตัวนี้เกิดมาเพื่อวิดีโอดิจิทัลโดยเฉพาะ อยู่ตระกูลเดียวกับ YUV และ YIQ นั่นแหละ YCbCr จะแยก RGB ออกเป็นค่าความสว่าง (Y) และค่าสี (Cb, Cr) ซึ่งมีประโยชน์มากในการบีบอัดข้อมูล ตามมาตรฐาน 601 ค่า Y จะอยู่ช่วง 16 (ดำ) ถึง 235 (ขาว) เพื่อเผื่อพื้นที่ไว้กันสัญญาณพีด (Signal processing room) ส่วน Cb และ Cr จะอยู่ช่วง 16 ถึง 240

Face detection based on skin color using RGB color space:\t

หนึ่งในวิธีที่ง่ายที่สุดคือการใช้ Skin color algorithm ตรวจจับพิกเซลสีผิว โดยแปลง [R, G, B] เป็น [r, g] แบบ Normalized เพื่อตัดปัญหาเรื่องความสว่าง วิธีนี้ตรวจจับหน้าได้เร็ว แต่จะหลุด (Fail) ทันทีถ้าในภาพมี แขน หรือ ขา โผล่เข้ามาด้วย เพราะมันก็มองว่าเป็นสีผิวเหมือนกันน่ะสิ!

Face detection based on skin color using YCbCr color space:\t

เราใช้อัลกอริทึมจำแนกสีผิวจากสถิติใน YCbCr เพราะพิกเซลที่เป็นผิวคนจะมีค่า Cb และ Cr ใกล้เคียงกันมาก ไม่ว่าจะเป็นคนชนชาติไหนก็ตาม ถ้าค่า [Cr, Cb] ตกอยู่ในช่วง Threshold ที่เราตั้งไว้ ก็ถือว่าเป็นผิวคนแน่นอน แต่อัลกอริทึมนี้ก็ยังมีข้อจำกัด คือในภาพต้องเน้นไปที่ใบหน้าเป็นหลักนะ

Eye detection Illumination-based Method:\t

พอได้ส่วนที่เป็นหน้ามาแล้ว เราจะหาตาโดยใช้ Eye map สองชุด ชุดแรกคือ Chrominance eye map เพราะรอบดวงตาจะมีค่า Cb สูง และ Cr ต่ำ คำนวณได้จาก:

EyeMapC = 1/3 { (Cr)² + (Cb)² + (Cb/Cr) } 

ส่วนอีกตัวคือ Luminance component ที่ใช้เทคนิคทาง Morphological (Erosion และ Dilation) เพื่อเน้นจุดที่สว่างและมืดรอบๆ ดวงตา:

EyeMapL = Dilation Y(x, y) / Erosion Y(x, y)

Mouth detection:\t

การหาปากก็คล้ายๆ กัน ปากจะมีสีแดงชัดและสีน้ำเงินน้อย (Cr > Cb) เราเลยใช้สูตร MouthMap ที่เน้นค่า Cr2 และใช้ Morphological operators มาช่วยเสริมเหมือนเดิม

BPNN Backpropagation Neural Network with heuristic rule: โมเดลนี้ใช้ Neural Network (BP ANN) ร่วมกับกฎ Heuristic บน YCbCr เพื่อเพิ่มความแม่นยำในสภาพแสงที่ต่างกัน พี่เทรนด้วยภาพขนาด 60x60 (3600 พิกเซล) ที่มีโทนสีผิวหลากหลาย โดยแปลง RGB เป็น YCbCr ก่อน แล้วใช้ข้อมูลนั้นเทรน Neural network แบบ 3 เลเยอร์ เพื่อแยกแยะว่าพิกเซลไหนคือผิว พิกเซลไหนไม่ใช่ โดยอิงจากเงื่อนไขนี้:

(132 < Cr > 173) ^ (76 < Cb > 126)







รายละเอียดทางเทคนิคเพิ่มเติม (หล่อๆ เลยน้อง)

Embedded Machine Learning Engine

นี่คือโปรเจกต์ระดับแอดวานซ์ที่ยัดเอา "Neural Network" พื้นฐานพร้อมการเทรนแบบ Backpropagation ลงไปรันบนหน่วยประมวลผลของ Arduino โดยตรง!

  • Multi-Layer Perceptron (MLP) Architecture: บอร์ด Arduino ของเราจะจัดการโครงสร้างตรรกะของ "Neurons" ที่เรียงกันเป็น Input, Hidden, และ Output layers โดยตัว Firmware จะใช้การคำนวณเลขทศนิยม (Floating-point math) เพื่อหาค่า "Weights" และ "Biases" ระหว่างการเรียนรู้
  • On-Chip Training Cycle: โชว์ให้เห็นเลยว่า Arduino ก็ "เรียนรู้" ได้นะเว้ย! มันสามารถแก้ปัญหาตรรกะง่ายๆ (อย่าง XOR gate) ได้ด้วยการปรับ Weights ภายในตัวเองผ่านการคำนวณ Backpropagation วนไปเรื่อยๆ

Performance

  • Visual Studio 2017 Optimized: ชุดคำนวณคณิตศาสตร์โหดๆ พวกนี้ถูกพัฒนาและ Debug ใน Visual Studio มาอย่างดี เพื่อให้มั่นใจว่าโค้ด C++ จะทำงานได้มีประสิทธิภาพสูงสุด และยัดลงไปใน RAM อันน้อยนิดของ Arduino ได้พอดีเป๊ะ ห้ามช็อตนะตัวนี้!

ข้อมูล Frontmatter ดั้งเดิม

title: "Neural Network Backpropagation"
description: "The feedforward backpropagation network is a neural model that minimize the squared error between the output and target values."
author: "vicentezavala"
category: ""
tags:
  - "artificial intelligence"
views: 1071
likes: 0
price: 699
difficulty: "Intermediate"
components: []
tools: []
apps:
  - "1x Visual Studio 2017"
downloadableFiles: []
documentationLinks: []
passwordHash: "4e06e2382dbd0bdd2b14fe663702f5ea273a660162f29407295f6d3731c21670"
encryptedPayload: "U2FsdGVkX1/0UZRjbFyYPiZs8SVeTGOalv/c5XiqVAFK3AVGipBYpv4CyiGL95DieXhppB9Dr1Mbrk9aUv1aEyC7K2v+9njG1ZKmdkvkKIA="
seoDescription: "Learn Neural Network Backpropagation: A Feedforward Neural Model designed to minimize squared error between output and target values."
videoLinks:
  - "https://www.youtube.com/embed/Z7NiAu-O00I"
heroImage: "https://cdn.jsdelivr.net/gh/bigboxthailand/arduino-assets@main/images/projects/neural-network-backpropagation-7d9fc0_cover.jpg"
lang: "th"