Predict Stock Price using Trandformer. 3231-180D

Predict Stock Price using Trandformer. 3231-180D
Photo by Nick Chong / Unsplash
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
import math
from sklearn.metrics import mean_squared_error

# 加載數據
df = pd.read_csv('/content/3231_0614t.csv')

# 重置索引並提取 'Close' 列
df['st_date'] = pd.to_datetime(df['st_date']) 
df2 = df.reset_index()[['st_date', 'close']]

# 創建更多特徵
df2['Year'] = df2['st_date'].dt.year
df2['Month'] = df2['st_date'].dt.month
df2['Weekday'] = df2['st_date'].dt.weekday
df2['MA5'] = df2['close'].rolling(window=5).mean()
df2['MA10'] = df2['close'].rolling(window=10).mean()
df2['MA20'] = df2['close'].rolling(window=20).mean()
df2 = df2.dropna()

# 數據歸一化
scaler = MinMaxScaler(feature_range=(0, 1))
df2_scaled = scaler.fit_transform(df2[['close', 'Year', 'Month', 'Weekday', 'MA5', 'MA10', 'MA20']])

# 創建訓練和測試集
train_size = int(len(df2_scaled) * 0.65)
test_size = len(df2_scaled) - train_size
train_data, test_data = df2_scaled[0:train_size, :], df2_scaled[train_size:len(df2_scaled), :]

# 創建數據集
def create_dataset(dataset, time_step=1):
    dataX, dataY = [], []
    for i in range(len(dataset) - time_step - 1):
        a = dataset[i:(i + time_step), :]
        dataX.append(a)
        dataY.append(dataset[i + time_step, 0])  # 預測 'close' 列
    return np.array(dataX), np.array(dataY)

time_step = 100
X_train, Y_train = create_dataset(train_data, time_step)
X_test, Y_test = create_dataset(test_data, time_step)

# 將數據轉換為適合Transformer的格式
X_train = X_train.reshape(X_train.shape[0], time_step, -1)
X_test = X_test.reshape(X_test.shape[0], time_step, -1)

print("X_train shape:", X_train.shape)
print("X_test shape:", X_test.shape)

# 構建 Transformer 模型
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense, Flatten, LayerNormalization, MultiHeadAttention, Dropout

# 位置編碼
class PositionalEncoding(tf.keras.layers.Layer):
    def __init__(self, position, d_model):
        super(PositionalEncoding, self).__init__()
        self.pos_encoding = self.positional_encoding(position, d_model)
    
    def get_angles(self, pos, i, d_model):
        angle_rates = 1 / np.power(10000, (2 * (i // 2)) / np.float32(d_model))
        return pos * angle_rates
    
    def positional_encoding(self, position, d_model):
        angle_rads = self.get_angles(np.arange(position)[:, np.newaxis], np.arange(d_model)[np.newaxis, :], d_model)
        angle_rads[:, 0::2] = np.sin(angle_rads[:, 0::2])
        angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])
        pos_encoding = angle_rads[np.newaxis, ...]
        return tf.cast(pos_encoding, dtype=tf.float32)
    
    def call(self, inputs):
        return inputs + self.pos_encoding[:, :tf.shape(inputs)[1], :]

# Transformer塊
class TransformerBlock(tf.keras.layers.Layer):
    def __init__(self, embed_dim, num_heads, ff_dim, rate=0.1):
        super(TransformerBlock, self).__init__()
        self.att = MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim)
        self.ffn = tf.keras.Sequential(
            [Dense(ff_dim, activation="relu"), Dense(embed_dim)]
        )
        self.layernorm1 = LayerNormalization(epsilon=1e-6)
        self.layernorm2 = LayerNormalization(epsilon=1e-6)
        self.dropout1 = Dropout(rate)
        self.dropout2 = Dropout(rate)
    
    def call(self, inputs, training):
        attn_output = self.att(inputs, inputs)
        attn_output = self.dropout1(attn_output, training=training)
        out1 = self.layernorm1(inputs + attn_output)
        ffn_output = self.ffn(out1)
        ffn_output = self.dropout2(ffn_output, training=training)
        return self.layernorm2(out1 + ffn_output)

