Doctor AI

Dr. Savath Saypadith

240 ບົດຄວາມ

ການພະຍາກອນຂໍ້ມູນແບບອະນຸກົມເວລາ (Time Series Forecasting) ດ້ວຍ LSTM

ໂພສເມື່ອ # Deep Learning # Time Series Forecasting # PyTorch

ການພະຍາກອນຂໍ້ມູນແບບອະນຸກົມເວລາ (Time Series Forecasting) ດ້ວຍ LSTM

ການຄາດຄະເນອະນາຄົດແມ່ນສິ່ງທີ່ທ້າທາຍ ແຕ່ມີຄວາມຈຳເປັນຢ່າງຍິ່ງສຳລັບການວາງແຜນໃນລະດັບມະຫາພາກ. ລອງຈິນຕະນາການເຖິງ ການພະຍາກອນລະດັບນ້ຳຂອງໃນນະຄອນຫຼວງວຽງຈັນ. ລະດັບນ້ຳໃນມື້ນີ້ ບໍ່ໄດ້ຂຶ້ນຢູ່ກັບປະລິມານນ້ຳຝົນຂອງມື້ວານນີ້ພຽງຢ່າງດຽວ, ແຕ່ມັນຍັງມີຄວາມສຳພັນທີ່ຊັບຊ້ອນກັບປະລິມານນ້ຳທີ່ປ່ອຍຈາກເຂື່ອນຕອນເທິງມາກ່ອນໜ້ານີ້ຫຼາຍອາທິດ, ລະດູການ, ແລະ ສະພາບອາກາດ (El Niño/La Niña). ຂໍ້ມູນທີ່ມີລັກສະນະຕໍ່ເນື່ອງກັນຕາມເວລາແບບນີ້ເອີ້ນວ່າ ອະນຸກົມເວລາ (Time Series).

ໃນອະດີດ, ພວກເຮົາອາດຈະໃຊ້ໂມເດວທາງສະຖິຕິເຊັ່ນ ARIMA, ແຕ່ເມື່ອຂໍ້ມູນມີຂະໜາດໃຫຍ່ (High-dimensional) ແລະ ມີຄວາມສຳພັນແບບບໍ່ເປັນເສັ້ນຊື່ (Non-linear), ໂມເດວແບບດັ້ງເດີມມັກຈະພົບກັບຂໍ້ຈຳກັດ. ສຳລັບນັກພັດທະນາ AI ລະດັບສູງ, ນີ້ຄືຈຸດທີ່ Long Short-Term Memory (LSTM) ເຊິ່ງເປັນສະຖາປັດຕະຍະກຳໜຶ່ງຂອງ Deep Learning ເຂົ້າມາມີບົດບາດສຳຄັນ ໃນການຈື່ຈຳຄວາມສຳພັນໄລຍະຍາວ (Long-term dependencies).


ໂຄງສ້າງທາງຄະນິດສາດຂອງ LSTM (Mathematical Architecture of LSTM)

RNNs ແບບມາດຕະຖານມັກຈະປະເຊີນກັບ ບັນຫາ Vanishing Gradient ເມື່ອຕ້ອງປະມວນຜົນລໍາດັບຂໍ້ມູນທີ່ຍາວ (Long sequences). ເພື່ອແກ້ໄຂບັນຫານີ້, LSTM ໄດ້ແນະນຳອົງປະກອບທີ່ເອີ້ນວ່າ Cell State (CtC_t) ເຊິ່ງເຮັດໜ້າທີ່ຄືກັບສາຍພານລຳລຽງຂໍ້ມູນ (Conveyor belt) ທີ່ຍອມໃຫ້ຂໍ້ມູນໄຫຼຜ່ານທາງລັດ ໂດຍມີການລົບກວນໜ້ອຍທີ່ສຸດ.

ການຂັບເຄື່ອນຂອງ Cell State ຖືກຄວບຄຸມດ້ວຍ “ປະຕູ” (Gates) 3 ບານ ເຊິ່ງປະກອບດ້ວຍສົມຜົນທາງຄະນິດສາດດັ່ງນີ້:

  1. Forget Gate (ftf_t): ຕັດສິນໃຈວ່າຈະຖິ້ມຂໍ້ມູນໃດຈາກ Cell State ເກົ່າ (Ct1C_{t-1}). ft=σ(Wf[ht1,xt]+bf)f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f)
  2. Input Gate (iti_t) ແລະ Candidate Memory (C~t\tilde{C}_t): ຕັດສິນໃຈວ່າຈະອັບເດດຂໍ້ມູນໃໝ່ໃດເຂົ້າໄປໃນ Cell State. it=σ(Wi[ht1,xt]+bi)i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) C~t=tanh(Wc[ht1,xt]+bc)\tilde{C}_t = \tanh(W_c \cdot [h_{t-1}, x_t] + b_c)
  3. Cell State Update (CtC_t): ການຄຳນວນ Cell State ປັດຈຸບັນ. Ct=ftCt1+itC~tC_t = f_t * C_{t-1} + i_t * \tilde{C}_t
  4. Output Gate (oto_t) ແລະ Hidden State (hth_t): ຕັດສິນໃຈວ່າຈະສົ່ງຂໍ້ມູນໃດອອກໄປເປັນ Hidden State ສຳລັບ Time step ຕໍ່ໄປ. ot=σ(Wo[ht1,xt]+bo)o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) ht=ottanh(Ct)h_t = o_t * \tanh(C_t)

