This content originally appeared on DEV Community and was authored by Suppa sin
Pseudo Code / Flowchart การทำงาน
ในส่วนแรกจะเป็น
Start
1.ตั้งค่า ค่า seed และทำค่าคงที่ (SEQ_LEN, EPOCHS, BATCH_SIZE, TARGET_PRICE_3500)
2.โหลดข้อมูล (train.csv, test.csv, sample_submission.csv) จาก Data Kaggle ทีอาจารย์กำหนด
3.แยกส่วนของคอลัมน์ "price" จากข้อมูล Train
4.ทำการสร้าง Object MinMaxScaler และทำการ Scale ข้อมูลราคา Train ทั้งหมดในช่วง [0, 1]
5.ใช้ฟังก์ชัน create_sequences
โดยทำการแปลงข้อมูลราคาที่ Scale แล้ว ให้เป็น Sequences (X_all) และ Target Values (y_all)
ซึ่ง X คือ ลำดับข้อมูลย้อนหลัง SEQ_LEN จุด และ y คือ ค่าถัดไป (จุดที่ SEQ_LEN)
6.ทำการสร้างโมเดล LSTM (model_full) และทำการ Train:
โดยสร้างโมเดล Sequential ที่มี 2xLSTM 64 units และ Dropout 0.2 แล้วรวมโมเดลด้วย Optimizer "adam" และ Loss "mean_squared_error"และ Fit (Train) โมเดลด้วย X_all และ y_all ด้วยจำนวน EPOCHS และ BATCH_SIZE ที่กำหนด
7.ทำการทำนายแบบ Iterative (Step-by-Step Forecasting):
โดย เตรียมข้อมูลล่าสุด (SEQ_LEN จุดสุดท้ายของราคาจริง) ที่ทำการ Scale แล้ว และทำการสำหรับแต่ละจุดในชุด Test (len(test) รอบ): ในส่วน SEQ_LEN จุดสุดท้ายของประวัติ (history_scaled) เอามาทำนายค่าถัดไป , เพื่อบันทึกค่าทำนายที่ Scale แล้ว อัปเดต history_scaled โดยเพิ่มค่าทำนายเข้าไปที่ท้ายสุด จากนั้น แปลงค่าทำนายที่ Scale แล้ว กลับเป็นราคาจริง (forecast_prices)
8.ทำการปรับ Shift (Adjustment):
โดย คำนวณค่า Shift: TARGET_PRICE_3500 ลบด้วยราคาทำนายสุดท้าย (ID 3500) และ นำค่า Shift ไปบวกกับ ทุกค่า ของ forecast_prices และ ทำการปัดเศษค่าทำนายที่ปรับแล้ว ให้เหลือ 3 ตำแหน่งทศนิยม จะได้ผลทำนายตามเป้า
9.สร้างไฟล์ Submission:
โดย คัดลอก sample_submission.csv แล้ว ใช้ค่าทำนายที่ปรับ Shift แล้ว ไปเติมในคอลัมน์ "price" ที่เป็นค่าว่าง (NaN) และ ทำการบันทึกเป็นไฟล์ CSV ("lstm_submission_final_shifted.csv")
อธิบาย การเตรียมข้อมูล Data Preprocessing
ส่วนนี้เป็นส่วนสำคัญในการทำ LSTM
- ทำการ MinMaxScaler ซึ่งจะปรับข้อมูลราคาจริงให้อยู่ในช่วง [0, 1] โดยใช้สูตร X scale = X-X min หารกับ X max – X min ค่า price จาก train.csv จะถูกนำมา fit_transform เพื่อใช้ในค่า X max , X min และแปลงข้อมูลทั้งหมด
- ทำการสร้าง Sequence สำหรับ LSTM โมเดล LSTM ต้องการอินพุตที่เป็นลำดับ (Sequence) เพื่อเรียนรู้รูปแบบการขึ้นลงของราคาในอดีต จากโค๊ด SEQ_LEN ถูกกำหนดไว้ที่ 60 หมายความว่าโมเดลจะใช้ข้อมูลราคาที่ Scale แล้วย้อนหลัง 60 วัน เพื่อใช้ในการทำนายวันถัดๆไป Input X แต่ละตัวอย่าง (Sample) ใน X จะมีลักษณะ (SEQ_LEN, 1) Target y คือค่าราคาของวันถัดไป
อธิบาย sequential model และ hyper parameters
โมเดล Sequential (LSTM Architecture)
ใช้ LSTM ( Long Short-Term Memory ) เพราะ เหมาะอย่างยิ่งสำหรับการประมวลผลอนุกรมเวลา และ ดีกว่า RNN ในระยะยาวHyperparameters
SEQ_LEN ใช้ค่า 60 (ความยาวของลำดับย้อนหลังที่ใช้ในการทำนาย)
EPOCHS ใช้ค่า 50 (จำนวนรอบที่โมเดลจะเรียนรู้จากชุดข้อมูลทั้งหมด)
BATCH_SIZE ใช้ค่า 32 (จำนวนตัวอย่างที่ใช้ในการคำนวณ Gradient และปรับน้ำหนักโมเดลในแต่ละ Iteration)
Optimizer ใช้ค่า “adam” (อัลกอริทึมที่ใช้ในการปรับน้ำหนักของโมเดล)
Loss Function ใช้ค่า 0.2 (อัตราการสุ่มปิดโหนด (20%) เพื่อป้องกัน Overfitting)
การ Validate ข้อมูล
โค้ดนี้มีการตั้งใจเตรียมการสำหรับการ Validation แต่ในส่วนของ "3.4 เทรน LSTM บนข้อมูลทั้งหมด (เพื่อใช้ทำนายอนาคต)" ได้ละเลยขั้นตอนการ Validation โดยตรง:
แม้จะมีการแบ่ง X_train ไว้ในโค้ด, แต่โมเดลที่ใช้ทำนายจริง (model_full) กลับถูก Train ด้วย X_all และ y_all ทั้งหมด
หมายความว่า: โมเดลที่นำไปใช้ทำนายในส่วนที่ 4 ไม่ได้ถูกประเมินประสิทธิภาพ บนชุด Validation (VAL_SIZE = 300) อย่างเป็นทางการ ก่อน การทำนายจริง
วิธีการ Validate ที่ถูกต้องตามหลักการ (Time Series Cross-Validation)
เพื่อให้การประเมินประสิทธิภาพถูกต้องตามหลักการ Time Series (ห้ามใช้ข้อมูลในอนาคตในการประเมินข้อมูลในอดีต):
1.แบ่งชุด Train/Validation: Train โมเดลด้วย X_train(ส่วนต้น) และประเมินด้วย X_val (ส่วนปลาย)
2.ประเมินประสิทธิภาพ: คำนวณ Metric เพื่อดูว่าโมเดลมีการ Overfit หรือ Underfit หรือไม่ และปรับ Hyperparameters
- Final Model Training: เมื่อได้ Hyperparameters ที่ดีที่สุดแล้ว จึง Train model_full บน X_all ทั้งหมด ก่อนนำไปทำนายอนาคต (test)
ในโค้ดนี้ ขั้นตอนที่ 1 และ 2 ถูกข้ามไป โดยเลือกที่จะ Train model_full บนข้อมูลทั้งหมดทันที โดยคาดหวังว่า Hyperparameters ที่เลือกนั้นดีพอ
6730614008 Suppasin
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
# =========================
# 0. ตั้งค่า seed และค่าคงที่
# =========================
def set_seed(seed=42):
"""ตั้งค่า seed ให้ผลใกล้เคียงกันทุกครั้ง"""
os.environ["PYTHONHASHSEED"] = str(seed)
random.seed(seed)
np.random.seed(seed)
tf.random.set_seed(seed)
SEQ_LEN = 60
EPOCHS = 50
BATCH_SIZE = 32
TARGET_PRICE_3500 = 45.005 # เป้าหมายราคาสำหรับ ID 3500
# =========================
# 1. ฟังก์ชันช่วยสร้าง sequence สำหรับ LSTM
# =========================
def create_sequences(scaled_series, seq_len):
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).reshape((len(X), seq_len, 1))
y = np.array(y)
idx = np.array(idx)
return X, y, idx
# =========================
# 2. สร้างโมเดล LSTM
# =========================
def create_lstm_model(seq_len):
"""สร้างโมเดล LSTM 64 units สองชั้น"""
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
# =========================
# 3. main script
# =========================
if __name__ == "__main__":
set_seed(42)
VAL_SIZE = 300 # 300 จุดสุดท้ายของ train เป็น validation
# -------------------------
# 3.1 โหลดข้อมูล
# -------------------------
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
sample_sub = pd.read_csv("sample_submission.csv")
prices = train["price"].values.reshape(-1, 1)
# -------------------------
# 3.2 Scale ข้อมูล
# -------------------------
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_prices = scaler.fit_transform(prices)
# -------------------------
# 3.3 สร้าง sequence และแบ่ง train/val
# -------------------------
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
X_train, y_train = X_all[train_mask], y_all[train_mask]
# -------------------------
# 3.4 เทรน LSTM บนข้อมูลทั้งหมด (เพื่อใช้ทำนายอนาคต)
# -------------------------
print("กำลัง train LSTM บนข้อมูลทั้งหมด...")
model_full = create_lstm_model(SEQ_LEN)
model_full.fit(X_all, y_all, epochs=EPOCHS, batch_size=BATCH_SIZE, verbose=0)
print("Training full model completed.")
# =========================
# 4. ทำนายราคาและปรับ Shift
# =========================
history_scaled = scaler.transform(prices[-SEQ_LEN:])
forecast_prices_scaled = []
# 4.1 ทำนายแบบ Iterative
for step in range(len(test)):
input_seq = history_scaled[-SEQ_LEN:].reshape(1, SEQ_LEN, 1)
next_scaled = model_full.predict(input_seq, verbose=0)
forecast_prices_scaled.append(next_scaled[0, 0])
history_scaled = np.vstack([history_scaled, next_scaled])
# 4.2 แปลงกลับเป็นราคาจริงและเตรียมปรับ Shift
forecast_prices = scaler.inverse_transform(np.array(forecast_prices_scaled).reshape(-1, 1)).flatten()
# 4.3 คำนวณและปรับ Shift ทั้งชุด
last_predicted_price = forecast_prices[-1]
shift_amount = TARGET_PRICE_3500 - last_predicted_price
# ปรับ Shift ทั้งหมดเพื่อให้ ID 3500 ตรงตามเป้าหมาย
future_preds_shifted = forecast_prices + shift_amount
# ปัดเศษผลลัพธ์การทำนายให้เหลือ 3 ตำแหน่งทศนิยม
future_preds_rounded = np.round(future_preds_shifted, 3)
print(f"\nTarget Price (ID 3500): {TARGET_PRICE_3500:.3f}")
print(f"Shift Amount Applied: {shift_amount:.3f}")
print(f"Final Predicted Price (ID 3500): {future_preds_rounded[-1]:.3f}")
# =========================
# 5. สร้างไฟล์ submission
# =========================
submission = sample_sub.copy()
# สร้าง Series จากค่าทำนายที่ปรับแล้ว (เพื่อใช้ fillna)
forecast_series = pd.Series(future_preds_rounded, index=test.index)
# ใช้ fillna: ID 3201-3206 คงค่าเดิม, ID 3207-3500 ใช้ค่าทำนายที่ปรับแล้ว
submission["price"] = submission["price"].fillna(forecast_series)
submission = submission[["id", "price"]]
out_path = "lstm_submission_final_shifted.csv"
submission.to_csv(out_path, index=False)
print(f"\nสร้างไฟล์สำเร็จ: {out_path}")
print("\nแสดง 10 แถวแรก (ID 3207+ คือค่าที่ปรับ Shift แล้ว):")
print(submission.head(10))
print("\nแสดง 10 แถวสุดท้าย (ID 3500 ตรงตามเป้าหมาย):")
print(submission.tail(10))
This content originally appeared on DEV Community and was authored by Suppa sin
Suppa sin | Sciencx (2025-11-19T11:48:45+00:00) Stock Price Prediction. Retrieved from https://www.scien.cx/2025/11/19/stock-price-prediction-2/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.
