Gold Price Prediction with Advanced Time Series Approaches by Python แบบ งงๆ(Part3: Wavelet with ANN)

Tour Watcharachai
4 min readSep 17, 2020

--

Hello Again! นะครับ สำหรับ Part 3 นี้เราจะนำ Machine learning Model มาใช้ในการทำพยากรณ์กันครับ นั้นก็คือ Artificial Neural Networks (ANN)โดยเราจะมี Extension คือการนำ ANN มารวมร่างกับ Wavelet Analysis เพื่อทดสอบว่า

ANN กับ Wavelet-ANNจะสามารถทำนายราคาทองได้ไหม??

สำหรับ Part นี้ เราจะเน้นอธิบาย Setting ที่ใช้ ส่วน Algorithm ของ 2 ทฤษฎีนี้มีความซับซ้อนอยู่พอสมควร ซึ่งเราจะขอข้ามส่วนนี้ไปเพื่อความกระชับ สำหรับคนที่สนใจในตัว Algorithm เราแนะนำให้อ่าน Paper หรือ บทความต่างๆได้เลยเพราะเนื้อหาหลากหลายมาก

ขอบคุณภาพจาก https://www.vectorstock.com/

Coding!!

#Install Packages
import numpy as np
import pandas as pd
import pywt
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn import preprocessing
#SET A DATAFRAME
df = pd.read_csv('Gold15-18.csv')
df=df.rename(columns={'Adj Close':'Close'})
import datetime
Gold_price = df.Close
df['Dates'] = pd.to_datetime(df['Date'])
Dates = df['Dates'] #Date type
d = {'Date': Dates, 'Gold_price': Gold_price}
df = pd.DataFrame(data=d)
df=df.dropna()
df = df.set_index('Date')
len_tt=int(len(df.Gold_price)*0.8) #80% of data is training set
#Train/Test Gold_price
y_to_train = df.Gold_price.iloc[:len_tt]
y_to_test = df.Gold_price.iloc[len_tt:]

Lib ที่เราใช้ในครั้งนี้เราใช้ Sklearn กับ PyWavelet ในพยากรณ์ โดย Dataset เราแบ่งเป็น 80:20 เหมือน Part2 นะครับ ส่วนโมเดลในการทดลองครั้งนี้ เราแบ่งเป็น 2 อันคือ Pure ANN และ Wavelets-ANN และครั้งนี้เนื้อจากเนื้อหาค่อนข้างยาวเราจะขอนำเพียง sideways market เข้ามาในการคำนวณอย่างเดียวนะครับ

Pure ANN

def Preprocess_data(train, test, num_lags): #Get only dataframe
from sklearn import preprocessing
#Get features from lagged time series
train_zero = np.zeros((len(train),num_lags+1))
train_df_zero = pd.DataFrame(train_zero)
train_df_zero.iloc[:,0] = train.values

test_zero = np.zeros((len(test),num_lags+1))
test_df_zero = pd.DataFrame(test_zero)
test_df_zero.iloc[:,0] = test.values

for i in range(1, num_lags+1):
train_df_zero.iloc[:,i] = train.shift(-i).values
test_df_zero.iloc[:,i] = test.shift(-i).values

#Drop rows with NANs
train_data_clean = train_df_zero.dropna()
test_data_clean = test_df_zero.dropna()

#Standardize the input data
train_data_standardized = preprocessing.scale(train_data_clean)
test_data_standardized = preprocessing.scale(test_data_clean)

#Target variable
train_target = train_data_standardized[:,-1]
test_target = test_data_standardized[:,-1]

return train_target, test_target,train_data_standardized[:,:-1], test_data_standardized[:,:-1], test_data_clean
num_lags = 2 #Choose Lags for prediction
data = Preprocess_data(y_to_train,y_to_test,num_lags = num_lags) #2 lagged regressors
train_y, test_y, train_x, test_x = data[0], data[1], data[2], data[3]
non_stand_data = data[4]

