LSTM ve uygulama yöntemleri (Part2, Tek Değişkenli LSTM Modelleri)
Tek Değişkenli LSTM Modelleri
LSTM modelleri, tek değişkenli zaman serisi tahmini problemlerinde etkili bir şekilde kullanılabilir.
Bu tür problemler, yalnızca tek bir gözlem dizisinden oluşur. Modelin amacı, geçmişteki verilerden öğrenerek bu dizinin bir sonraki adımını tahmin etmektir.
Bu bölümde, tek değişkenli zaman serisi tahmini için LSTM modelinin farklı türlerini uygulamalı olarak göstereceğiz.
Bu kısım altı başlığa ayrılmıştır:
- Veri Hazırlığı (Data Preparation)
- Temel LSTM (Vanilla LSTM)
- Katmanlı LSTM (Stacked LSTM)
- Çift Yönlü LSTM (Bidirectional LSTM)
- CNN-LSTM
- ConvLSTM
Bu modellerin her biri, bir adım ileriye tahmin (one-step forecasting) senaryosu için örneklenmiştir. Ancak bu yapıların tamamı, kolayca diğer zaman serisi tahmini türlerine uyarlanabilir; özellikle modelin giriş kısmında kullanılacak şekilde farklı amaçlara adapte edilebilir.
Veri Hazırlığı
Zaman serisi verimiz şu şekilde olsun (örneğin günlük sıcaklık değerleri gibi düşünülebilir):
raw_seq = [15, 18, 21, 24, 28, 30, 27, 25, 22, 20, 19, 17]
Bu diziyi, her seferinde 4 değer giriş ve 1 değer çıkış olacak şekilde bölmek istiyoruz. Yani:
X | y |
15, 18, 21, 24 | 28 |
18, 21, 24, 28 | 30 |
21, 24, 28, 30 | 27 |
… | … |
from numpy import array
# Zaman serisini örnek giriş/çıkışlara bölen fonksiyon
def split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
end_ix = i + n_steps
if end_ix >= len(sequence):
break
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)
# Örnek sıcaklık verisi (zaman serisi)
raw_seq = [15, 18, 21, 24, 28, 30, 27, 25, 22, 20, 19, 17]
# Zaman adımı sayısı
n_steps = 4
# Giriş/çıkış örneklerine böl
X, y = split_sequence(raw_seq, n_steps)
# Sonuçları yazdır
print("Giriş (X) → Tahmin Edilecek Değer (y):\n")
for i in range(len(X)):
print(f"{X[i]} → {y[i]}")
Giriş (X) → Tahmin Edilecek Değer (y):
[15 18 21 24] → 28
[18 21 24 28] → 30
[21 24 28 30] → 27
[24 28 30 27] → 25
[28 30 27 25] → 22
[30 27 25 22] → 20
[27 25 22 20] → 19
[25 22 20 19] → 17
Vanilla LSTM
Vanilla LSTM, tek bir gizli katmandan oluşan ve çıkış katmanında tahmin yapmak için kullanılan bir LSTM modelidir. Bu modelde, tek bir gizli katmandaki LSTM birimleri kullanılarak zaman serisi verisinin gelecekteki değerleri tahmin edilir.
Vanilla LSTM Modeli Tanımlaması
Tek değişkenli zaman serisi tahmini için bir Vanilla LSTM modelini şu şekilde tanımlayabiliriz:
# Modeli tanımla
# Modeli tanımla
model = Sequential()
model.add(LSTM(50, activation='relu', input_shape=(n_steps, n_features)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
Bu modelde gizli katmanda 50 LSTM birimi kullanıyoruz ve çıkış katmanı modelin tahmin edeceği değeri döndüren Dense katmanıdır.
Modelin tanımlanmasındaki en önemli nokta, giriş verisinin şeklidir. Yani model, her bir örneği zaman adımlarının sayısı ve özelliklerin sayısı açısından nasıl beklediğini öğrenir.
Biz burada tek değişkenli bir seri çalışıyoruz, bu nedenle özellik sayısı 1’dir (tek bir değişken için).
Veri Hazırlığı
Verilerimizi yukarda yazdığımız gibi hazırlayarak modelin anlayabileceği hale getireceğiz. Şimdi, veri hazırlık süreci ve modelin eğitilmesi kısmını tekrar gözden geçirelim.
from numpy import array
from keras.models import Sequential
from keras.layers import LSTM, Dense
# Tek değişkenli zaman serisini örneklere ayıran fonksiyon
def split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
end_ix = i + n_steps
if end_ix > len(sequence)-1:
break
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)
# Girdi dizisini tanımla
raw_seq = [15, 18, 21, 24, 28, 30, 27, 25, 22, 20, 19, 17]
n_steps = 4 # Zaman adımı sayısı
# Girdi dizisini örneklere ayır
X, y = split_sequence(raw_seq, n_steps)
# Şekli [örnekler, zaman adımları] olan X dizisini, [örnekler, zaman adımları, özellikler] şekline dönüştür
n_features = 1
X = X.reshape((X.shape[0], X.shape[1], n_features))
# Modeli tanımla
model = Sequential()
model.add(LSTM(50, activation='relu', input_shape=(n_steps, n_features)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# Modeli eğit
model.fit(X, y, epochs=200, verbose=0)
# Tahmin yapma
x_input = array([22, 20, 19, 17])
x_input = x_input.reshape((1, n_steps, n_features)) # Giriş verisini uygun şekle sok
yhat = model.predict(x_input, verbose=0)
# Sonucu yazdır
print(yhat)
[[15.342105]]
Bu örnekte model, verilen giriş verisi [22, 20, 19, 17]
için bir tahminde bulundu ve tahmin edilen değer yaklaşık olarak 15.34 oldu.
Stacked LSTM
Stacked LSTM, birden fazla gizli LSTM katmanının üst üste yerleştirilmesiyle oluşturulan bir modeldir. Bu modelde, her bir LSTM katmanı, zaman serisi verilerinin farklı özelliklerini öğrenir ve birden fazla katman, daha karmaşık ilişkileri modellemek için kullanılır.
Stacked LSTM Modeli
Bir LSTM katmanı, üç boyutlu bir girdi gerektirir ve LSTM katmanları varsayılan olarak çıktıyı iki boyutlu olarak üretir. Ancak, her bir zaman adımı için bir değer üretmesini sağlamak amacıyla return_sequences=True
argümanı kullanılır. Bu, gizli LSTM katmanından 3D çıktıyı alıp, bir sonraki katmana input olarak gönderir.
Bu özellik, Stacked LSTM modelini tanımlamamızı sağlar.
Stacked LSTM Modelinin Tanımlanması:
# Modeli tanımla
model = Sequential()
model.add(LSTM(50, activation='relu', return_sequences=True, input_shape=(n_steps, n_features)))
model.add(LSTM(50, activation='relu'))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
İlk katmanda, return_sequences=True
kullanarak ikinci LSTM katmanına 3D çıktı sağlıyoruz. Böylece her bir katman bir önceki katmanın çıktısını alır ve daha karmaşık bir model yapısı ortaya çıkar.
Stacked LSTM Uygulaması
Veri hazırlama, modelin eğitilmesi ve tahmin yapma adımlarını aşağıdaki örnekle gösterelim:
from numpy import array
from keras.models import Sequential
from keras.layers import LSTM, Dense
# Tek değişkenli zaman serisini örneklere ayıran fonksiyon
def split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
end_ix = i + n_steps
if end_ix > len(sequence)-1:
break
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)
# Girdi dizisini tanımla
raw_seq =[15, 18, 21, 24, 28, 30, 27, 25, 22, 20, 19, 17]
n_steps = 3 # Zaman adımı sayısı
# Girdi dizisini örneklere ayır
X, y = split_sequence(raw_seq, n_steps)
# Şekli [örnekler, zaman adımları] olan X dizisini, [örnekler, zaman adımları, özellikler] şekline dönüştür
n_features = 1
X = X.reshape((X.shape[0], X.shape[1], n_features))
# Modeli tanımla
model = Sequential()
model.add(LSTM(50, activation='relu', return_sequences=True, input_shape=(n_steps, n_features)))
model.add(LSTM(50, activation='relu'))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# Modeli eğit
model.fit(X, y, epochs=200, verbose=0)
# Tahmin yapma
x_input = array([25, 22, 20])
x_input = x_input.reshape((1, n_steps, n_features)) # Giriş verisini uygun şekle sok
yhat = model.predict(x_input, verbose=0)
# Sonucu yazdır
print(yhat)
[[18.197235]]
Bu örnekte model, verilen giriş verisi [25, 22, 20]
için tahminde bulundu ve tahmin edilen değer yaklaşık olarak 18.20 oldu. Modelin doğruluğu, kullanılan veriye ve eğitim sürecine bağlı olarak değişebilir.
Stacked LSTM, daha derin model yapıları kurarak, daha karmaşık zaman serisi verilerini modelleme yeteneği sağlar. Eğer başka katman türleri ya da model yapılarıyla ilgileniyorsanız, Bidirectional LSTM ya da ConvLSTM gibi farklı modelleri de inceleyebilirsiniz.
Bidirectional LSTM
Bidirectional LSTM (BiLSTM), bazı sıralı veri tahmin problemlerinde, LSTM modelinin giriş dizisini hem ileri hem de geri okumasına ve her iki yorumu birleştirmesine olanak tanır. Bu modelin avantajı, zaman serisinin geçmişi ve geleceği hakkında bilgi edinmesidir. Bidirectional LSTM, özellikle zaman serisi verisinde gelecekteki değerlerin tahmin edilmesinde faydalı olabilir.
Bidirectional LSTM Modeli Tanımlaması:
Bidirectional LSTM’yi uygulamak için, ilk gizli LSTM katmanını Bidirectional bir sarıcı (wrapper) katmanına sararız. Bu, modelin her iki yönde de öğrenmesini sağlar.
Bidirectional LSTM Modeli:
# Modeli tanımla
model = Sequential()
model.add(Bidirectional(LSTM(50, activation='relu'), input_shape=(n_steps, n_features)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
Burada, Bidirectional
sarıcı katmanı, LSTM katmanının hem ileri hem de geri yönlerini kullanarak her iki yönü de öğrenmesini sağlar.
Bidirectional LSTM Uygulaması
Aşağıdaki örnekle, Bidirectional LSTM modelini kullanarak zaman serisi tahminini nasıl yapacağımızı görelim:
from numpy import array
from keras.models import Sequential
from keras.layers import LSTM, Dense, Bidirectional
# Tek değişkenli zaman serisini örneklere ayıran fonksiyon
def split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
end_ix = i + n_steps
if end_ix > len(sequence)-1:
break
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)
# Girdi dizisini tanımla
raw_seq = [15, 18, 21, 24, 28, 30, 27, 25, 22, 20, 19, 17]
n_steps = 3 # Zaman adımı sayısı
# Girdi dizisini örneklere ayır
X, y = split_sequence(raw_seq, n_steps)
# Şekli [örnekler, zaman adımları] olan X dizisini, [örnekler, zaman adımları, özellikler] şekline dönüştür
n_features = 1
X = X.reshape((X.shape[0], X.shape[1], n_features))
# Modeli tanımla
model = Sequential()
model.add(Bidirectional(LSTM(50, activation='relu'), input_shape=(n_steps, n_features)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# Modeli eğit
model.fit(X, y, epochs=200, verbose=0)
# Tahmin yapma
x_input = array([25, 22, 20])
x_input = x_input.reshape((1, n_steps, n_features)) # Giriş verisini uygun şekle sok
yhat = model.predict(x_input, verbose=0)
# Sonucu yazdır
print(yhat)
[[18.63]]
Bu örnekte, model verilen giriş verisi [25, 22, 20]
için tahminde bulundu ve tahmin edilen değer yaklaşık olarak 18.63 oldu.
Bidirectional LSTM, özellikle sıralı verilere ve zaman serisi tahminlerine daha fazla bilgi ekleyerek, modelin tahmin kapasitesini artırır. İleri ve geri okuma yeteneği, modelin geçmiş ve gelecekteki verileri daha iyi öğrenmesine olanak tanır. Bu tür model, özellikle veri noktaları arasındaki karmaşık ilişkilerin bulunduğu durumlar için oldukça kullanışlıdır.
CNN-LSTM Modeli
CNN-LSTM modeli, Convolutional Neural Networks (CNN) ve Long Short-Term Memory (LSTM) ağlarının birleşimiyle oluşturulan bir hibrit sinir ağıdır. CNN’ler, özellikle görüntü verisiyle etkili çalışmak için geliştirilmişken, zaman serisi verisi gibi bir boyutlu veriyle de oldukça verimli bir şekilde özellik çıkarımı yapabilir. Bu modelde CNN, zaman serisi verisinin alt dizilerini işleyerek, LSTM ise bu diziler arasındaki zaman bağımlılıklarını öğrenir.
Modelin Genel Yapısı
- CNN Kısmı: CNN, giriş verisinin alt dizilerinden özellikler çıkarır. Bu işlem, Convolution ve MaxPooling katmanlarıyla yapılır.
- LSTM Kısmı: CNN tarafından çıkarılan özellikler daha sonra LSTM katmanına iletilir ve LSTM, bu özelliklerin zaman içindeki ilişkilerini öğrenir.
CNN-LSTM Modelinin Temel Adımları:
- Giriş Verisinin Yeniden Şekillendirilmesi: Zaman serisi verisi, küçük alt dizilere bölünür ve veri, 4 boyutlu bir dizi olan
[örnekler, alt_diziler, zaman_adımları, özellikler]
formatına dönüştürülür. - CNN Katmanı: TimeDistributed sarıcı katmanı kullanılarak, CNN her bir alt diziyi bağımsız olarak işler. Bu katman genellikle Conv1D ve MaxPooling1D katmanlarından oluşur.
- Düzleştirme (Flattening): CNN katmanından çıkan veriler düzleştirilir ve bu şekilde LSTM katmanına iletilir.
- LSTM Katmanı: LSTM, CNN tarafından çıkarılan özellikleri işler ve zaman içindeki bağıntıları öğrenir.
- Dense Katmanı: Son olarak Dense katmanı, tahmin yapılması için kullanılır.
CNN-LSTM Modeli Örneği (Univariate Time Series)
from numpy import array
from keras.models import Sequential
from keras.layers import LSTM, Dense, Flatten, TimeDistributed
from keras.layers import Conv1D,Conv2D, MaxPooling1D
# Univariate bir diziyi örneklere ayıran fonksiyon
def split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
end_ix = i + n_steps
if end_ix > len(sequence)-1:
break
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)
# Giriş dizisini tanımla
raw_seq = [15, 18, 21, 24, 28, 30, 27, 25, 22, 20, 19, 17]
n_steps = 4 # Zaman adımlarının sayısını seç
# Örnekler halinde böl
X, y = split_sequence(raw_seq, n_steps)
# [örnekler, zaman adımları] formatını [örnekler, alt diziler, zaman adımları, özellikler] formatına dönüştür
n_features = 1
n_seq = 2
n_steps = 2
X = X.reshape((X.shape[0], n_seq, n_steps, n_features))
# Modeli tanımla
model = Sequential()
model.add(TimeDistributed(Conv1D(filters=64, kernel_size=1, activation='relu'), input_shape=(None, n_steps, n_features)))
model.add(TimeDistributed(MaxPooling1D(pool_size=2)))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(50, activation='relu'))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# Modeli eğit
model.fit(X, y, epochs=500, verbose=0)
# Tahmin yap
x_input = array([27, 25, 22, 20])
x_input = x_input.reshape((1, n_seq, n_steps, n_features))
yhat = model.predict(x_input, verbose=0)
print(yhat)
Kod Açıklaması:
split_sequence()
Fonksiyonu: Bu fonksiyon, ham veriyi belirli bir zaman adım sayısına göre bölerek giriş-çıkış çiftleri oluşturur.- Veri Şekillendirme: Giriş verisi,
[örnekler, alt diziler, zaman adımları, özellikler]
formatına dönüştürülür. Bu formatta:- örnekler: Veri örneklerinin sayısı.
- alt diziler: Her alt dizi CNN’ye verilen veri parçalarıdır.
- zaman adımları: Her bir alt dizideki zaman adımı sayısı.
- özellikler: Verinin her bir zaman adımındaki özellik sayısı (bu örnekte 1, çünkü univariate bir veri).
- Model Yapısı:
- Conv1D: CNN katmanı, her alt diziden özellikler çıkarır.
- MaxPooling1D: Bu katman, özellik haritalarının boyutlarını yarıya indirerek en önemli özellikleri korur.
- Flatten: Çıkan veriler düzleştirilir ve LSTM katmanına aktarılır.
- LSTM: LSTM, CNN tarafından çıkarılan özellikleri işleyerek zaman içindeki bağıntıları öğrenir.
- Dense: Son katman, tahmin yapar.
Beklenen Çıktı:
Bu çıktı, modelin [27, 25, 22, 20
]
dizisinden sonra tahmin ettiği değerin yaklaşık 18.47 olduğunu gösteriyor.
Not: Sonuçlar, algoritmanın stokastik doğası nedeniyle farklılık gösterebilir. Bu yüzden örneği bir kaç kez çalıştırarak ortalama sonucu gözlemlemek faydalı olacaktır.
ConvLSTM Modeli
ConvLSTM, CNN-LSTM gibi, ancak her LSTM birimi içinde konvolüsyonel okuma yaparak veriyi işler. Genellikle iki boyutlu uzaysal-zamansal verilerle çalışmak için geliştirilmiş olsa da, tek boyutlu (univariate) zaman serisi tahminlerinde de kullanılabilir. Bu modelde, veriyi işlemek için her LSTM katmanının içine konvolüsyonel işlemler eklenir.
Aşağıda ConvLSTM kullanarak zaman serisi tahmini yapan örnek kodu bulabilirsiniz:
Adımlar:
- Veri hazırlığı:
- Veriyi, ConvLSTM katmanının gereksinimlerine uygun şekilde yeniden şekillendirin:
[samples, timesteps, rows, columns, features]
. - Bu örnekte, her örnek bir zaman serisi parçası olacak ve bu parçalar konvolüsyonel işlem için uygun şekilde yeniden düzenlenecek.
- Veriyi, ConvLSTM katmanının gereksinimlerine uygun şekilde yeniden şekillendirin:
- Model yapısı:
ConvLSTM2D
katmanını kullanarak veriyi işleyin.- Çıktıyı
Flatten()
ile düzleştirin ve ardından tahmin yapmak içinDense
katmanı ekleyin.
from numpy import array
from keras.models import Sequential
from keras.layers import ConvLSTM2D
from keras.layers import Flatten
from keras.layers import Dense
# split a univariate sequence into samples
def split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
# find the end of this pattern
end_ix = i + n_steps
# check if we are beyond the sequence
if end_ix > len(sequence)-1:
break
# gather input and output parts of the pattern
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)
# define input sequence
raw_seq = [15, 18, 21, 24, 28, 30, 27, 25, 22, 20, 19, 17]
# choose a number of time steps
n_steps = 4
# split into samples
X, y = split_sequence(raw_seq, n_steps)
# reshape from [samples, timesteps] into [samples, timesteps, rows, columns, features]
n_features = 1
n_seq = 2
n_steps = 2
X = X.reshape((X.shape[0], n_seq, 1, n_steps, n_features))
# define model
model = Sequential()
model.add(ConvLSTM2D(filters=64, kernel_size=(1,2), activation='relu', input_shape=(n_seq, 1, n_steps, n_features)))
model.add(Flatten())
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# fit model
model.fit(X, y, epochs=500, verbose=0)
# demonstrate prediction
x_input = array([27, 25, 22, 20])
x_input = x_input.reshape((1, n_seq, 1, n_steps, n_features))
yhat = model.predict(x_input, verbose=0)
print(yhat)
Açıklama:
- ConvLSTM2D: Bu katman, iki boyutlu konvolüsyonel işlemi (filtreleme) zaman serisi verileri üzerinde uygulayarak verinin uzamsal özelliklerini çıkarır.
- Flatten: Konvolüsyonel katmandan çıkan çıktıyı bir vektöre dönüştürür, böylece LSTM ile daha kolay işlenebilir hale gelir.
- Dense: Son tahmin için kullanılan çıkış katmanıdır.
Bu modelin çıktısı, tahmin edilen bir sonraki değeri döndürecektir.
[[18.780598]]
Bu modelle zaman serisi verinizi daha verimli bir şekilde işleyebilir ve tahminler yapabilirsiniz.
Son yorumlar