DEV Community

กษิ ศรีสุวรรณ
กษิ ศรีสุวรรณ

Posted on • Edited on

Use LSTM to calculate stocks

โพสนี้เขียนโดย นาย กษิ ศรีสุวรรณ 6730614006 AISE

  • ในการสร้างตัวคำนวณเบื้องต้นสำหรับคาดเดาหุ้น ณ ตอนนี้ ผมได้นำ LSTM หรือในชื่อ Long short-term memmory ซึ่งเป็น Algorithm ที่อยู่ใน Supervised Learning ในหัวข้อย่อย Neural Network ซึ้งพัฒนามาจาก RNN หรือ Recurrnt neural network
  • ในความเข้าใจของผมตอนนี้ในหัวข้อ LSTM เป็น Algorithm ที่สามารถวิเคราะห์มีประสิทธิภาพสำหรับ time series และเหมาะมากสำหรับการเทียบราคาเดียว และนี่คือแผนภาพของหน่วยการสร้าง LSTM  แบ่งไปได้ 3 ส่วนคือ
  1. Forget gate คือ gate ที่จะตัดสินใจว่า ข้อมูลในเซลล์ควรถูกลืมหรือเก็บไว้

  2. Input gate คือ gate ที่ตัดสินใจว่าจะนำข้อมูลใหม่เข้าเซลล์อย่างไร

  3. Output gate คือ gate ที่จะเป็นตัวเลือกข้อมูลที่จะแปลงจากเซลล์เป็น hidden state และส่งต่อออกไป

  • ส่วนที่ผมทำ code โดยทำใน colab ##
import os
import random
import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error

def set_seed(seed=42):
    os.environ["PYTHONHASHSEED"] = str(seed)
    random.seed(seed)
    np.random.seed(seed)
    tf.random.set_seed(seed)

def create_sequences(scaled_series, seq_len=60):
    """
    scaled_series: ndarray รูป (N, 1) ที่ผ่าน MinMaxScaler แล้ว
    seq_len: จำนวน timestep ย้อนหลังที่ใช้เป็น input

    คืนค่า:
    X: shape (num_samples, seq_len, 1)
    y: shape (num_samples,)
    idx: index ของตำแหน่ง y ใน series เดิม (ไว้ใช้แบ่ง train/val)
    """
    X, y, idx = [], [], []
    for i in range(seq_len, len(scaled_series)):
        X.append(scaled_series[i-seq_len:i, 0])
        y.append(scaled_series[i, 0])
        idx.append(i)
    X = np.array(X)
    y = np.array(y)
    idx = np.array(idx)

    X = X.reshape((X.shape[0], X.shape[1], 1))
    return X, y, idx

def create_lstm_model(seq_len=60):
    model = tf.keras.Sequential(
        [
            tf.keras.layers.LSTM(
                64, return_sequences=True, input_shape=(seq_len, 1)
            ),
            tf.keras.layers.Dropout(0.2),
            tf.keras.layers.LSTM(64),
            tf.keras.layers.Dropout(0.2),
            tf.keras.layers.Dense(1),
        ]
    )

    model.compile(optimizer="adam", loss="mean_squared_error")
    return model