ขั้นตอนแรกเราในการทำ Predictive Model โดยใช้ ANN เราต้องทำการ Preprocessing Data ให้เป็น Standardize ก่อนเนื่องจาก ช่วยลด Bias ที่เกิดขึ้นได้, เวลาในการคำนวณลดลง และยังช่วยให้เราได้ลองเปลี่ยน fucntion ในการสร้างโมเดลอีกด้วย รวมทั้ง Setup explanatory variables & Dependent Variable ขึ้นมา ซึ่งตาม Code นี้ผมตั้ง lags เท่ากับ 2 หมายความว่า เราใช้ข้อมูลของ 2 periods ที่แล้วมาเป็น Explanatory variables

def predict_ANN(train_x,train_y,hidden_layer_sizes=(100, ), activation='relu', solver='adam', alpha=0.0001, batch_size='auto', learning_rate='constant', learning_rate_init=0.001, power_t=0.5, max_iter=200, shuffle=True, random_state=None, tol=0.0001, verbose=False, warm_start=False, momentum=0.9, nesterovs_momentum=True, early_stopping=False, validation_fraction=0.1, beta_1=0.9, beta_2=0.999, epsilon=1e-08):import sklearn
from sklearn.neural_network import MLPRegressor
from sklearn import preprocessing
import math
#Build the network model
mlp = MLPRegressor(hidden_layer_sizes=hidden_layer_sizes, activation=activation, solver=solver, alpha=alpha, batch_size=batch_size, learning_rate=learning_rate, learning_rate_init=learning_rate_init, power_t=power_t, max_iter=max_iter, shuffle=shuffle, random_state=random_state, tol=tol, verbose=verbose, warm_start=warm_start, momentum=momentum, nesterovs_momentum=nesterovs_momentum, early_stopping=early_stopping, validation_fraction=validation_fraction, beta_1=beta_1, beta_2=beta_2, epsilon=epsilon)
#Fit the model to the training data
mlp.fit(train_x, train_y)
#Predictions
preds = mlp.predict(test_x)
return preds

สำหรับการสร้างโมเดล จริงๆมีรายละเอียดที่สำคัญค่อนข้างเยอะ เช่น การตั้งค่า จำนวนของ Neurons ใน Hidden Layer, Function ที่ใช้ในการคำนวณ, Optimization in Parameters และอีกมากมาย (สำหรับผู้เริ่มต้นเราแนะนำให้อ่านลิ้งค์นี้ได้เลย) นอกจากนี้ยังมีกระบวนการ Hyperparameters tuning และอีกมากมาย

หลังจากเราได้ Predicted Values มาแล้วให้เราทำการ De-standardize ให้กลับมาเป็นค่าปกติแล้วค่อยนำมาคำควนค่า Error

Setting For Prediction เราตั้งค่าหลายๆค่าตาม Default เลย เช่น จำนวน Neuron ไว้ที่ 100, โดยเราใช้ Rectified Linear Unit function (ReLU)ในการสร้างโมเดลเพราะการคิดเป็น linear กับ numeric values สามารถเทียบกันได้เลย

Wavelets — ANN

สำหรับ Wavelets transforms with ANN เราจะเริ่มที่เปลี่ยน DATA ด้วยวิธีการ Daubechies Wavelet Transform ที่เท่ากับ 1 เพราะว่าจำนวน dataset เราสามารถทำได้แค่ 1 ถ้าเป็น data อื่นสามารถปรับเปลี่ยนได้โดยหาได้จาก function ของ Pywavelets เลย จากนั้นเราก็ทำการ Standardize ก่อนจะนำเข้าสู่ prediction หลังจากได้ค่า Prediction มาแล้วให้เราทำ De-standardize ก่อนจะสร้างตัวแปรพารามิเตอร์สำหรับการคำนวณค่าพยากรณ์ด้วย Wavelets ใหม่ ก่อนจะคำนวณค่า Error ที่เกิดขึ้น

