Sıralı katman girişi katmanla uyumsuz: LSTM'de şekil hatası

Dec 22 2020

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

2 YoanB.M.Sc Dec 22 2020 at 21:18

GİRİŞ:

Sorun şu ki, modellemeniz bir 3B şekil girdisi bekliyor, (batch, sequence, features)ancak sizin X_trainaslı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 = 15ve sequence = 1, sizin durumunuzda dizi uzunluğudur bilmiyorum ama her şey olabilir.

MODEL:

Şimdi modelinde, keras input_shapebekliyoruz (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) Noneparti boyutu içindir. Yapmaya çalıştığın şeyin bu olduğunu sanmıyorum, bu yüzden yeniden şekillendirdikten input_shapesonra yeni diziye uyacak şekilde düzeltmen de gerekir .

1 mujjiga Dec 24 2020 at 21:27

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,quarterk
  • Herhangi bir gün için n ne yapacağı tahmin istediğiniz söz hakkından özellikleri verilen son 'm' günler yarasında ngü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 pnerede polduğu son kayıtlara ait hiçbir tahmin yoktur .
  • timeseries_dataset_from_arrayYö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 molduğu zamanda açılırız m. ySon 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>