ການແກ້ໄຂບັນຫາ Exploding ແລະ Vanishing Gradients ໃນ Neural Networks
ບັນຫາ Exploding ແລະ Vanishing Gradients ໃນ Deep Neural Networks
ໃນຍຸກທີ່ປັນຍາປະດິດມີບົດບາດສຳຄັນໃນການແກ້ໄຂບັນຫາລະດັບຊາດ—ຕັ້ງແຕ່ການພັດທະນາລະບົບ [Recurrent Neural Networks (RNNs)] ເພື່ອພະຍາກອນລະດັບນ້ຳຂອງໃນຊ່ວງລະດູຝົນ, ຈົນເຖິງການໃຊ້ Computer Vision ວິເຄາະສະພາບການຈະລາຈອນທີ່ຕິດຂັດຢູ່ແຍກໄຟແດງດົງໂດກ—ພວກເຮົາຈຳເປັນຕ້ອງສ້າງໂມເດວທີ່ມີຄວາມເລິກ (Deep) ຂຶ້ນເພື່ອຈັບເອົາຮູບແບບ (Patterns) ທີ່ຊັບຊ້ອນ.
ແຕ່ການເພີ່ມຈຳນວນຊັ້ນ (Hidden Layers) ເຂົ້າໄປໃນ Network ກໍນຳມາເຊິ່ງບັນຫາ Optimization ທາງຄະນິດສາດທີ່ຮ້າຍແຮງສອງຢ່າງຄື: Vanishing Gradients (ຂໍ້ມູນຄວາມຊັນຈາງຫາຍໄປ) ແລະ Exploding Gradients (ຂໍ້ມູນຄວາມຊັນເພີ່ມຂຶ້ນຈົນລະເບີດ). ໃນບົດຄວາມນີ້, ເຮົາຈະມາເຈາະລິກເຖິງພື້ນຖານທາງຄະນິດສາດຂອງບັນຫານີ້ ແລະ ວິທີທາງແກ້ໄຂໃນລະດັບ Advanced Architecture.
ຕົ້ນຕໍຂອງບັນຫາ: The Chain Rule ໃນ Backpropagation
ໃນການຝຶກອົບຮົມ (Training) Neural Network, ເຮົາໃຊ້ Algorithm ທີ່ເອີ້ນວ່າ Backpropagation. ຖ້າເຮົາມີ Network ທີ່ມີຄວາມເລິກ ຊັ້ນ, Gradient ຂອງ Loss Function () ທຽບໃສ່ Weight ໃນຊັ້ນທຳອິດ () ຈະຖືກຄຳນວນໂດຍການຄູນຕ່ອງໂສ້ (Chain Rule) ຜ່ານການຫາອະນຸພັນ (Derivatives) ຂອງແຕ່ລະຊັ້ນ:
ລອງຈິນຕະນາການເຖິງການສົ່ງສືບຕໍ່ຂໍ້ຄວາມລຽບຕາມສາຍນ້ຳຂອງ ຈາກແຂວງຜົ້ງສາລີ ລົງໄປຮອດ ຈຳປາສັກ.
- Vanishing Gradient: ຖ້າທຸກຄົນທີ່ຮັບສານ ເວົ້າຄ່ອຍລົງ 10% (< 1), ພໍໄປຮອດຈຳປາສັກ, ສຽງນັ້ນຈະເບົາຈົນບໍ່ໄດ້ຍິນຫຍັງເລີຍ. ຄ່າ Gradients ທີ່ເຂົ້າໃກ້ 0 ເຮັດໃຫ້ Weights ໃນຊັ້ນທຳອິດບໍ່ຖືກປັບປຸງ.
- Exploding Gradient: ໃນທາງກົງກັນຂ້າມ, ຖ້າທຸກຄົນຕື່ມສຽງດັງຂຶ້ນ 10% (> 1), ສຽງຈະດັງກ້ອງຈົນກາຍເປັນສຽງລົບກວນ (Noise). ຄ່າ Gradients ຈະເພີ່ມຂຶ້ນແບບ Exponential, ເຮັດໃຫ້ Weights ປ່ຽນແປງໄວເກີນໄປຈົນຫຼຸດອອກຈາກຄ່າທີ່ເໝາະສົມ (Diverge) ແລະ ສົ່ງຄ່າເປັນ
NaNໃນທີ່ສຸດ.
ວິທີແກ້ໄຂທາງສະຖາປັດຕະຍະກຳ (Architectural Solutions)
1. ການເລືອກ Activation Function ທີ່ເໝາະສົມ
ການໃຊ້ Sigmoid ຫຼື Tanh ເປັນສາເຫດຫຼັກຂອງ Vanishing Gradient ເພາະຄ່າອະນຸພັນສູງສຸດຂອງ Sigmoid ແມ່ນພຽງແຕ່ . ເມື່ອເອົາ ມາຄູນກັນຫຼາຍຊັ້ນ, ມັນຈະເຂົ້າໃກ້ສູນທັນທີ.
ວິທີແກ້: ປ່ຽນມາໃຊ້ ReLU (Rectified Linear Unit) ຫຼື Leaky ReLU ໃນ Hidden Layers. ອະນຸພັນຂອງ ReLU ມີຄ່າເປັນ ສຳລັບ , ໝາຍຄວາມວ່າ Gradients ສາມາດຖືກສົ່ງກັບຄືນໄປໄດ້ໂດຍບໍ່ຖືກບີບອັດໃຫ້ຫຼຸດລົງ.
2. Weight Initialization (He ແລະ Xavier)
ການກຳນົດຄ່າເລີ່ມຕົ້ນ (Initialization) ເບບສຸ່ມທົ່ວໄປ (Random Normal) ອາດເຮັດໃຫ້ Variance ຂອງ Output ເພີ່ມຂຶ້ນ ຫຼື ຫຼຸດລົງໃນແຕ່ລະຊັ້ນ. ເພື່ອແກ້ບັນຫານີ້, ທາງຄະນິດສາດແນະນຳໃຫ້ Variance ຂອງ Input ແລະ Output ເທົ່າກັນ.
- Xavier (Glorot) Initialization: ເໝາະສຳລັບ Tanh/Sigmoid.
- He (Kaiming) Initialization: ເໝາະສຳລັບ ReLU ຊຶ່ງຈະຊົດເຊີຍການທີ່ ReLU ຕັດຄ່າລົບຖິ້ມໄປເຄິ່ງໜຶ່ງ.
3. Gradient Clipping (ການຕັດຂອບຄວາມຊັນ)
ສຳລັບບັນຫາ Exploding Gradients (ທີ່ພົບເຫັນເລື້ອຍໃນການຝຶກ Deep LSTMs ສຳລັບແປພາສາລາວ-ອັງກິດ), ວິທີແກ້ໄຂທີ່ກົງໄປກົງມາທີ່ສຸດຄືການກຳນົດເພດານ Gradient (Threshold) ເພື່ອບໍ່ໃຫ້ມັນເກີນຄ່າທີ່ກຳນົດ.
4. Skip Connections (ResNets)
ໃນໂມເດວ Computer Vision ຂະໜາດໃຫຍ່, Architecture ແບບ Residual Networks (ResNets) ໄດ້ເພີ່ມ “ທາງລັດ” (Skip Connections) ໃຫ້ຂໍ້ມູນ. ຊຶ່ງເຮັດໃຫ້ Gradient ສາມາດຂ້າມຊັ້ນ Weight ແລະ ກັບຄືນສູ່ຊັ້ນເລີ່ມຕົ້ນໄດ້ໂດຍກົງຜ່ານ Operation ແບບການບວກ: .
ຕົວຢ່າງການຈັດການດ້ວຍ PyTorch ໃນພາກປະຕິບັດ
ຂ້າງລຸ່ມນີ້ຄືຕົວຢ່າງ Code ສຳລັບການສ້າງໂມເດວພະຍາກອນຄ່າຝຸ່ນ PM2.5 ທີ່ນະຄອນຫຼວງວຽງຈັນ ໂດຍໃຊ້ Deep Feedforward Network, ພ້ອມທັງສາທິດການໃຊ້ He Initialization ແລະ Gradient Clipping.
import torch
import torch.nn as nn
import torch.optim as optim
class VteAirQualityPredictor(nn.Module):
def __init__(self, input_size, hidden_size):
super(VteAirQualityPredictor, self).__init__()
# ສ້າງ Deep Network ດ້ວຍ 3 Hidden Layers
self.net = nn.Sequential(
nn.Linear(input_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, 1)
)
self._init_weights()
def _init_weights(self):
# ໃຊ້ Kaiming (He) Initialization ສຳລັບທຸກໆ Linear 层ທີ່ຕາມດ້ວຍ ReLU
for m in self.modules():
if isinstance(m, nn.Linear):
nn.init.kaiming_normal_(m.weight, mode='fan_in', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
def forward(self, x):
return self.net(x)
# ຕົວຢ່າງການກຳນົດ Training Loop ເພື່ອປ້ອງກັນ Exploding Gradients
input_feature_dim = 15 # ຕົວແປທາງສະພາບອາກາດ ເຊັ່ນ: ອຸນຫະພູມ, ຄວາມຊຸ່ມ, ແຮງລົມ...
model = VteAirQualityPredictor(input_size=input_feature_dim, hidden_size=256)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.MSELoss()
# ສົມມຸດວ່າ inputs ແລະ targets ແມ່ນຂໍ້ມູນ Tensors ຈາກແຫຼ່ງອ້າງອີງ
inputs = torch.randn(32, input_feature_dim)
targets = torch.randn(32, 1)
# --- ຂັ້ນຕອນ Training 1 Step ---
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, targets)
# 1. Calculate gradients (Backpropagation)
loss.backward()
# 2. Gradient Clipping ຢູ່ທີ່ຄ່າ Norm = 1.0 ເພື່ອຢຸດ Exploding Gradients
nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
# 3. Update weights
optimizer.step()
print(f"Step Loss: {loss.item():.4f}")
ຈຸດສຳຄັນທີ່ຄວນຈື່ (Key Takeaways)
- Vanishing Gradients: ເຮັດໃຫ້ໂມເດວຮຽນຮູ້ຊ້າ ຫຼື ບໍ່ຮຽນຮູ້ເລີຍ, ແກ້ໄຂໄດ້ດ້ວຍການໃຊ້ Activation Function ປະເພດ ReLU ແລະ ການ Initialise Weights ແບບ He/Xavier.
- Exploding Gradients: ເຮັດໃຫ້ Loss ກາຍເປັນ
NaN, ສາມາດປ້ອງກັນໄດ້ໄວທີ່ສຸດໂດຍການໃຊ້ຍຸດທະວິທີGradient Clippingໃນລະຫວ່າງ Backpropagation. - Architecture Matters: ຖ້າຕ້ອງການ Train Network ທີ່ເລິກຫຼາຍຂຶ້ນສຳລັບຂໍ້ມູນທີ່ຊັບຊ້ອນໃນປະເທດລາວ ເຊັ່ນ ການວິເຄາະຮູບພາບດາວທຽມຂອງພື້ນທີ່ປູກກາເຟຢູ່ປາກຊ່ອງ, ການຫັນໄປໃຊ້ Residual Networks (ResNet) ຫຼື ການໃຊ້ Batch Normalization ຖືເປັນສິ່ງຈຳເປັນທີ່ຂາດບໍ່ໄດ້.
ສະຫຼຸບ
ການເຂົ້າໃຈຫຼັກການທາງຄະນິດສາດ ແລະ ສັງເກດເບິ່ງພຶດຕິກຳຂອງ Loss function ເປັນທັກສະທີ່ສຳຄັນທີ່ສຸດສຳລັບ AI Engineer. ບັນຫາ Exploding ແລະ Vanishing Gradients ບໍ່ແມ່ນກຳແພງທີ່ຂ້າມຜ່ານບໍ່ໄດ້ອີກຕໍ່ໄປ ຂໍພຽງແຕ່ເຮົາຮູ້ຈັກເລືອກໃຊ້ພື້ນຖານ Activation Functions ທີ່ເໝາະສົມ, ການຕັ້ງຄ່າ Weight Initialization, ແລະ ການໃຊ້ເຕັກນິກ Clipping. ເຄື່ອງມືເຫຼົ່ານີ້ຈະຊ່ວຍໃຫ້ການພັດທະນາໂມເດວ Deep Learning ເພື່ອມາຮັບໃຊ້ບໍລິບົດຂອງສັງຄົມລາວນັ້ນ ມີຄວາມສະຖຽນລະພາບ ແລະ ແມ້ນຢຳກວ່າເດີມ.