Iwan Ahmadi Lubis
LSTM (Long Short-Term Memory) merupakan varian dari Recurrent Neural Network (RNN) yang dirancang khusus untuk mengatasi masalah vanishing gradient yang sering terjadi pada RNN biasa.
Salah satu kelebihan LSTM adalah sangat baik dalam menagani data sekunsial misalnya data cuaca, prediksi harga, bahasa alami dan lain-lain.
Dalam portofolio ini akan dijabarkan langkah-langkah implementasi RNN multi features dengan studi kasus prediksi harga saham INDOSAT menggunakan data train dari bulan September 2023 sampai dengan September 2024
Tujuan utama dari portofolio ini adalah melakukan prediksi harga saham INDOSAT. Perlu dipahami bahwa harga saham dipengaruhi oleh banyak sekali faktor seperti data historis (technical), rasio keuangan perusahaan, kinerja perusahaan, kebijakan ekonomi pemerintah, sentimen pasar, dan lain-lain. Untuk menyederhanakan masalah, pada portofolio ini prediksi saham hanya akan menggunakan data historis sehingga tingkat akurasi prediksi yang dihasilkan cukup rendah.
Evaluasi model akan menggunakan Root Mean Squared Error.
Data yang akan digunakan adalah data historis saham INDOSAT dari bulan September 2023 sampai bulan Oktober 2024 yang terdiri dari
Library yang digunakan
drive.mount('/content/drive') # mount google drive df |
Summary Singkat dari Data Frame
df.describe() |
Data Frame Info
df.info() |
Untuk meningkatkan performansi model maka pada LSTM perlu dilakukan normalisasi data, biasanya data numerik diskalakan menjadi nilai antara 0 dan 1. Terkait hal ini maka perlu dilakukan perubahan type data dari int64 ke float64.
Selanjutnya perlu pastikan tidak ada data yang kosong.
df.isnull().sum() |
Melihat korelasi antar features dengan target (Terakhir). Karena Tanggal tidak bisa diproses maka Tanggal akan di-drop.
df_drop = df.drop(['Tanggal'], axis=1) |
Data Frame setelah Tanggal di drop
df_drop.info() |
Menampilkan korelasi menggunakan heatmap
correlation_matrix = df_drop.corr() # Buat heatmap korelasi plt.figure(figsize=(12, 8)) sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0) plt.title("ISAT HeadMap") plt.show() |
Dari heatmap dapat terlihat bahwa semua features berpengaruh terhadap nilai Terakhir.
Library yang digunakan
- MinMaxScaler dari sklearn.preprocessing yang digunakan untuk skala nilai numerik
- Sequential dari tensorflow.keras.models
Dalam tahap eksplorasi data diketahui bahwa features yang digunakan adalah Pembukaan, Tertinggi, Terendah, Volume dan Perubahan. Untuk kebutuhan normalisasi data maka tipe int64 akan diubah menjadi float64. Dari info data frame maka yang perlu diubah adalah Terakhir, Pembukaan, Tertinggi dan Terendah.
df_type = df_drop.astype({'Terakhir': 'float64', 'Pembukaan': 'float64', 'Tertinggi': 'float64', 'Terendah': 'float64'}) |
Data Frame setelah Tipe diubah
df_type.info() |
Telah disebutkan sebelumnya bahwa LSTM menggunakan data historis dalam membuat prediksi. Dalam implementasinya, penggunaan data historis ini disebut dengan data window, di mana kita akan mengambil potongan data historis dengan jumlah tertentu (window size) sebagai sampel input untuk model LSTM.
Contoh:
Misalkan kita memiliki data dari tanggal 1 sampai tanggal 10 dengan window size 5. Maka untuk memprediksi nilai pada tanggal 11 kita akan menggunakan sampel input nilai dari tanggal 6 sampai tanggal 10. Apabila window size nya 3 maka nilai yang digunakan dari tanggal 8 sampai tanggal 10.
Berikutnya akan dilakukan normalisasi data numerik, tujuannya untuk meningkatkan performansi dan akurasi pada saat pelatihan. Normalisasi akan menggunakan MinMaxScaler dengan rentang dari 0 sampai 1.
Siapkan data set training terlebih dahulu di mana akan digunakan data 30 hari sebelumnya untuk prediksi harga.
window_size = 30 training_set_X = df_type.values training_set_y = df_type.iloc[window_size:, 0].values # target adalah kolom Terakhir, skip window size (dalam hal ini 5) data pertama scaler = MinMaxScaler(feature_range=(0, 1)) # menggunakan MinMaxScaler, dari 0 sampai 1 normalisasi_data_train_X = scaler.fit_transform(training_set_X) normalisasi_data_train_Y = scaler.fit_transform(training_set_y.reshape(-1, 1)) |
Fungsi untuk membuat data window
def create_datawindow(dataset, size=1): dataWindow = [] for i in range(len(dataset)-size): a = dataset[i:(i+size), :] dataWindow.append(a) return np.array(dataWindow) |
Membuat data training
X_train = create_datawindow(normalisasi_data_train_X, window_size) y_train = normalisasi_data_train_Y |
Akan digunakan model Sequential yang merupakan model neural network yang paling sederhana dan sering digunakan.
Library yang digunakan
- Sequential dari Keras sebagai model
- LSTM dan Dense dari Keras sebagai layer
Model yang akan digunakan adalah Sequential dengan adam optimizer (Optimizer: Algoritma yang digunakan untuk memperbarui bobot model selama proses pelatihan)
# menggunakan 3 layer, 61 neuron di setiap layer model.compile(optimizer='adam', loss='mean_squared_error') |
Berikutnya akan dilakukan pelatihan model dengan epoch bernilai 224 dan batch_size bernilai 32.
epoch: adalah jumlah iterasi pelatihan yang dilakukan. 1 kali iterasi terdiri dari inisialiasi bobot, Forward Pass, perhitungan Loss, Backpropagation dan update bobot.
batch_size: Menentukan jumlah sampel data yang akan diproses dalam satu langkah pelatihan.
model.fit(X_train, y_train, epochs=224, batch_size=32) |
Menyiapkan data test yaitu data historis harga saham ISAT mulai dari bulan Agustus 2024 sampai bulan Oktober 2024. Data diload dari google drive.
df_test = pd.read_csv('/content/drive/MyDrive/bisaai/data_test.csv') # load data test df_test_drop = df_test.drop(['Tanggal'], axis=1) # drop Tanggal df_test_type = df_test_drop.astype({'Terakhir': 'float64', 'Pembukaan': 'float64', 'Tertinggi': 'float64', 'Terendah': 'float64'}) test_set_X = df_test_type.values test_set_y = df_test_type.iloc[window_size:, 0].values # target adalah kolom Terakhir, skip window size (dalam hal ini 5) data pertama scaler = MinMaxScaler(feature_range=(0, 1)) # menggunakan MinMaxScaler, dari 0 sampai 1 normalisasi_data_test_X = scaler.fit_transform(test_set_X) normalisasi_data_test_Y = scaler.fit_transform(test_set_y.reshape(-1, 1)) X_test = create_datawindow(normalisasi_data_test_X, window_size) y_test = normalisasi_data_test_Y |
Selanjutnya lakukan prediksi harga saham.
prediksi = model.predict(X_test) prediksi = prediksi.reshape(-1,1) prediksi = scaler.inverse_transform(prediksi) |
inverse_transform dilakukan untuk mengembalikan nilai dalam skala ke nilai normal
Dari hasil prediksi selanjut tampilkan perbandingan harga prediksi dan harga aktual.
plt.figure(figsize=(12, 6)) plt.plot(test_set_y, label='Harga Aktual') plt.plot(prediksi, label='Harga Prediksi') plt.legend() plt.title('Perbandingan Harga Aktual dan Prediksi') plt.xlabel('') plt.ylabel('Harga Saham') plt.show() |
Evaluasi model menggunakan Root Mean Squared Error (RMSE)
from sklearn import metrics rmse = metrics.root_mean_squared_error(test_set_y, prediksi) print("Root Mean Squared Error: ", rmse) |
Nilai RSME menunjukkan selisih antara nilai aktual dan prediksi masih sangat besar. Untuk meningkatkan akurasi feature dari data prinsipal perlu ditambahkan.