if __name__ == "__main__":
    set_seed(42)

    SEQ_LEN = 60          # ใช้ย้อนหลัง 60 วัน
    VAL_SIZE = 300        # ให้ 300 จุดสุดท้ายของ train เป็น validation
    EPOCHS = 50
    BATCH_SIZE = 32


    train = pd.read_csv("train.csv")              # id, price (1–3200)
    test = pd.read_csv("test.csv")                # id (3201–3500)
    sample_sub = pd.read_csv("sample_submission.csv")

    print("Train shape :", train.shape)
    print("Test shape  :", test.shape)

    prices = train["price"].values.reshape(-1, 1)   # (3200, 1)

    scaler = MinMaxScaler(feature_range=(0, 1))
    scaled_prices = scaler.fit_transform(prices)

    X_all, y_all, idx_all = create_sequences(scaled_prices, SEQ_LEN)

    target_start_val = len(prices) - VAL_SIZE

    train_mask = idx_all < target_start_val
    val_mask = idx_all >= target_start_val

    X_train, y_train = X_all[train_mask], y_all[train_mask]
    X_val, y_val = X_all[val_mask], y_all[val_mask]

    print(f"Train samples     : {len(X_train)}")
    print(f"Validation samples: {len(X_val)}")

    model = create_lstm_model(SEQ_LEN)
    model.summary()

    early_stop = tf.keras.callbacks.EarlyStopping(
        monitor="val_loss",
        patience=5,
        restore_best_weights=True
    )

    print("\nกำลัง train LSTM (ใช้ train / val จาก train.csv)...")
    history = model.fit(
        X_train,
        y_train,
        epochs=EPOCHS,
        batch_size=BATCH_SIZE,
        validation_data=(X_val, y_val),
        callbacks=[early_stop],
        verbose=1,
    )

    val_pred_scaled = model.predict(X_val)
    val_pred = scaler.inverse_transform(val_pred_scaled)
    y_val_actual = scaler.inverse_transform(y_val.reshape(-1, 1))

    rmse = np.sqrt(mean_squared_error(y_val_actual, val_pred))
    mae = mean_absolute_error(y_val_actual, val_pred)

    print("\n=== Validation metrics (300 จุดท้ายของ train) ===")
    print(f"LSTM -> RMSE: {rmse:.4f}, MAE: {mae:.4f}")

    print("\nกำลัง train LSTM ใหม่บนข้อมูลทั้งหมด (เพื่อใช้ทำนายอนาคต)...")
    model_full = create_lstm_model(SEQ_LEN)
    model_full.fit(
        X_all,
        y_all,
        epochs=EPOCHS,
        batch_size=BATCH_SIZE,
        verbose=1,
    )

    history_prices = prices[-SEQ_LEN:].copy()              # shape (60, 1)
    history_scaled = scaler.transform(history_prices)      # shape (60, 1)

    future_preds = []

    for step in range(len(test)):  # 300 ก้าว
        # ใช้ sequence ล่าสุด 60 จุด (scaled) เป็น input
        input_seq = history_scaled[-SEQ_LEN:].reshape(1, SEQ_LEN, 1)
        next_scaled = model_full.predict(input_seq, verbose=0)   # shape (1,1)`

        next_price = scaler.inverse_transform(next_scaled)[0, 0]
        future_preds.append(next_price)

        history_scaled = np.vstack([history_scaled, next_scaled])

    future_preds = np.array(future_preds)
    print("\nตัวอย่างผลทำนาย 5 ตัวแรก (LSTM):")
    for i in range(5):
        print(f"id {test['id'].iloc[i]} -> {future_preds[i]:.4f}")

    submission = sample_sub.copy()
    submission["price"] = future_preds
    submission = submission[["id", "price"]]

    out_path = "/content/Sent2/lstm_submission.csv"
    submission.to_csv(out_path, index=False)

    print(f"\nไฟล์ submission ถูกบันทึกเป็น: {out_path}")
    print(submission.head())
    print("...")  # ถ้าอยากดูท้าย ๆ เพิ่ม: print(submission.tail())

Enter fullscreen mode Exit fullscreen mode

-อธิบายการทำงานของโค้ดในแต่ละส่วน

  • ส่วนที่ 1 ลง library และ เตรียมพร้อมสภาพแวดล้อมสำหรับเขียน code
import os
import random
import numpy as np
import pandas as pd
import tensorflow as tf

from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error
Enter fullscreen mode Exit fullscreen mode

library พวกนี้ไว้ใช้ปรับสภาพแวดล้อมไว้
os, random = ไว้ตั้งค่า seed ให้การสุ่มนิ่ง
numpy = จัดการ array ตัวเลข
pandas = อ่าน CSV (train.csv, test.csv, sample_submission.csv)
tensorflow = ใช้สร้างและฝึก LSTM
MinMaxScaler = scale ข้อมูลราคาหุ้นให้อยู่ในช่วง [0,1] ช่วยให้ LSTM เทรนง่าย
mean_squared_error, mean_absolute_error = ใช้ประเมินผลบน validation (RMSE, MAE)

  • ส่วนที่ 2 ฟังก์ชัน set_seed ทำให้ผลสุ่ม “คงที่”