# 構建Transformer模型
def build_transformer_model(input_shape, num_heads, ff_dim):
    inputs = Input(shape=input_shape)
    x = PositionalEncoding(input_shape[0], input_shape[1])(inputs)
    transformer_block = TransformerBlock(input_shape[1], num_heads, ff_dim)
    x = transformer_block(x)
    x = Flatten()(x)
    outputs = Dense(1)(x)
    model = Model(inputs=inputs, outputs=outputs)
    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss="mean_squared_error")
    return model

input_shape = (time_step, X_train.shape[2])
num_heads = 4
ff_dim = 128

model = build_transformer_model(input_shape, num_heads, ff_dim)
model.summary()

# 訓練模型 epochs 120
early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)

model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=120, batch_size=64, verbose=1, callbacks=[early_stop])

# 預測
train_predict = model.predict(X_train)
test_predict = model.predict(X_test)

# 反歸一化預測結果
train_predict = scaler.inverse_transform(np.concatenate((train_predict, np.zeros((train_predict.shape[0], df2_scaled.shape[1]-1))), axis=1))[:, 0]
test_predict = scaler.inverse_transform(np.concatenate((test_predict, np.zeros((test_predict.shape[0], df2_scaled.shape[1]-1))), axis=1))[:, 0]

# 計算RMSE
rmse_train = math.sqrt(mean_squared_error(Y_train, train_predict))
print("訓練數據的RMSE:", rmse_train)

rmse_test = math.sqrt(mean_squared_error(Y_test, test_predict))
print("測試數據的RMSE:", rmse_test)

# 繪製預測結果
look_back = time_step

trainPredictPlot = np.empty_like(df2_scaled[:, 0])
trainPredictPlot[:] = np.nan
trainPredictPlot[look_back:len(train_predict) + look_back] = train_predict

testPredictPlot = np.empty_like(df2_scaled[:, 0])
testPredictPlot[:] = np.nan
testPredictPlot[len(train_predict) + (look_back * 2) + 1:len(df2_scaled) - 1] = test_predict

plt.plot(scaler.inverse_transform(df2_scaled)[:, 0], color='blue', label='ACT')
plt.plot(trainPredictPlot, color='orange', label='Training')
plt.plot(testPredictPlot, color='green', label='Testing')
plt.title('Transformer1 Predict')
plt.xlabel('Time')
plt.ylabel('Stock Price')
plt.legend()
plt.show()
                                          
X_train shape: (2007, 100, 7)
X_test shape: (1035, 100, 7)
Model: "model_3"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_4 (InputLayer)        [(None, 100, 7)]          0         
                                                                 
 positional_encoding_3 (Pos  (None, 100, 7)            0         
 itionalEncoding)                                                
                                                                 
 transformer_block_7 (Trans  (None, 100, 7)            2830      
 formerBlock)                                                    
                                                                 
 flatten_3 (Flatten)         (None, 700)               0         
                                                                 
 dense_19 (Dense)            (None, 1)                 701       
                                                                 
