ошибка значения рекуррентной нейронной сети: найден массив с dim 3. Ожидаемая оценка <= 2

#python #lstm

#python #lstm

Вопрос:

Я запускаю модель LSTM, GRU и bilstm, используя следующий код

 # Create BiLSTM model
def create_model_bilstm(units):
    model = Sequential()
    model.add(Bidirectional(LSTM(units = units,                             
              return_sequences=True),
              input_shape=(X_train.shape[1], X_train.shape[2])))
    #model.add(Bidirectional(LSTM(units = units)))
    model.add(Dense(1))
    #Compile model
    model.compile(loss='mse', optimizer='adam')
    return model

# Create LSTM or GRU model
def create_model(units, m):
    model = Sequential()
    model.add(m (units = units, return_sequences = True,
                input_shape = [X_train.shape[1], X_train.shape[2]]))
    model.add(Dropout(0.1))
    #model.add(m (units = units))
    #model.add(Dropout(0.2))
    model.add(Dense(units = 1))
    #Compile model
    model.compile(loss='mse', optimizer='adam')
    return model

# BiLSTM
model_bilstm = create_model_bilstm(20)

# GRU and LSTM
model_gru = create_model(50, GRU)
model_lstm = create_model(20, LSTM)

# Fit BiLSTM, LSTM and GRU
def fit_model(model):
    early_stop = EarlyStopping(monitor = 'val_loss',
                                               patience = 100)
    
    history = model.fit(X_train, y_train, epochs = 700,  
                        validation_split = 0.2, batch_size = 32, 
                        shuffle = False, callbacks = [early_stop])
    return history

history_bilstm = fit_model(model_bilstm)
history_lstm = fit_model(model_lstm)
history_gru = fit_model(model_gru)
  

Все это проходит гладко и выводит мои графики потерь. но когда дело доходит до прогнозов, я запускаю следующий код

 # Make prediction
def prediction(model):
    prediction = model.predict(X_test)
    prediction = scaler_y.inverse_transform(prediction)
    return prediction

prediction_bilstm = prediction(model_bilstm)
prediction_lstm = prediction(model_lstm)
prediction_gru = prediction(model_gru)
  

и я получаю следующую ошибку

    ValueError Traceback (most recent call last)
<ipython-input-387-9d45f01ae2a2> in <module>
      5     return prediction
      6 
----> 7 prediction_bilstm = prediction(model_bilstm)
      8 prediction_lstm = prediction(model_lstm)
      9 prediction_gru = prediction(model_gru)

<ipython-input-387-9d45f01ae2a2> in prediction(model)
      2 def prediction(model):
      3     prediction = model.predict(X_test)
----> 4     prediction = scaler_y.inverse_transform(prediction)
      5     return prediction

                         ...

    ValueError: Found array with dim 3. Estimator expected <= 2.
  

Я предполагаю, что это как-то связано с моей формой X_test на основе других сообщений, которые я прочитал, поэтому я попытался изменить ее на 2d, но получил другую ошибку, сообщающую мне, что «ожидаемый двунаправленный ввод_3_input имеет 3 измерения, но снова получил массив с формой (62, 36)» в строке 7.

Что я делаю не так и как я могу это исправить?

Объяснение данных: Итак, я пытаюсь предсказать скорость сброса (целевую переменную), используя уровни грунтовых вод (34 объекта), осадки и температуру в качестве входных данных, что дает мне в общей сложности 36 объектов. Мои данные находятся в месячном разрешении. Я использую 63 наблюдения для своего теста (5-летний pred), а остальные для своего поезда.

Комментарии:

1. не могли бы вы также указать форму X_test и X_train

2. @SrikarManthatti X_test.shape = (62, 1, 36) и X_train = (316, 1, 36)

3. Я считаю, что это, безусловно, связано с формой данных, поскольку для bilstm вы тренируетесь с входными измерениями (316,1) и при прогнозировании вы проходите (62,1,36). Могу ли я узнать, над какими данными вы работаете, что означают эти второе (1) и третье измерения (36) в ваших данных? Если все в порядке, вы можете вставить изображение данных и поговорить об этом.

4. @SrikarManthatti я добавил объяснение для своих данных. Исходя из вашего комментария, означает ли это, что моя перестройка неверна?

5. Отлично!!! итак, согласно вашему объяснению, я предполагаю, что форма вашего X_train должна быть (316,36), y_train (316,1), а тест должен быть X_test(63,36), а Y_test должен быть (63,1)

Ответ №1:

Что вы делаете не так?Предположим, что ваши входные данные имеют форму X_train.shape = [d0,d1,d2] , затем после настройки вашей BiLSTM-модели, например

 from tensorflow.keras import Sequential
from tensorflow.keras.layers import Bidirectional,LSTM,Dense

model = tf.keras.Sequential()
model.add(
   tf.keras.layers.Bidirectional(
      tf.keras.layers.LSTM(
         units = 10,                             
         return_sequences=True),
         input_shape=(d1, d2)
         )
      )
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
  

мы можем проверить входные и выходные формы, ожидаемые вашей моделью, с помощью

 >>model.input.shape
TensorShape([None, d1, d2])
>>model.output.shape
TensorShape([None, d1, 1])
  

Итак, ваша модель ожидает ввода формы (n_batch,d1,d2) , где n_batch — размер пакета данных, и возвращает форму (n_batch,d1,1) , таким образом, 3d-тензор.

Теперь, если вы предоставите 3d-тензор своей модели, model.prediction метод -успешно вернет 3d-тензор, однако sklearn.preprocessing.StandardScaler.inverse_transform работает только для 2d-данных, вот почему он говорит

 ValueError: Found array with dim 3. Estimator expected <= 2.
  

С другой стороны, если вы сначала измените свои данные на 2d, то model.prediction пожалуетесь, потому что они настроены на ожидание 3d-тензора.

Как вы можете это исправить?Для получения дополнительной помощи в исправлении вашего кода вам нужно будет предоставить нам более подробную информацию о том, что вы ожидаете от своей модели, особенно о том, какую форму вывода вы хотите, чтобы ваша BiLSTM-модель имела. Я предполагаю, что вы действительно хотите, чтобы ваша BiLSTM-модель возвращала скаляр для каждого образца, поэтому дополнительный Flatten уровень может сделать трюк:

 from tensorflow.keras import Sequential
from tensorflow.keras.layers import Bidirectional,LSTM,Dense,Flatten

model = tf.keras.Sequential()
model.add(
   tf.keras.layers.Bidirectional(
      tf.keras.layers.LSTM(
         units = 10,                             
         return_sequences=True),
         input_shape=(d1, d2)
         )
      )
model.add(Flatten()) #<-- additional flatten-layer
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')