def set_seed(seed=42):
    os.environ["PYTHONHASHSEED"] = str(seed)
    random.seed(seed)
    np.random.seed(seed)
    tf.random.set_seed(seed)
Enter fullscreen mode Exit fullscreen mode

ปกติ deep learning จะสุ่มหลายอย่าง เช่น weight เริ่มต้น, การ shuffle, ฯลฯ
ถ้าเราอยากให้ “รันใหม่แล้วได้ผลใกล้เคียงเดิม” = ต้อง fix seed ทุกที่ที่เกี่ยวกับการสุ่ม

  • ส่วนที่ 3 ฟังก์ชัน create_sequences –แปลง time series เป็นข้อมูลสำหรับ LSTM
def create_sequences(scaled_series, seq_len=60):
    """
    scaled_series: ndarray รูป (N, 1) ที่ผ่าน MinMaxScaler แล้ว
    seq_len: จำนวน timestep ย้อนหลังที่ใช้เป็น input

    คืนค่า:
    X: shape (num_samples, seq_len, 1)
    y: shape (num_samples,)
    idx: index ของตำแหน่ง y ใน series เดิม (ไว้ใช้แบ่ง train/val)
    """
    X, y, idx = [], [], []
    for i in range(seq_len, len(scaled_series)):
        X.append(scaled_series[i-seq_len:i, 0])
        y.append(scaled_series[i, 0])
        idx.append(i)
    X = np.array(X)
    y = np.array(y)
    idx = np.array(idx)

    # reshape X ให้เป็น (samples, timesteps, features)
    X = X.reshape((X.shape[0], X.shape[1], 1))
    return X, y, idx
Enter fullscreen mode Exit fullscreen mode

- ไอเดีย
เรามี series ราคาหุ้น (หลัง scale แล้ว)
เช่น p1, p2, p3, ..., p3200
อยากให้ LSTM ใช้ “ย้อนหลัง 60 วัน” มาทำนาย “วันถัดไป 1 วัน” เช่น
input: [p1..p60] = target: p61
input: [p2..p61] = target: p62
…ไปเรื่อย ๆ

- ในโค้ดทำอะไร

  • ลูป for i in range(seq_len, len(scaled_series)):

  • scaled_series[i-seq_len:i, 0]
    1.ดึง window ย้อนหลัง 60 จุด ก่อนตำแหน่ง i
    2.เก็บใน X

  • scaled_series[i, 0]
    1.เป็นค่าที่จะให้ model ทาย (ราคาวันที่ i)
    2.เก็บใน y

  • idx.append(i)
    1.จำว่า target ตัวนี้มาจาก index ที่เท่าไรใน series เดิม
    2.ไว้ใช้แบ่ง train/validation ตามตำแหน่งเวลา

  • สุดท้าย

    • X กลายเป็น numpy array รูป (num_samples, 60, 1)
    • (samples = 3200 - 60 = 3140)
    • y รูป (num_samples,)
    • idx รูป (num_samples,) เก็บ index ของแต่ละ target
  • ส่วนที่ 4 ฟังก์ชัน create_lstm_model – สร้างโครง LSTM
def create_lstm_model(seq_len=60):
    model = tf.keras.Sequential(
        [
            tf.keras.layers.LSTM(
                64, return_sequences=True, input_shape=(seq_len, 1)
            ),
            tf.keras.layers.Dropout(0.2),
            tf.keras.layers.LSTM(64),
            tf.keras.layers.Dropout(0.2),
            tf.keras.layers.Dense(1),
        ]
    )

    model.compile(optimizer="adam", loss="mean_squared_error")
    return model
