แบ่งปันโค้ดโมเดล LSTM ช่วยพยากรณ์ราคาทองคำในหนึ่งวันข้างหน้า

เนื่องจากเราเป็นเด็กวิศวกะคอม พอมีความรู้เรื่องนี้อยู่
เลยลองทำโมเดลพยากรณ์ high และ low ของราคาทองคำ
ในหนึ่งวันข้างหน้า จากข้อมูล high และ low ย้อนหลัง 5 วัน

     โมเดลที่เราใช้นั้นเป็น LSTM (Long-Short Term Memory)
หรือ หน่วยความจำระยะสั้นยาว มันจะมีอยู่ 3 Gate คือ
Input Gate, Output Gate และ Forget Gate
มีความสามารถที่จะจดจำข้อมูลที่เป็นลำดับเวลาก่อน ๆ หน้าได้

     เทคนิคที่เราใช้ ก็ไม่ค่อยมีอะไร
ตอน Normalize ก็ต้อง Min-Max Scaling
เฉพาะช่วงค่าที่ดึงพยากรณ์เท่านั้น
อย่างเช่น ถ้าข้อมูลที่จะมาประกอบการพยากรณ์
มีแค่ 5 วัน ก็ให้ Normalized เฉพาะระหว่าง 5 วันนี้

     Train-Test Split เราใช้ 10%:90%
เพราะต้องการทำให้มั่นใจว่า เรียนรู้เพียง 2 ปี
จะสามารถพยากรณ์ในอนาคตได้เป็น 10 กว่าปี โดยไม่มีปัญหา
และเนื่องจากข้อมูลเป็นแบบต่อเนื่อง จะไม่มีการ shuffle เด็ดขาด

     Epoch เราปรับเป็น 2 เพราะมัน Overfit เร็วมาก
Batch size ปรับแบบ Stochastic ไปเลย
เพราะเดี๋ยวเว็บ Colab เดี้ยง รันไม่ไหว


     ข้างล่างนี้ ก็จะเป็นโค้ด Python นะ
สามารถ Copy เอาไปแปะใส่ใน Google Colab
ตามด้วยปรับ tab ให้ถูกต้อง แล้ว run ตัวโค้ดได้เลย!

โค้ดโหลดและ label ข้อมูล:
import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
import matplotlib.pyplot as plt
import gdown
from sklearn.preprocessing import MinMaxScaler

file_id = "1XXkVwG0OUQqNxWVSdz3q6IMzAnxf2dnv" # Timeframe = 1 วัน
# https://drive.google.com/file/d/1XXkVwG0OUQqNxWVSdz3q6IMzAnxf2dnv/view?usp=drive_link
# ข้อมูลได้มาจากใน Kaggle ชื่อ "XAU/USD Gold Price Historical Data (2004-2025)" ของ Novandra Anugrah
# ช่วงเวลาของข้อมูล ระหว่าง 1 ม.ค. 2547 จนถึง 20 กันยายน 2567

csv_path = "gold_prices.csv"

gdown.download(f"https://drive.google.com/uc?id={file_id}", csv_path, quiet=False)

df = pd.read_csv(csv_path)
df['Datetime'] = pd.to_datetime(df['Date'] + ' ' + df['Time'])
df.set_index('Datetime', inplace=True)
df = df[['High', 'Low']]

def create_dataset_with_scaling(data, time_step=5):
    X, Y = [], []
    for i in range(len(data) - time_step):
        window = data[i:i + time_step + 1]
        scaler = MinMaxScaler(feature_range=(0, 1))
        window_scaled = scaler.fit_transform(window)
        X.append(window_scaled[:-1])
        Y.append(window_scaled[-1])
    return np.array(X), np.array(Y)

time_step = 5 # เวลาก่อนหน้าที่นำมาใช้พยากรณ์

X, Y = create_dataset_with_scaling(df.values, time_step)
X = np.reshape(X, (X.shape[0], X.shape[1], X.shape[2]))

โค้ด Train-Test Split และตัวโมเดล LSTM:
train_size = int(len(X) * 0.1) # ฝึก 10% ทดสอบ 90%

X_train, X_test = X[:train_size], X[train_size:]
Y_train, Y_test = Y[:train_size], Y[train_size:]

model = Sequential([
    LSTM(64, return_sequences=True, input_shape=(time_step, X.shape[2])),
    LSTM(32, return_sequences=False),
    Dense(2)
])

model.compile(optimizer='adam', loss='mean_squared_error')
model.summary()

โค้ดฝึกโมเดล:
model.fit(X_train, Y_train, batch_size=1, epochs=2, validation_data=(X_test, Y_test))

