ຄະນິດສາດທີ່ຢູ່ເບື້ອງຫຼັງ Backpropagation
ຄະນິດສາດທີ່ຢູ່ເບື້ອງຫຼັງ Backpropagation: ເຈາະເລິກ Calculus ທີ່ເຮັດໃຫ້ Neural Networks ຮຽນຮູ້ໄດ້
ສຳລັບນັກພັດທະນາ ແລະ ນັກຄົ້ນຄວ້າ AI ທີ່ເຄີຍສ້າງ Neural Networks (NN) ດ້ວຍ PyTorch ຫຼື TensorFlow, ທ່ານຄົງຈະຄຸ້ນເຄີຍກັບການໃຊ້ຄຳສັ່ງງ່າຍໆເຊັ່ນ loss.backward() ທີ່ເຮັດທຸກຢ່າງໃຫ້ແບບອັດຕະໂນມັດ. ເບື້ອງໜ້າອາດເບິ່ງຄືເວດມົນ, ແຕ່ພາຍໃຕ້ຄຳສັ່ງດຽວນັ້ນ ມີສົມຜົນຄະນິດສາດຂັ້ນສູງທີ່ກຳລັງເຮັດວຽກຢູ່. ໃນບົດຄວາມນີ້, ເຮົາຈະມາເຈາະເລິກເຖິງພື້ນຖານຂອງ Calculus (ແຄລຄູລັສ) ແລະ Linear Algebra ທີ່ເປັນຫົວໃຈສຳຄັນຂອງ Backpropagation.
ເພື່ອໃຫ້ເຫັນພາບທີ່ຊັດເຈນສະພາບການຕົວຈິງໃນບ້ານເຮົາ, ເຮົາຈະໃຊ້ຕົວແບບ (Model) ການພະຍາກອນ ລະດັບນໍ້າຂອງຢູ່ສະຖານີວັດແທກນະຄອນຫຼວງວຽງຈັນ ເປັນກໍລະນີສຶກສາ.
ກໍລະນີສຶກສາ: ໂມເດວພະຍາກອນລະດັບນໍ້າຂອງ
ສົມມຸດເຮົາກຳລັງສ້າງ Multi-Layer Perceptron (MLP) ເພື່ອຄາດເດົາລະດັບນໍ້າຂອງ (Output ) ໃນມື້ອື່ນ ໂດຍອ້າງອີງຈາກ 2 ປັດໄຈຫຼັກຄື:
- ປະລິມານນໍ້າຝົນສະສົມຢູ່ແຂວງຜົ້ງສາລີ ແລະ ຫຼວງພະບາງ.
- ລະດັບການປ່ອຍນໍ້າຈາກເຂື່ອນຢູ່ທາງຕອນເທິງ (Inputs ).
ໂມເດວຂອງເຮົາຈະຮຽນຮູ້ໄດ້ກໍຕໍ່ເມື່ອມັນສາມາດຫຼຸດຜ່ອນ “ຄວາມຜິດພາດ” (Loss) ລະຫວ່າງຄ່າທີ່ມັນຄາດເດົາ () ແລະ ຄ່າຕົວຈິງທີ່ວັດແທກໄດ້ຈາກຄະນະກຳມາທິການແມ່ນໍ້າຂອງ (MRC).
ສົມຜົນຄະນິດສາດຂອງ Forward Propagation
ກ່ອນທີ່ຈະຍ້ອນກັບ (Backward), ເຮົາຕ້ອງຍ່າງໄປຂ້າງໜ້າ (Forward). ສຳລັບຊັ້ນ (Layer) ທີ່ ໃດໜຶ່ງ ໃນເຄືອຂ່າຍ, ສົມຜົນການຄິດໄລ່ຈະກຳນົດເປັນ:
- ຜົນບວກແບບລີເນຍ (Linear Combination):
- ການກະຕຸ້ນ (Activation):
ໂດຍທີ່ ແມ່ນ Matrix ຂອງນໍ້າໜັກ (Weights), ແມ່ນ Bias, ແລະ ກໍຄື Input ຂອງເຮົາ (ຂໍ້ມູນນໍ້າຝົນ ແລະ ການປ່ອຍນໍ້າ). ແມ່ນ Activation Function ເຊັ່ນ Sigmoid ຫຼື ReLU.
ເມື່ອມາຮອດຊັ້ນສຸດທ້າຍ (Output Layer ), ເຮົາຈະໄດ້ຄ່າພະຍາກອນ . ຈາກນັ້ນເຮົາຊອກຫາຄ່າຄວາມຜິດພາດດ້ວຍ Loss Function (ສົມມຸດໃຊ້ Mean Squared Error ສຳລັບການພະຍາກອນຕົວເລກຕໍ່ເນື່ອງ):
ຫົວໃຈຂອງ Backpropagation: ກົດລະບຽບຫຼັກການຕໍ່ເນື່ອງ (The Chain Rule)
ເປົ້າໝາຍຂອງເຮົາຄືການຊອກຫາວ່າ ຄວນປ່ຽນແປງ ແລະ ແນວໃດເພື່ອໃຫ້ຄ່າຄວາມຜິດພາດ ໜ້ອຍລົງ. ສິ່ງນີ້ໝາຍເຖິງການຊອກຫາ Partial Derivatives (ຜົນຕຳລາບາງສ່ວນ) ຄື: ແລະ .
ເນື່ອງຈາກ ຖືກສ້າງຂຶ້ນມາຈາກຟັງຊັນທີ່ຊ້ອນກັນຫຼາຍຊັ້ນ, ເຮົາຈຶ່ງຕ້ອງໃຊ້ Chain Rule ຂອງ Calculus:
ຂັ້ນຕອນການແຍກສ່ວນມີດັ່ງນີ້:
- ການປ່ຽນແປງຂອງ Loss ທຽບກັບ Output ():
- ການປ່ຽນແປງຂອງ Output ທຽບກັບ ():
ຖ້າໃຊ້ Sigmoid, ຜົນຕຳລາຂອງມັນແມ່ນ . - ກຳນົດຕົວແປຄວາມຜິດພາດ (Node Delta, ):
ເພື່ອຄວາມງ່າຍ, ເຮົາລວມ 2 ຄ່າຂ້າງເທິງເຂົ້າກັນເປັນ (ຈຸດຜິດພາດທີ່ Output node): (ໝາຍເຫດ: ແມ່ນ Hadamard product ຫຼື ການຄູນແບບ Element-wise) - ການຊອກຫາ Gradient ຂອງຊັ້ນສຸດທ້າຍ:
ການສົ່ງຜ່ານຄວາມຜິດພາດກັບຫຼັງສູ່ Hidden Layers
ສໍາລັບຊັ້ນເຊື່ອງຊ້ອນ (Hidden layer ), ເຮົາບໍ່ຮູ້ວ່າຄ່າ ຕົວຈິງຂອງມັນຄວນເປັນເທົ່າໃດ. ດັ່ງນັ້ນ, ວິທີດຽວທີ່ມັນຈະຮຽນຮູ້ໄດ້ຄື ການຮບເອົາ “ຄວາມຜິດພາດທີ່ຫຼົ່ງເຫຼືອ” (Blame) ຈາກຊັ້ນຖັດໄປ (). ນີ້ຄືຕົ້ນກຳເນີດຂອງຄຳວ່າ Backpropagation (ຍ້ອນກັບ).
ສົມຜົນສຳລັບຊອກຫາ Node Delta ໃນຊັ້ນ ແມ່ນ:
ເມື່ອໄດ້ ແລ້ວ, ເຮົາກໍສາມາດຫາ Gradients ເພື່ອອັບເດດ Weights ຂອງຊັ້ນນັ້ນຕໍ່ໄປໄດ້ເລີຍ.
ການນຳໃຊ້ເຂົ້າໃນໂມເດວພະຍາກອນນໍ້າຂອງດ້ວຍ Python & Numpy
ເພື່ອປ່ຽນຈາກຄະນິດສາດນາມມະທຳມາເປັນໂຄ້ດຕົວຈິງ, ນີ້ຄືການສ້າງລະບົບ Backpropagation ຈາກສູນລ້ວນໆໂດຍໃຊ້ພຽງ NumPy:
import numpy as np
# ຈຳລອງຂໍ້ມູນວັດແທກ (Inputs: ປະລິມານນໍ້າຝົນແຂວງຜົ້ງສາລີ, ລະດັບປ່ອຍນໍ້າເຂື່ອນ)
X = np.array([[0.8, 0.6]]) # 1 Sample ຕົວຢ່າງ, 2 Features
y = np.array([[0.75]]) # ລະດັບນໍ້າຂອງຕົວຈິງທີ່ວັດແທກໄດ້ (Normalized: 0 ຫາ 1)
# 1. ກຳນົດຄ່າເລີ່ມຕົ້ນຂອງ Weights ແລະ Biases
np.random.seed(42)
W1 = np.random.randn(3, 2) # Hidden layer ມີ 3 Nodes
b1 = np.zeros((3, 1))
W2 = np.random.randn(1, 3) # Output layer ພະຍາກອນລະດັບນໍ້າ (1 Node)
b2 = np.zeros((1, 1))
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def sigmoid_derivative(z):
s = sigmoid(z)
return s * (1 - s)
# --- 2. Forward Propagation ---
x_input = X.T # ປ່ຽນເປັນ Shape (2, 1)
z1 = np.dot(W1, x_input) + b1
a1 = sigmoid(z1)
z2 = np.dot(W2, a1) + b2
y_hat = sigmoid(z2) # ຄ່າພະຍາກອນລະດັບນໍ້າຂອງເຮົາ (a2)
# --- 3. Backpropagation ---
# ກ) ຫາຄ່າຄວາມຜິດພາດທີ່ Output Layer (Node delta ສໍາລັບ Layer 2)
delta2 = (y_hat - y) * sigmoid_derivative(z2)
# ຂ) ຫາ Gradients ຂອງ Layer 2
dW2 = np.dot(delta2, a1.T)
db2 = delta2
# ຄ) ສົ່ງຄວາມຜິດພາດກັບຫຼັງ (Backpropagate to Hidden Layer 1)
delta1 = np.dot(W2.T, delta2) * sigmoid_derivative(z1)
# ງ) ຫາ Gradients ຂອງ Layer 1
dW1 = np.dot(delta1, x_input.T)
db1 = delta1
# --- 4. Gradient Descent (ການປັບຄ່າ Weights) ---
learning_rate = 0.05
W1 -= learning_rate * dW1
b1 -= learning_rate * db1
W2 -= learning_rate * dW2
b2 -= learning_rate * db2
print(f"ຄ່າພະຍາກອນກ່ອນປັບ: {y_hat[0][0]:.4f}, ຄ່າຕົວຈິງ: {y[0][0]:.4f}")
print("ດຳເນີນການ Backpropagation ສຳເລັດ! ອັບເດດ Weights ເພື່ອລໍຖ້າການຮຽນຮູ້ຮອບຕໍ່ໄປ.")
ຂໍ້ສັງເກດສຳຄັນ (Key Takeaways)
- Chain Rule ຄືທຸກສິ່ງທຸກຢ່າງ: ຖ້າບໍ່ມີກົດລະບຽບຫຼັກການຕໍ່ເນື່ອງຂອງ Calculus, ເຮົາຈະບໍ່ສາມາດສົ່ງຄ່າຄວາມຜິດພາດຈາກປາຍທາງ (ເຊັ່ນ ລະດັບນໍ້າຂອງທີ່ພະຍາກອນຜິດ) ກັບຄືນໄປຫາຕົ້ນທາງ (ເຊັ່ນ ຕົວແປນໍ້າຝົນ).
- Matrix Multiplication: ການເຂົ້າໃຈ Linear Algebra ຊ່ວຍໃຫ້ເຮົາສາມາດຄິດໄລ່ Derivative ຂອງຫຼາຍໆ Nodes ແລະ ຫຼາຍໆ Samples ໄດ້ພາຍໃນພິບຕາດຽວ ຜ່ານ Matrix Operations ເຊິ່ງມັນເໝາະສົມທີ່ສຸດກັບການປະມວນຜົນເທິງ GPU.
- ບັນຫາ Vanishing Gradients: ໃນລະບົບຕົວຈິງຖ້າຊັ້ນ (Layer) ຂອງໂມເດວມີຄວາມເລິກຫຼາຍ, ຄ່າ Gradient ຈະຫຼຸດລົງຈົນກາຍເປັນສູນ (ໂດຍສະເພາະເມື່ອໃຊ້ Sigmoid), ເຮັດໃຫ້ໂມເດວຢຸດການຮຽນຮູ້. ນີ້ຄືເຫດຜົນທີ່ສະຖາປັດຕະຍະກຳໃໝ່ໆມັກໃຊ້ ReLU ເປັນ Activation Function ແທນ.
ສະຫຼຸບ
ເຖິງແມ່ນວ່າ Framework ຍຸກສະໄໝໃໝ່ເຊັ່ນ PyTorch ແລະ TensorFlow ຈະເຮັດໃຫ້ການຂຽນ AI ເປັນເລື່ອງງ່າຍພຽງນິ້ວສຳຜັດ, ແຕ່ການລົງເລິກເຂົ້າໃຈເຖິງສົມຜົນຄະນິດສາດ ແລະ Calculus ທີ່ຢູ່ເບື້ອງຫຼັງ Backpropagation ແມ່ນສິ່ງທີ່ແຍກ “ຜູ້ໃຊ້ເຄື່ອງມື” ອອກຈາກ “ຜູ້ສ້າງນະວັດຕະກຳ”. ສຳລັບນັກພັດທະນາໃນລາວ ການເຂົ້າໃຈເລິກເຊິ່ງໃນລະດັບ Core Math ແບບນີ້ ຈະຊ່ວຍໃຫ້ສາມາດປັບແຕ່ງ Loss Functions ສະເພາະທາງ, ແກ້ໄຂບັນຫາທີ່ກ່ຽວຂ້ອງກັບຂໍ້ຈຳກັດຂອງຂໍ້ມູນລະດັບທ້ອງຖິ່ນ ເຊັ່ນ ຂໍ້ມູນສຳມະໂນຄົວ ຫຼື ຂໍ້ມູນອຸຕຸນິຍົມວິທະຍາທີ່ມີຈຳກັດ ໃຫ້ໂມເດວຮຽນຮູ້ໄດ້ຢ່າງມີປະສິດທິຜົນສູງສຸດ. ຄວາມເຂົ້າໃຈໃນທິດສະດີທີ່ຖືກຕ້ອງ ຈະເປັນຮາກຖານອັນໜັກແໜ້ນໃນການຕໍ່ຍອດສູ່ສະຖາປັດຕະຍະກຳທີ່ຊັບຊ້ອນກວ່າໃນອະນາຄົດ.