Enter fullscreen mode Exit fullscreen mode
  • โครงโมเดล

    • input shape (seq_len, 1) = คือ sequence ยาว 60 มี 1 feature (ราคา)
  • ชั้นแรก LSTM(64, return_sequences=True)

    • มี 64 units
    • return_sequences=True หมายถึง ส่ง sequence ทั้ง 60 timestep ให้ชั้นถัดไป
  • Dropout(0.2) = ปิด neuron 20% แบบสุ่มระหว่างฝึก เพื่อลด overfitting
    -** ชั้นที่สอง LSTM(64)** = รับ sequence แล้วสรุปออกมาเป็น vector ตัวสุดท้าย

  • Dropout(0.2) อีกที

  • Dense(1) = แปลงเป็นค่าเดียว = ราคาที่คาดการณ์ (ในโลกที่ scale แล้ว)
    model.compile(optimizer="adam", loss="mean_squared_error")

    • ใช้ optimizer Adam ปรับน้ำหนัก
    • ใช้ MSE เป็น loss function
  • ส่วนที่ 5 main script – เริ่มรันจริง
if __name__ == "__main__":
    set_seed(42)

    SEQ_LEN = 60          # ใช้ย้อนหลัง 60 วัน
    VAL_SIZE = 300        # ให้ 300 จุดสุดท้ายของ train เป็น validation
    EPOCHS = 50
    BATCH_SIZE = 32
Enter fullscreen mode Exit fullscreen mode
  • เรียก set_seed(42) เพื่อ fix seed
  • กำหนด hyperparameter ต่าง ๆ:
    • SEQ_LEN = 60 = ใช้ย้อนหลัง 60 จุดต่อ 1 prediction
    • VAL_SIZE = 300 = 300 จุดสุดท้ายของ train เอาไว้ “เช็คความแม่น” (validation)
    • EPOCHS = 50, BATCH_SIZE = 32 = จำนวนรอบเทรน / ขนาด batch

ส่วนที่ 5.1 โหลดไฟล์ CSV

    train = pd.read_csv("train.csv")              # id, price (1–3200)
    test = pd.read_csv("test.csv")                # id (3201–3500)
    sample_sub = pd.read_csv("sample_submission.csv")

    print("Train shape :", train.shape)
    print("Test shape  :", test.shape)

    prices = train["price"].values.reshape(-1, 1)   # (3200, 1)
Enter fullscreen mode Exit fullscreen mode
  • train มีคอลัมน์ id, price รวม 3200 แถว
  • test มี id ตั้งแต่ 3201–3500 (300 แถว) ต้องทำนาย price
  • sample_sub คือ template สำหรับ submit
  • prices คือ series ราคาที่เราจะใช้สร้าง sequence = reshape เป็น (3200,1) เพื่อใช้กับ MinMaxScaler

ส่วนที่ 5.2 scale ข้อมูลด้วย MinMaxScaler

    scaler = MinMaxScaler(feature_range=(0, 1))
    scaled_prices = scaler.fit_transform(prices)
Enter fullscreen mode Exit fullscreen mode
  • ราคาหุ้นมี range ประมาณ 0.3–90+
  • LSTM ทำงานได้ดีกว่าเมื่อ input อยู่ในช่วงเล็ก ๆ เช่น [0,1]
  • = ใช้ MinMaxScaler แปลงราคาทั้งหมดให้มาอยู่ในช่วง [0,1]
  • scaled_prices จะเป็น array (3200,1) แต่ค่าทีละจุดอยู่ระหว่าง 0 กับ 1

ส่วนที่ 5.3 สร้าง sequences ทั้งหมด และแบ่ง train / validation

    X_all, y_all, idx_all = create_sequences(scaled_prices, SEQ_LEN)
    # idx_all[i] = index ของ y_all[i] ใน series (หลังจาก scale)

    # ให้ target 300 จุดสุดท้าย เป็น validation
    # => index ของ y ที่ >= len(prices) - VAL_SIZE จะเป็น val
    target_start_val = len(prices) - VAL_SIZE

    train_mask = idx_all < target_start_val
    val_mask = idx_all >= target_start_val

    X_train, y_train = X_all[train_mask], y_all[train_mask]
    X_val, y_val = X_all[val_mask], y_all[val_mask]