(ໝາຍເຫດ: σ\sigma ແມ່ນ Sigmoid layer ທີ່ໃຫ້ຄ່າລະຫວ່າງ 0 ຫາ 1, ສ່ວນ WW ແລະ bb ແມ່ນ Weights ແລະ Biases ທີ່ໂມເດວຈະຕ້ອງຮຽນຮູ້)


ກໍລະນີສຶກສາ: ການພະຍາກອນລະດັບນ້ຳຂອງໃນນະຄອນຫຼວງວຽງຈັນ

ໃນກໍລະນີສຶກສານີ້, ພວກເຮົາຈະອອກແບບໂມເດວ Multivariate LSTM ທີ່ຮັບຂໍ້ມູນ Input ຫຼາຍຕົວແປ (ເຊັ່ນ: ລະດັບນ້ຳປັດຈຸບັນ, ປະລິມານນ້ຳຝົນ, ແລະ ປະລິມານນ້ຳຈາກແຫຼ່ງອື່ນໆ) ເພື່ອພະຍາກອນລະດັບນ້ຳຂອງໃນ NN ມື້ຂ້າງໜ້າ.

ການກຽມຂໍ້ມູນ (Sliding Window Generation)

ໃນ PyTorch, LSTM ຄາດຫວັງ Input Tensor ໃນຮູບແບບ (batch_size, sequence_length, input_size). ພວກເຮົາຕ້ອງແປງຂໍ້ມູນ Time Series ໃຫ້ເປັນດັ່ງກ່າວດ້ວຍເຕັກນິກ Sliding Window.

import numpy as np
import torch

def create_sequences(data, seq_length):
    xs, ys = [], []
    for i in range(len(data) - seq_length):
        # ໃຊ້ຂໍ້ມູນ sequance_length ມື້ ມາເປັນ input
        xs.append(data[i:(i + seq_length)])
        # label ແມ່ນມື້ຖັດໄປ
        ys.append(data[i + seq_length, 0]) # ສົມມຸດວ່າ index 0 ແມ່ນລະດັບນ້ຳຂອງທີ່ຕ້ອງການພະຍາກອນ
    
    return torch.tensor(np.array(xs), dtype=torch.float32), torch.tensor(np.array(ys), dtype=torch.float32)

# Sequence Length = 30 ມື້
SEQ_LENGTH = 30
INPUT_SIZE = 3 # Multivariate: [ລະດັບນ້ຳ, ປະລິມານຝົນ, ຄວາມຊຸ່ມຊື່ນສະສົມ]

# ສົມມຸດວ່າ scaled_data ແມ່ນ numpy array ທີ່ຜ່ານການ Scaling (MinMaxScaler) ມາແລ້ວ
# X_train, y_train = create_sequences(scaled_data, SEQ_LENGTH)

ການສ້າງສະຖາປັດຕະຍະກຳ LSTM ໃນ PyTorch (Building the LSTM Architecture)

ພວກເຮົາຈະສ້າງ Model Class ທີ່ສືບທອດຈາກ nn.Module. ເພື່ອປ້ອງກັນ Overfitting ເຊິ່ງເປັນບັນຫາຫຼັກໃນ Time Series, ຈະມີການເພີ່ມ Dropout ເຂົ້າໄປດ້ວຍ.

import torch.nn as nn

class MekongWaterLSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size, dropout=0.2):
        super(MekongWaterLSTM, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        
        # ປະກາດ LSTM Layer
        self.lstm = nn.LSTM(
            input_size=input_size, 
            hidden_size=hidden_size, 
            num_layers=num_layers, 
            batch_first=True, # ໃຫ້ batch size ເປັນ Dimension ທຳອິດ
            dropout=dropout if num_layers > 1 else 0
        )
        
        # Fully Connected Layer ສຳລັບການພະຍາກອນຄ່າສຸດທ້າຍ
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        # x shape: (batch_size, seq_length, input_size)
        
        # ກຳນົດຄ່າເລີ່ມຕົ້ນຂອງ Hidden State ແລະ Cell State ເປັນ 0
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)

        # ປ້ອນຂໍ້ມູນເຂົ້າ LSTM
        out, (hn, cn) = self.lstm(x, (h0, c0))
        
        # ດຶງເອົາພຽງແຕ່ Output ຂອງ Time-step ສຸດທ້າຍ (seq_length) ມາໃຊ້
        out = out[:, -1, :]
        out = self.fc(out)
        return out