โค้ดแสดงตัวอย่างของผลการพยากรณ์:
def predict_next_day(model, data, time_step=5):
    last_days = data[-time_step:]
    scaler = MinMaxScaler(feature_range=(0, 1))
    last_days_scaled = scaler.fit_transform(last_days)
    last_days_scaled = last_days_scaled.reshape(1, time_step, 2)
    predicted_scaled = model.predict(last_days_scaled)
    predicted_actual = scaler.inverse_transform([predicted_scaled[0]])[0]
    return predicted_actual

predictions_actual = []
actual_values = []

test_range = 200

start_index = len(X_test) - test_range

for i in range(start_index, len(X_test)):
    scaler = MinMaxScaler(feature_range=(0, 1))
    absolute_index = train_size + i
    test_window = df.values[absolute_index: absolute_index + time_step + 1]
    if len(test_window) < time_step + 1:
        continue
    scaler.fit(test_window)
    pred_scaled = model.predict(X_test[i].reshape(1, time_step, 2), verbose=0)
    pred_actual = scaler.inverse_transform([pred_scaled[0]])[0]
    predictions_actual.append(pred_actual)
    actual_values.append(test_window[-1])

predictions_actual = np.array(predictions_actual)
actual_values = np.array(actual_values)

plt.figure(figsize=(14, 7))

x = np.arange(len(actual_values))

plt.fill_between(x, actual_values[:, 0], actual_values[:, 1], color='skyblue', alpha=0.4, label="Actual Range")

plt.fill_between(x, predictions_actual[:, 0], predictions_actual[:, 1], color='salmon', alpha=0.4, label="Predicted Range")

plt.plot(x, actual_values[:, 0], color='blue', label="Actual High", linewidth=1)
plt.plot(x, actual_values[:, 1], color='blue', label="Actual Low", linewidth=1, linestyle='dotted')
plt.plot(x, predictions_actual[:, 0], color='red', label="Predicted High", linewidth=1)
plt.plot(x, predictions_actual[:, 1], color='red', label="Predicted Low", linewidth=1, linestyle='dotted')
plt.title(f"Gold Price Range Prediction (Last {test_range} Days)")
plt.xlabel("Hour Index")
plt.ylabel("Price")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

โค้ดสำหรับกรอกข้อมูลเพื่อพยากรณ์ (เอาไว้ลองใช้งาน):
import numpy as np

from sklearn.preprocessing import MinMaxScaler

def predict_next_value(model, highs, lows, time_step=5, target="high"):
    assert len(highs) == len(lows), "Highs and Lows must be the same length"
    input_data = np.column_stack((highs, lows))
    if len(input_data) < time_step:
        raise ValueError(f"Not enough data! Expected at least {time_step} values, got {len(input_data)}.")
    input_seq = input_data[-time_step:]
    scaler = MinMaxScaler()
    input_seq_scaled = scaler.fit_transform(input_seq)
    input_seq_scaled = input_seq_scaled.reshape(1, time_step, 2)
    predicted_scaled = model.predict(input_seq_scaled, verbose=0)
    output_index = 0 if target == "high" else 1
    predicted_actual = scaler.inverse_transform([[0, 0] if output_index else [0, 0]])[0][output_index]
    predicted_actual = scaler.inverse_transform([[predicted_scaled[0][output_index], predicted_scaled[0][output_index]]])[0][output_index]
    return predicted_actual

# ตอนเวลาจะใช้งานจริง ให้กรอก high กับ low แล้ว run ตัวโค้ด
highs = [2500, 2510, 2515, 2520, 2525]
lows =  [2480, 2490, 2495, 2500, 2505]

predicted_high = predict_next_value(model, highs, lows, time_step=5, target="high")
print(f"📈 Predicted Next High: {predicted_high:.2f}")
predicted_low = predict_next_value(model, highs, lows, time_step=5, target="low")
print(f"📉 Predicted Next Low: {predicted_low:.2f}")

     ถ้าหากทดลองแล้วโค้ดมีปัญหา
"ถาม ChatGPT หรือ AI ตัวอื่น ๆ"
เพราะตามจริงก็ให้ ChatGPT ช่วยเขียนโค้ดนั่นแหละ
เพียงแต่ต้องพอรู้หลักการอะไรมาปรับบ้าง

แสดงความคิดเห็น
โปรดศึกษาและยอมรับนโยบายข้อมูลส่วนบุคคลก่อนเริ่มใช้งาน อ่านเพิ่มเติมได้ที่นี่