#Transform with whole dataset
"""Continueuous Wavelet Decomposition"""
#Decompose training data using Daubechies Wavelet Transform
c1_Gold_price = pywt.swt(np.ravel(df.Gold_price[1:].values), 'db1', level = 1,start_level =0)
#Contains list +tuple giving both continuous and inv conti
#Decompose all data using Daubechies Wavelet Transform
data_pad = np.lib.pad(np.ravel(df.Gold_price[1:].values), (0, len(df)-len_tt), 'constant', constant_values=0)
data_pad = np.trim_zeros(data_pad) #trim 0
c1 = pywt.swt(data_pad, 'db1', level = 1)
wave_data=c1_Gold_price[0][0] #d1 transform
wave_data_ins = c1_Gold_price[0][1] #ins_transform
#Seperate train and test
wave_test=wave_data[len_tt:]
wave_train =wave_data[:len_tt]
#Preprocess data
wav_clean_data=Preprocess_data(wave_train, wave_test, num_lags = 3)
#Assign Values
train_yw, test_yw, train_xw, test_xw = wav_clean_data[0], wav_clean_data[1], wav_clean_data[2], wav_clean_data[3]
non_stand_wdata = wav_clean_data[4]
#Prediction
result_WANN = predict_ANN(train_xw, train_yw)
#De-standardize value
final_result_WANN = result_WANN * non_stand_wdata.iloc[:,-1].std() + non_stand_wdata.iloc[:,-1].mean()
#From Decomposition with wavelet db1 (data_pad , c1), so assign values
(cA1,cD1)=c1[0][0], c1[0][1]
#Recreate forecasted coeff
cA1for_recon_nn = cA1.copy()
cA1for_recon_nn = cA1for_recon_nn[2:]
cA1for_recon_nn[len_tt:] = final_result_WANN
cA1for_recon_nn = pywt.iswt([(cA1for_recon_nn, np.zeros(len(cA1for_recon_nn)))], 'db1')
predicted_adj_value = cA1for_recon_nn #Adjusted Values
#Seperate test
predicted_adj_value[:250].shape
ANN['WANN'] = predicted_adj_value[:247] #Add values
#Plot
ax = Gold_price.plot(label='Original data')
ANN.plot(ax=ax, figsize = (14,8),kind='line' ,label='20% Out-of-Sample')
plt.legend()
plt.show()

Result!!

สำหรับการทดลองหลังจากปรับค่า Lags, Function ที่ใช้ในการคำนวณ, Optimizer ใน ANN, Function ของ Wavelets เราพบว่า “ครั้งนี้เราได้ผลว่า Pure-ANN มีความสามารถในการทำนายที่ดีกว่า Wavelets-ANN ด้วยค่า MAPE 0.49% เทียบกับ 3.43%” ซึ่งการ Plot รูปออกมาจะเห็นว่า Wavelets จะทำให้ค่าที่ออกมาช้ากว่าปกติ

https://www.researchgate.net/publication/326503958_An_Algorithm_of_Daubechies_Wavelet_Transform_in_the_Final_Field_When_Processing_Speech_Signals

คำนิยามของ Wavelets และ ANN เราแนะนำให้อ่านจาก Paper และสามารถค้นหาเพิ่มเติมได้จาก youtube และ Website ต่างๆได้เลย เราจะแปะลิ้งค์ที่สอน Intro ไว้ให้นะครับ จริงๆเนื้อหาของตัว Wavelets และ ANN นั้นใหญ่มาก สามารถปรับเปลี่ยนจุด Optimal ได้ดีขึ้นกว่าโมเดลนี้(จริงๆเราทำอันนี้ขึ้นมาเพื่อเป็นตัวอย่างเพราะน่าสนใจดี แต่การปรับค่าบางค่าเราอาจจะยังไม่ถึงขั้น ทั้งใน Wavelet เช่น function ที่ใช้ในการ decompose สามารถใช้ discrete in continuous time ได้ และ ANN ที่สามารถปรับแต่งให้มี layer ที่หลายหลากและซับซ้อนขึ้น

บทความต่อไปเราจะปิดท้ายกันที่ TBATS model ซึ่งเราก็ยังไม่เคยศึกษาโมเดลนี้มาก่อนเลยอาจจะใช้เวลานิดนึงนะครับ ขอบคุณสำหรับการเสพงานชิ้นนี้ ถ้ามีท่านใดสนใจอยากจะปรับเปลี่ยน หรือ มีข้อสงสัยตรงไหน สามารถเข้ามา Discuss กันได้นะครับ เพราะเราเองเพิ่งใช้โมเดลนี้ครั้งแรก

ขอบคุณรูปภาพ :https://www.btelligent.com/en/

--

--