Enter fullscreen mode Exit fullscreen mode
  • 1.create_sequences คืนค่า:
    • X_all: sequence ทั้งหมด (num_samples, 60, 1)
    • y_all: target ทั้งหมด (num_samples,)
    • idx_all: index ของ target ใน series เดิม เช่น [60, 61, ..., 3199]
  • 2.อยากให้ “300 จุดสุดท้ายของ target” เป็น validation:
    • target ในโลกจริงมี index 0–3199
    • 300 จุดสุดท้าย = index 3200 - 300 = 2900 ถึง 3199
    • เลยกำหนด target_start_val = len(prices) - VAL_SIZE = 3200 - 300 = 2900
  • 3.จากนั้นสร้าง mask:
    • train_mask = idx_all < 2900 = กลุ่ม train
    • val_mask = idx_all >= 2900 = กลุ่ม validation
  • 4.สุดท้าย:
    • X_train, y_train: ข้อมูลสำหรับเทรน
    • X_val, y_val: ข้อมูลสำหรับประเมิน

ส่วนที่ 5.4 สร้างและฝึก LSTM รุ่นแรก (เพื่อดู performance บน validation)

 model = create_lstm_model(SEQ_LEN)
    model.summary()

    early_stop = tf.keras.callbacks.EarlyStopping(
        monitor="val_loss",
        patience=5,
        restore_best_weights=True
    )

Enter fullscreen mode Exit fullscreen mode
  • สร้างโมเดล LSTM ตามที่นิยามไว้
  • EarlyStopping:
  • ดูค่า val_loss
  • ถ้า 5 epoch ติดต่อกันไม่ดีขึ้น = หยุดฝึก
  • แล้ว “ย้อนกลับ” ไปใช้ weight ที่ดีที่สุด (restore_best_weights=True)
 print("\nกำลัง train LSTM (ใช้ train / val จาก train.csv)...")
    history = model.fit(
        X_train,
        y_train,
        epochs=EPOCHS,
        batch_size=BATCH_SIZE,
        validation_data=(X_val, y_val),
        callbacks=[early_stop],
        verbose=1,
Enter fullscreen mode Exit fullscreen mode
)
Enter fullscreen mode Exit fullscreen mode
  • ฝึกโมเดลบน X_train/y_train
  • รายงานทั้ง loss และ val_loss ในแต่ละ epoch
  • ถ้า val_loss ไม่ดีขึ้นเกิน 5 รอบ = หยุด (เพื่อกัน overfitting) history เก็บ loss/val_loss ไปใช้ plot ทีหลังก็ได้ (แต่โค้ดนี้ยังไม่ได้ plot) ##

ส่วนที่ 5.5 ประเมินบน validation และแปลงค่ากลับเป็น “หน่วยราคา”

val_pred_scaled = model.predict(X_val)
    val_pred = scaler.inverse_transform(val_pred_scaled)
    y_val_actual = scaler.inverse_transform(y_val.reshape(-1, 1))

    rmse = np.sqrt(mean_squared_error(y_val_actual, val_pred))
    mae = mean_absolute_error(y_val_actual, val_pred)

    print("\n=== Validation metrics (300 จุดท้ายของ train) ===")
    print(f"LSTM -> RMSE: {rmse:.4f}, MAE: {mae:.4f}")

Enter fullscreen mode Exit fullscreen mode
  • model.predict(X_val) ให้ผลในหน่วย “scaled” (0–1)
  • ใช้ scaler.inverse_transform แปลงกลับไปเป็น “ราคา (บาท)”
  • y_val ก็ต้องถูก inverse transform เหมือนกัน
  • จากนั้นคำนวณ:
    • RMSE (Root Mean Squared Error) = วัดความคลาดเคลื่อนแบบถ่วง error ใหญ่เยอะหน่อย
    • MAE (Mean Absolute Error) = เฉลี่ยค่าคลาดเคลื่อนแบบ |จริง–ทำนาย| ค่าพวกนี้ใช้เทียบกับโมเดลอื่นได้ เช่น Linear, XGBoost ฯลฯ

ส่วนที่ 5.6 เทรนใหม่บน “sequence ทั้งหมด” เพื่อใช้ทำนายอนาคตจริง”

    print("\nกำลัง train LSTM ใหม่บนข้อมูลทั้งหมด (เพื่อใช้ทำนายอนาคต)...")
    model_full = create_lstm_model(SEQ_LEN)
    model_full.fit(
        X_all,
        y_all,
        epochs=EPOCHS,
        batch_size=BATCH_SIZE,
        verbose=1,
    )