=================================================================
Total params: 3531 (13.79 KB)
Trainable params: 3531 (13.79 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
Epoch 1/120
32/32 [==============================] - 9s 193ms/step - loss: 0.2285 - val_loss: 0.0740
Epoch 2/120
32/32 [==============================] - 3s 97ms/step - loss: 0.0620 - val_loss: 0.0546
Epoch 3/120
32/32 [==============================] - 3s 90ms/step - loss: 0.0399 - val_loss: 0.0399
Epoch 4/120
32/32 [==============================] - 4s 141ms/step - loss: 0.0324 - val_loss: 0.0349
Epoch 5/120
32/32 [==============================] - 5s 168ms/step - loss: 0.0250 - val_loss: 0.0257
Epoch 6/120
32/32 [==============================] - 4s 128ms/step - loss: 0.0216 - val_loss: 0.0452
Epoch 7/120
32/32 [==============================] - 5s 153ms/step - loss: 0.0194 - val_loss: 0.0400
Epoch 8/120
32/32 [==============================] - 4s 138ms/step - loss: 0.0168 - val_loss: 0.0257
Epoch 9/120
32/32 [==============================] - 3s 93ms/step - loss: 0.0137 - val_loss: 0.0191
Epoch 10/120
32/32 [==============================] - 3s 87ms/step - loss: 0.0134 - val_loss: 0.0181
Epoch 11/120
32/32 [==============================] - 3s 89ms/step - loss: 0.0118 - val_loss: 0.0261
Epoch 12/120
32/32 [==============================] - 5s 154ms/step - loss: 0.0108 - val_loss: 0.0240
Epoch 13/120
32/32 [==============================] - 3s 97ms/step - loss: 0.0104 - val_loss: 0.0166
Epoch 14/120
32/32 [==============================] - 3s 102ms/step - loss: 0.0106 - val_loss: 0.0135
Epoch 15/120
32/32 [==============================] - 3s 97ms/step - loss: 0.0091 - val_loss: 0.0163
Epoch 16/120
32/32 [==============================] - 5s 153ms/step - loss: 0.0082 - val_loss: 0.0182
Epoch 17/120
32/32 [==============================] - 4s 130ms/step - loss: 0.0091 - val_loss: 0.0226
Epoch 18/120
32/32 [==============================] - 3s 90ms/step - loss: 0.0075 - val_loss: 0.0158
Epoch 19/120
32/32 [==============================] - 4s 120ms/step - loss: 0.0069 - val_loss: 0.0164
Epoch 20/120
32/32 [==============================] - 5s 144ms/step - loss: 0.0067 - val_loss: 0.0139
Epoch 21/120
32/32 [==============================] - 3s 104ms/step - loss: 0.0072 - val_loss: 0.0205
Epoch 22/120
32/32 [==============================] - 3s 99ms/step - loss: 0.0061 - val_loss: 0.0151
Epoch 23/120
32/32 [==============================] - 5s 149ms/step - loss: 0.0054 - val_loss: 0.0151
Epoch 24/120
32/32 [==============================] - 3s 99ms/step - loss: 0.0055 - val_loss: 0.0120
Epoch 25/120
32/32 [==============================] - 4s 120ms/step - loss: 0.0050 - val_loss: 0.0206
Epoch 26/120
32/32 [==============================] - 3s 101ms/step - loss: 0.0054 - val_loss: 0.0195
Epoch 27/120
32/32 [==============================] - 5s 145ms/step - loss: 0.0045 - val_loss: 0.0102
Epoch 28/120
32/32 [==============================] - 3s 102ms/step - loss: 0.0047 - val_loss: 0.0145
Epoch 29/120
32/32 [==============================] - 3s 98ms/step - loss: 0.0050 - val_loss: 0.0124
Epoch 30/120
32/32 [==============================] - 3s 101ms/step - loss: 0.0041 - val_loss: 0.0118
Epoch 31/120
32/32 [==============================] - 5s 165ms/step - loss: 0.0038 - val_loss: 0.0091
Epoch 32/120
32/32 [==============================] - 3s 103ms/step - loss: 0.0043 - val_loss: 0.0091
Epoch 33/120
32/32 [==============================] - 4s 116ms/step - loss: 0.0040 - val_loss: 0.0089
Epoch 34/120
32/32 [==============================] - 4s 132ms/step - loss: 0.0055 - val_loss: 0.0094
Epoch 35/120
32/32 [==============================] - 4s 119ms/step - loss: 0.0034 - val_loss: 0.0149
Epoch 36/120
32/32 [==============================] - 3s 102ms/step - loss: 0.0035 - val_loss: 0.0126
Epoch 37/120
32/32 [==============================] - 4s 121ms/step - loss: 0.0047 - val_loss: 0.0164
Epoch 38/120
32/32 [==============================] - 5s 143ms/step - loss: 0.0035 - val_loss: 0.0095
Epoch 39/120
32/32 [==============================] - 3s 101ms/step - loss: 0.0029 - val_loss: 0.0087
Epoch 40/120
32/32 [==============================] - 4s 115ms/step - loss: 0.0032 - val_loss: 0.0089
Epoch 41/120
32/32 [==============================] - 3s 108ms/step - loss: 0.0027 - val_loss: 0.0124
Epoch 42/120
32/32 [==============================] - 5s 167ms/step - loss: 0.0026 - val_loss: 0.0077
Epoch 43/120
32/32 [==============================] - 3s 91ms/step - loss: 0.0028 - val_loss: 0.0102
Epoch 44/120
32/32 [==============================] - 3s 95ms/step - loss: 0.0029 - val_loss: 0.0090
Epoch 45/120
32/32 [==============================] - 3s 103ms/step - loss: 0.0030 - val_loss: 0.0144
Epoch 46/120
32/32 [==============================] - 5s 175ms/step - loss: 0.0024 - val_loss: 0.0176
Epoch 47/120
32/32 [==============================] - 3s 93ms/step - loss: 0.0030 - val_loss: 0.0070
Epoch 48/120
32/32 [==============================] - 3s 94ms/step - loss: 0.0025 - val_loss: 0.0130
Epoch 49/120
32/32 [==============================] - 3s 101ms/step - loss: 0.0025 - val_loss: 0.0099
Epoch 50/120
32/32 [==============================] - 4s 141ms/step - loss: 0.0035 - val_loss: 0.0109
Epoch 51/120
32/32 [==============================] - 4s 119ms/step - loss: 0.0020 - val_loss: 0.0085
Epoch 52/120
32/32 [==============================] - 4s 124ms/step - loss: 0.0021 - val_loss: 0.0069
Epoch 53/120
32/32 [==============================] - 4s 142ms/step - loss: 0.0027 - val_loss: 0.0136
Epoch 54/120
32/32 [==============================] - 3s 94ms/step - loss: 0.0022 - val_loss: 0.0066
Epoch 55/120
32/32 [==============================] - 3s 91ms/step - loss: 0.0022 - val_loss: 0.0119
Epoch 56/120
32/32 [==============================] - 4s 117ms/step - loss: 0.0022 - val_loss: 0.0076
Epoch 57/120
32/32 [==============================] - 5s 175ms/step - loss: 0.0027 - val_loss: 0.0174
Epoch 58/120
32/32 [==============================] - 3s 98ms/step - loss: 0.0022 - val_loss: 0.0112
Epoch 59/120
32/32 [==============================] - 4s 118ms/step - loss: 0.0020 - val_loss: 0.0116
Epoch 60/120
32/32 [==============================] - 4s 138ms/step - loss: 0.0027 - val_loss: 0.0093
Epoch 61/120
32/32 [==============================] - 7s 213ms/step - loss: 0.0016 - val_loss: 0.0089
Epoch 62/120
32/32 [==============================] - 5s 164ms/step - loss: 0.0017 - val_loss: 0.0078
Epoch 63/120
32/32 [==============================] - 3s 95ms/step - loss: 0.0016 - val_loss: 0.0070
Epoch 64/120
32/32 [==============================] - 5s 154ms/step - loss: 0.0015 - val_loss: 0.0086
63/63 [==============================] - 2s 24ms/step
33/33 [==============================] - 1s 21ms/step
訓練數據的RMSE: 31.843369604565645
測試數據的RMSE: 33.50093618916143