ການຝຶກອົບຮົມໂມເດວ ແລະ ການປັບແຕ່ງ (Training and Optimization)

ຈຸດສຳຄັນທີ່ສຸດໃນການ Train RNN/LSTM ແມ່ນການໃຊ້ເຕັກນິກ Gradient Clipping (torch.nn.utils.clip_grad_norm_) ເພື່ອປ້ອງກັນບັນຫາ Exploding Gradients ເຊິ່ງມັກຈະເຮັດໃຫ້ຄ່າ Loss ກາຍເປັນ NaN.

# ຕັ້ງຄ່າ Hyperparameters
HIDDEN_SIZE = 64
NUM_LAYERS = 2
OUTPUT_SIZE = 1 # ພະຍາກອນ 1 ຕົວແປ (ລະດັບນ້ຳ 1 ມື້ຂ້າງໜ້າ)
LEARNING_RATE = 0.001
EPOCHS = 100

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = MekongWaterLSTM(INPUT_SIZE, HIDDEN_SIZE, NUM_LAYERS, OUTPUT_SIZE).to(device)

criterion = nn.MSELoss() # ໃຊ້ Mean Squared Error ສຳລັບ Regression Task
optimizer = torch.optim.Adam(model.parameters(), lr=LEARNING_RATE)

# Training Loop
for epoch in range(EPOCHS):
    model.train()
    optimizer.zero_grad()
    
    # Forward pass
    # X_train, y_train presupposed to be moved to 'device'
    # outputs = model(X_train)
    # loss = criterion(outputs.squeeze(), y_train)
    
    # Backward pass
    # loss.backward()
    
    # Gradient Clipping ເພື່ອປ້ອງກັນ Exploding Gradients
    torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
    
    # optimizer.step()
    
    if (epoch+1) % 20 == 0:
        pass # print(f'Epoch [{epoch+1}/{EPOCHS}], Loss: {loss.item():.4f}')

ເຕັກນິກການປັບປຸງປະສິດທິພາບລະດັບສູງ (Advanced Considerations)

ສຳລັບການພັດທະນາໂມເດວເພື່ອໃຊ້ງານຈິງ (Production-level), ຄຸນນະພາບສະເພາະຂອງຂໍ້ມູນ Time Series ຈະຮຽກຮ້ອງໃຫ້ມີການປັບແຕ່ງເພີ່ມເຕີມ:


ຂໍ້ສັງເກດທີ່ສຳຄັນ (Key Takeaways)


ສະຫຼຸບ

ການພະຍາກອນອະນຸກົມເວລາທີ່ຊັບຊ້ອນ ບໍ່ວ່າຈະເປັນລະດັບນ້ຳຂອງ, ຄວາມຕ້ອງການການໃຊ້ໄຟຟ້າຂອງລັດວິສາຫະກິດໄຟຟ້າລາວ (EDL), ຫຼື ລາຄາສິນຄ້າກະສິກຳ ລ້ວນນແລ້ວແຕ່ຮຽກຮ້ອງໃຫ້ມີໂມເດວທີ່ສາມາດຈັບຄວາມສຳພັນໄລຍະຍາວໄດ້. LSTM ເປັນເຄື່ອງມື Deep Learning ທີ່ມີປະສິດທິພາບສູງສຳລັບວຽກງານນີ້ ເມື່ອຖືກກຳນົດຄ່າ (Configured) ແລະ ຝຶກອົບຮົມຢ່າງຖືກຕ້ອງ. ໂດຍການເຂົ້າໃຈກົນໄກທາງຄະນິດສາດ ແລະ ການຄວບຄຸມ Pipeline ຂອງຂໍ້ມູນໃນ PyTorch ຕາມທີ່ໄດ້ສະແດງໃຫ້ເຫັນ, ທ່ານຈະສາມາດນຳເອົາພະລັງຂອງ AI ມາສ້າງການຄາດຄະເນທີ່ສາມາດຊ່ວຍໃນການຕັດສິນໃຈທາງທຸລະກິດ ແລະ ກິດຈະກຳລະດັບຊາດໄດ້ຢ່າງມີປະສິດທິພາບ.