Enter fullscreen mode Exit fullscreen mode
  • ตอนแรกเราใช้เฉพาะส่วน train (ต้น–ก่อนท้าย 300 จุด) เพื่อวัด performance
  • แต่เวลาจะ “ใช้จริง” อยากให้โมเดลได้เรียนรู้จาก “ข้อมูลทั้งหมด” (ทั้งก่อนหน้าและช่วงที่ใช้เป็น val)
  • เลยสร้าง model_full ใหม่ แล้วเทรนด้วย X_all, y_all (ไม่มี validation แล้ว)
  • ส่วนที่ 6 ทำนายราคาสำหรับ id 3201–3500 (rolling forecast)
    #ใช้ราคาจริง 60 จุดสุดท้ายจาก train เป็นจุดเริ่มต้น
history_prices = prices[-SEQ_LEN:].copy()              # shape (60, 1)
    history_scaled = scaler.transform(history_prices)      # shape (60, 1)

    future_preds = []

    for step in range(len(test)):  # 300 ก้าว
        # ใช้ sequence ล่าสุด 60 จุด (scaled) เป็น input
        input_seq = history_scaled[-SEQ_LEN:].reshape(1, SEQ_LEN, 1)
        next_scaled = model_full.predict(input_seq, verbose=0)   # shape (1,1)

        # เก็บ prediction (กลับไปเป็นราคา)
        next_price = scaler.inverse_transform(next_scaled)[0, 0]
        future_preds.append(next_price)

        # เอา prediction (scaled) ต่อเข้า history สำหรับรอบถัดไป
        history_scaled = np.vstack([history_scaled, next_scaled])

Enter fullscreen mode Exit fullscreen mode

นี่คือส่วนสำคัญของ “การคาดอนาคต 300 วันถัดไปแบบต่อเนื่อง”:

  1. เริ่มจาก ราคาจริง 60 จุดสุดท้ายของ train (prices[-60:])
    • แปลงเป็น scaled = history_scaled
  2. วนลูป for step in range(len(test)): = 300 รอบ (1 รอบ = 1 วันถัดไป)

ในแต่ละรอบ:

  • เอา 60 จุดล่าสุดจาก history_scaled = input_seq (shape (1, 60, 1))
  • ส่งเข้า model_full.predict() เพื่อทำนายราคาของวันถัดไปในรูป scaled (next_scaled)
  • แปลง next_scaled กลับเป็นราคา = next_price = เก็บใน future_preds
  • สำคัญ: เอา next_scaled ไปต่อท้าย history_scaled
    • รอบต่อไป model จะใช้ “59 จุดก่อนหน้า + จุดที่เพิ่งทำนายล่าสุด” เป็น input
    • ทำให้การทำนายในแต่ละวัน “ต่อเนื่อง” กันจริง ๆ (rolling) สุดท้าย future_preds จะเป็น array ยาว 300 แถว = ตรงกับ test 300 แถวพอดี
    future_preds = np.array(future_preds)
    print("\nตัวอย่างผลทำนาย 5 ตัวแรก (LSTM):")
    for i in range(5):
        print(f"id {test['id'].iloc[i]} -> {future_preds[i]:.4f}")
Enter fullscreen mode Exit fullscreen mode
  • ส่วนที่ 7 สร้างไฟล์ submission
    submission = sample_sub.copy()
    submission["price"] = future_preds
    submission = submission[["id", "price"]]

    out_path = "/content/Sent2/lstm_submission.csv"
    submission.to_csv(out_path, index=False)

    print(f"\nไฟล์ submission ถูกบันทึกเป็น: {out_path}")
    print(submission.head())
    print("...")  # ถ้าอยากดูท้าย ๆ เพิ่ม: print(submission.tail())
Enter fullscreen mode Exit fullscreen mode
  • เริ่มจาก copy sample_submission.csv เพื่อให้แน่ใจว่า id ตรงกัน
  • ใส่ค่า future_preds ลงไปในคอลัมน์ price
  • เลือกเฉพาะคอลัมน์ ["id", "price"]
  • เซฟเป็น lstm_submission.csv เพื่อเอาไปส่ง / ใช้งานต่อ
  • print หัวตารางให้ดูว่า id กับ price แมปกันถูก

