Sıralı katman girişi katmanla uyumsuz: LSTM'de şekil hatası
Sinir ağlarında yeniyim ve bunları diğer makine öğrenimi yöntemleriyle karşılaştırmak için kullanmak istiyorum. Yaklaşık iki yıllık bir aralığa sahip çok değişkenli bir zaman serisi verisine sahibim. LSTM'yi kullanarak diğer değişkenlere dayanarak önümüzdeki birkaç gün için 'y'yi tahmin etmek istiyorum. Verilerimin son günü 2020-07-31.
df.tail()
y holidays day_of_month day_of_week month quarter
Date
2020-07-27 32500 0 27 0 7 3
2020-07-28 33280 0 28 1 7 3
2020-07-29 31110 0 29 2 7 3
2020-07-30 37720 0 30 3 7 3
2020-07-31 32240 0 31 4 7 3
LSTM modelini eğitmek için, verileri eğitim ve test verilerine de böldüm.
from sklearn.model_selection import train_test_split
split_date = '2020-07-27' #to predict the next 4 days
df_train = df.loc[df.index <= split_date].copy()
df_test = df.loc[df.index > split_date].copy()
X1=df_train[['day_of_month','day_of_week','month','quarter','holidays']]
y1=df_train['y']
X2=df_test[['day_of_month','day_of_week','month','quarter','holidays']]
y2=df_test['y']
X_train, y_train =X1, y1
X_test, y_test = X2,y2
LSTM ile çalıştığım için biraz ölçeklendirme gerekiyor:
scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
Şimdi, zor kısma gelelim: model.
num_units=50
activation_function = 'sigmoid'
optimizer = 'adam'
loss_function = 'mean_squared_error'
batch_size = 10
num_epochs = 100
# Initialize the RNN
regressor = Sequential()
# Adding the input layer and the LSTM layer
regressor.add(LSTM(units = num_units, return_sequences=True ,activation = activation_function,
input_shape=(X_train.shape[1], 1)))
# Adding the output layer
regressor.add(Dense(units = 1))
# Compiling the RNN
regressor.compile(optimizer = optimizer, loss = loss_function)
# Using the training set to train the model
regressor.fit(X_train_scaled, y_train, batch_size = batch_size, epochs = num_epochs)
Ancak aşağıdaki hatayı alıyorum:
ValueError: Input 0 of layer sequential_11 is incompatible with the layer: expected ndim=3, found
ndim=2. Full shape received: [None, 5]
Girdinin parametrelerini veya şeklini nasıl seçtiğimizi anlamıyorum. Bazı videolar gördüm ve bazı Github sayfalarını okudum ve herkes LSTM'yi farklı bir şekilde çalıştırıyor gibi görünüyor, bu da uygulamayı daha da zorlaştırıyor. Önceki hata muhtemelen şekilden geliyor, ancak bunun dışında her şey doğru mu? Ve bunu işe yarayacak şekilde nasıl düzeltebilirim? Teşekkürler
DÜZENLEME: Bu benzer soru sorunumu çözmüyor .. Çözümü oradan denedim
x_train = X_train_scaled.reshape(-1, 1, 5)
x_test = X_test_scaled.reshape(-1, 1, 5)
(X_test ve y_test'imde yalnızca bir sütun vardır). Ve çözüm de işe yaramıyor gibi görünüyor. Bu hatayı şimdi alıyorum:
ValueError: Input 0 is incompatible with layer sequential_22: expected shape=
(None, None, 1), found shape=[None, 1, 5]
Yanıtlar
GİRİŞ:
Sorun şu ki, modellemeniz bir 3B şekil girdisi bekliyor, (batch, sequence, features)
ancak sizin X_train
aslında bir veri çerçevesi dilimi, yani bir 2B dizi:
X1=df_train[['day_of_month','day_of_week','month','quarter','holidays']]
X_train, y_train =X1, y1
Sütunlarınızın özellikleriniz olması gerektiğini varsayıyorum, bu nedenle genellikle yaptığınız şey df'nizin "yığın dilimlerini" böyle bir X_train
şeye benzemek için:
İşte sahte bir 2D veri seti şekli (15,5)
:
data = np.zeros((15,5))
array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
Bir toplu iş boyutu eklemek için yeniden şekillendirebilirsiniz, örneğin (15,1,5)
:
data = data[:,np.newaxis,:]
array([[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.]]])
Aynı veriler, ancak farklı bir şekilde sunulur. Şimdi bu örnekte, batch = 15
ve sequence = 1
, sizin durumunuzda dizi uzunluğudur bilmiyorum ama her şey olabilir.
MODEL:
Şimdi modelinde, keras
input_shape
bekliyoruz (batch, sequence, features)
bunu geçerken,:
input_shape=(X_train.shape[1], 1)
Bu, modellediğiniz şeydir: (None, Sequence = X_train.shape[1] , num_features = 1)
None
parti boyutu içindir. Yapmaya çalıştığın şeyin bu olduğunu sanmıyorum, bu yüzden yeniden şekillendirdikten input_shape
sonra yeni diziye uyacak şekilde düzeltmen de gerekir .
LSTM kullanarak çözdüğünüz çok değişkenli bir regresyon problemidir. Koda geçmeden önce ne anlama geldiğini gerçekten görelim
Sorun bildirimi:
- Günlerdir günlük
5
özelliğiniz varholidays, day_of_month, day_of_week,month,quarter
k
- Herhangi bir gün için n ne yapacağı tahmin istediğiniz söz hakkından özellikleri verilen son 'm' günler
y
arasından
gününde
Pencere veri kümesi oluşturma:
- Modelimize beslemek istediğimiz günlerin sayısına ilk önce karar vermemiz gerekiyor. Buna sıra uzunluğu denir (bu örnek için 3'e sabitleyelim).
- Tren ve test veri kümesini oluşturmak için sıra uzunluğu günlerini bölmemiz gerekir. Bu, pencere boyutunun sıra uzunluğu olduğu kayan bir pencere kullanılarak yapılır.
- Gördüğünüz gibi , sıra uzunluğunun
p
neredep
olduğu son kayıtlara ait hiçbir tahmin yoktur . timeseries_dataset_from_array
Yöntem kullanarak pencere veri seti oluşturma işlemini yapacağız .- Daha ileri bilgiler için resmi tf belgelerini takip edin .
LSTM Modeli
Yani elde etmek istediğimiz şey resimli aşağıda gösterilmektedir:

Her bir LSTM hücresi açma işlemi için, günün 5 özelliğini geçiyoruz ve sıra uzunluğunun m
olduğu zamanda açılırız m
. y
Son günün geleceğini tahmin ediyoruz .
Kod:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, models
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
# Model
regressor = models.Sequential()
regressor.add(layers.LSTM(5, return_sequences=True))
regressor.add(layers.Dense(1))
regressor.compile(optimizer='sgd', loss='mse')
# Dummy data
n = 10000
df = pd.DataFrame(
{
'y': np.arange(n),
'holidays': np.random.randn(n),
'day_of_month': np.random.randn(n),
'day_of_week': np.random.randn(n),
'month': np.random.randn(n),
'quarter': np.random.randn(n),
}
)
# Train test split
train_df, test_df = train_test_split(df)
print (train_df.shape, test_df.shape)\
# Create y to be predicted
# given last n days predict todays y
# train data
sequence_length = 3
y_pred = train_df['y'][sequence_length-1:].values
train_df = train_df[:-2]
train_df['y_pred'] = y_pred
# Validataion data
y_pred = test_df['y'][sequence_length-1:].values
test_df = test_df[:-2]
test_df['y_pred'] = y_pred
# Create window datagenerators
# Train data generator
train_X = train_df[['holidays','day_of_month','day_of_week','month','month']]
train_y = train_df['y_pred']
train_dataset = tf.keras.preprocessing.timeseries_dataset_from_array(
train_X, train_y, sequence_length=sequence_length, shuffle=True, batch_size=4)
# Validation data generator
test_X = test_df[['holidays','day_of_month','day_of_week','month','month']]
test_y = test_df['y_pred']
test_dataset = tf.keras.preprocessing.timeseries_dataset_from_array(
test_X, test_y, sequence_length=sequence_length, shuffle=True, batch_size=4)
# Finally fit the model
regressor.fit(train_dataset, validation_data=test_dataset, epochs=3)
Çıktı:
(7500, 6) (2500, 6)
Epoch 1/3
1874/1874 [==============================] - 8s 3ms/step - loss: 9974697.3664 - val_loss: 8242597.5000
Epoch 2/3
1874/1874 [==============================] - 6s 3ms/step - loss: 8367530.7117 - val_loss: 8256667.0000
Epoch 3/3
1874/1874 [==============================] - 6s 3ms/step - loss: 8379048.3237 - val_loss: 8233981.5000
<tensorflow.python.keras.callbacks.History at 0x7f3e94bdd198>