Pseudo Code การทำงาน (ภาพรวมทั้งโปรแกรม)

เริ่มโปรแกรม

  1. ตั้งค่า seed ให้การสุ่ม (random, numpy, tensorflow) คงที่

  2. กำหนดค่าพารามิเตอร์หลัก:

    • SEQ_LEN = 60 # ใช้ข้อมูลย้อนหลัง 60 จุดในแต่ละ sequence
    • VAL_SIZE = 300 # ใช้ 300 จุดสุดท้ายของ train เป็น validation
    • EPOCHS = 50
    • BATCH_SIZE = 32
  3. โหลดไฟล์:

    • train.csv (มี id, price ตั้งแต่ 1–3200)
    • test.csv (มี id ตั้งแต่ 3201–3500)
    • sample_submission.csv
  4. ดึงราคาจาก train:

    • prices = คอลัมน์ "price" จาก train = shape (3200, 1)
  5. สร้าง MinMaxScaler แล้ว fit+transform บน prices:

    • scaled_prices = scale ราคาทั้งหมดให้อยู่ในช่วง [0,1]
  6. สร้าง sequence สำหรับ LSTM:

    • เรียก create_sequences(scaled_prices, SEQ_LEN)
    • ได้: X_all = ทุก window ยาว 60 (ย้อนหลัง) = shape (N, 60, 1) y_all = ราคาของวันถัดไป (label) = shape (N,) idx_all = index ของตำแหน่งแต่ละ y ใน series เดิม
  7. แบ่ง train / validation ตามตำแหน่งเวลา:

    • target_start_val = len(prices) - VAL_SIZE
    • train_mask = idx_all < target_start_val
    • val_mask = idx_all >= target_start_val
    • X_train, y_train = X_all[train_mask], y_all[train_mask]
    • X_val, y_val = X_all[val_mask], y_all[val_mask]
  8. สร้างโมเดล LSTM (2 ชั้น + Dense 1 ชั้น) ด้วยฟังก์ชัน create_lstm_model()

    • compile ด้วย optimizer = "adam", loss = "mse"
  9. กำหนด EarlyStopping เพื่อดูค่า val_loss:

    • ถ้า val_loss ไม่ดีขึ้นติดต่อกัน 5 epoch = หยุด และคืน weight ที่ดีที่สุด
  10. เทรนโมเดลรอบที่ 1 (สำหรับประเมิน):

    • model.fit(X_train, y_train, validation_data = (X_val, y_val), ...)
  11. ประเมินบน validation:

    • ทำนาย X_val = val_pred_scaled
    • inverse_transform ทั้ง y_val และ val_pred_scaled = ราคาจริง
    • คำนวณ RMSE, MAE แล้วแสดงผล
  12. เทรนโมเดลใหม่ (model_full) ด้วยข้อมูลทั้งหมด:

    • model_full.fit(X_all, y_all, ...)
  13. ทำนายอนาคตสำหรับ test (300 จุด):

    • เริ่มจากราคาจริง 60 จุดสุดท้ายใน train = history_prices
    • scale = history_scaled
    • ทำลูป 300 รอบ:
      • เอา 60 จุดล่าสุดใน history_scaled = input_seq
      • model_full.predict(input_seq) = next_scaled
      • inverse_transform = next_price (หน่วยบาท)
      • เก็บ next_price ใน future_preds
      • ต่อ next_scaled เข้า history_scaled เพื่อใช้ในรอบถัดไป
    • ได้ future_preds ยาว 300 จุด
  14. สร้าง submission:

    • copy sample_submission
    • ใส่ future_preds ลงคอลัมน์ "price"
    • เซฟเป็น lstm_submission.csv

จบโปรแกรม

อ้างอิงรูปภาพ และ เนื้อหาบางส่วนจาก
https://blog.mlreview.com/understanding-lstm-and-its-diagrams-37e2f46f1714

ขอบคุณที่เข้ามาอ่านครับ ถ้าผิดประการใดขออภัย ณ ที่นี้ครับ

Top comments (0)