Как исправить ошибку ‘required broadcastable shapes’ при реализации мульти-выходного прогнозирования с помощью Keras timeseries_dataset_from_array?
Я пытаюсь создать модель мульти-выходного прогнозирования с использованием Keras со следующей настройкой:
Подготовка данных:
train_data = features.loc[0 : train_split - 1]
x_train = train_data.iloc[:, :6].values
y_train1 = train_data.iloc[:,6].values
y_train2 = train_data.iloc[:,7].values
y_train3 = train_data.iloc[:,8].values
y_train4 = train_data.iloc[:,9].nvalues
combined_targets_train = np.stack([y_train1, y_train2, y_train3, y_train4], axis=-1)
dataset_train = keras.preprocessing.timeseries_dataset_from_array(
x_train,
combined_targets_train,
sequence_length=120,
sampling_rate=step,
batch_size=16,
shuffle=True,
)
Формы данных:
- Форма входных данных: (16, 120, 6)
- Форма целевых данных: (16, 4)
Архитектура модели:
inputs_seq = keras.layers.Input(shape=(120, 6), name='meteo')
lstm_out = LSTM(10, return_sequences=True)(inputs_seq)
output_surfrun = Dense(1, activation='linear', name='pred_surf_runoff')(lstm_out)
output_subsurf = Dense(1, activation='linear', name='pred_sub_surf_runoff')(lstm_out)
output_evap = Dense(1, activation='linear', name='pred_evapo')(lstm_out)
output_een = Dense(1, activation='linear', name='pred_een')(lstm_out)
model = keras.Model(
inputs=inputs_seq,
outputs=[output_surfrun, output_subsurf, output_evap, output_een],
name='model_multi_heads'
)
model.compile(optimizer=keras.optimizers.Adam(learning_rate=learning_rate), loss="mse")
Возникшая ошибка:
Epoch 1/10
2025-11-04 16:20:09.341769: W tensorflow/core/framework/op_kernel.cc:1844] INVALID_ARGUMENT: required broadcastable shapes
InvalidArgumentError: Graph execution error:
Detected at node compile_loss/mse/sub defined at (most recent call last):
File "/databricks/python_shell/scripts/db_ipykernel_launcher.py", line 52, in <module>
Что вызывает ошибку несоответствия форм, и как правильно структурировать мою модель мульти-выходного прогнозирования для работы с timeseries_dataset_from_array?
Ошибка возникает из-за несоответствия формы между выходными данными модели и целевыми данными. Ваш слой LSTM использует return_sequences=True, что создает выходные данные формы (batch_size, sequence_length, units), но ваши целевые данные имеют форму (batch_size, 4) вместо ожидаемой (batch_size, sequence_length, 4).
Вот как решить эту проблему:
Содержание
- Понимание несоответствия форм
- Решение 1: Изменение структуры целевых данных
- Решение 2: Изменение архитектуры модели
- Решение 3: Использование подхода многошагового прогнозирования
- Полная рабочая реализация
- Лучшие практики для многовыходного прогнозирования
Понимание несоответствия форм
Основная причина заключается в том, что ваш слой LSTM выводит последовательности (из-за return_sequences=True), создавая выходные данные формы (batch_size, sequence_length, 10). Когда вы применяете Dense-слои к этому выходу, они сохраняют измерение последовательности, что приводит к конечным выходным данным формы (batch_size, sequence_length, 1) для каждого из 4 выходных голов модели.
Однако ваши целевые данные имеют форму (batch_size, 4), что не соответствует ожидаемой форме выхода модели (batch_size, sequence_length, 4).
Как объясняется в документации Keras: “Если multi_horizon=True, то модель будет делать прогноз для временных шагов t+T+1, t+T+2, t+T+3. Таким образом, целевые данные будут иметь форму (T,3). Но если multi_horizon=False, модель будет делать прогноз только для временного шага t+T+3, и поэтому целевые данные будут иметь форму (T, 1).”
Решение 1: Изменение структуры целевых данных
Наиболее прямое решение - изменить форму ваших целевых данных, чтобы она соответствовала форме выхода модели:
# Вместо:
# combined_targets_train = np.stack([y_train1, y_train2, y_train3, y_train4], axis=-1)
# что дает форму (samples, 4)
# Изменяем форму целевых данных для соответствия выходу модели:
combined_targets_train = np.stack([y_train1, y_train2, y_train3, y_train4], axis=-1)
# Расширяем измерения для добавления длины последовательности
combined_targets_train = np.expand_dims(combined_targets_train, axis=1) # (samples, 1, 4)
# Повторяем для длины последовательности
combined_targets_train = np.repeat(combined_targets_train, 120, axis=1) # (samples, 120, 4)
Это создает целевые данные, которые соответствуют форме выхода вашей модели (batch_size, sequence_length, 4).
Решение 2: Изменение архитектуры модели
Если вы хотите предсказывать только один вывод на последовательность (а не на каждый временной шаг), измените вашу модель, чтобы использовать return_sequences=False:
inputs_seq = keras.layers.Input(shape=(120, 6), name='meteo')
lstm_out = LSTM(10, return_sequences=False)(inputs_seq) # Изменено на False
output_surfrun = Dense(1, activation='linear', name='pred_surf_runoff')(lstm_out)
output_subsurf = Dense(1, activation='linear', name='pred_sub_surf_runoff')(lstm_out)
output_evap = Dense(1, activation='linear', name='pred_evapo')(lstm_out)
output_een = Dense(1, activation='linear', name='pred_een')(lstm_out)
model = keras.Model(
inputs=inputs_seq,
outputs=[output_surfrun, output_subsurf, output_evap, output_een],
name='model_multi_heads'
)
model.compile(optimizer=keras.optimizers.Adam(learning_rate=learning_rate), loss="mse")
С этим изменением каждый вывод будет иметь форму (batch_size, 1), что может работать с вашей целевой формой (batch_size, 4), если вы правильно их объедините.
Решение 3: Использование подхода многошагового прогнозирования
Для настоящего многошагового прогнозирования структурируйте ваши данные для предсказания будущих временных шагов:
def create_multi_step_dataset(data, targets, sequence_length, forecast_horizon):
"""
Создание набора данных для многошагового прогнозирования
Args:
data: Входные данные формы (samples, features)
targets: Целевые данные формы (samples, num_outputs)
sequence_length: Длина входной последовательности
forecast_horizon: Количество шагов для прогнозирования
"""
X, y = [], []
for i in range(len(data) - sequence_length - forecast_horizon + 1):
X.append(data[i:i + sequence_length])
# Получаем forecast_horizon будущих шагов для каждой цели
y.append(targets[i + sequence_length:i + sequence_length + forecast_horizon])
return np.array(X), np.array(y)
# Использование
forecast_horizon = 120 # Прогнозируем следующие 120 временных шагов
x_train_reshaped, y_train_reshaped = create_multi_step_dataset(
x_train.reshape(-1, 6), # Изменяем форму на 2D
combined_targets_train,
sequence_length=120,
forecast_horizon=forecast_horizon
)
# Возвращаем форму 3D для LSTM
x_train_reshaped = x_train_reshaped.reshape(-1, 120, 6)
y_train_reshaped = y_train_reshaped.reshape(-1, forecast_horizon, 4)
Полная рабочая реализация
Вот полный рабочий пример, использующий Решение 1:
import numpy as np
import keras
from keras.layers import LSTM, Dense
from keras.models import Model
# Генерация примеров данных (замените на ваши реальные данные)
samples = 1000
sequence_length = 120
features = 6
num_outputs = 4
# Генерация синтетических данных
x_train = np.random.randn(samples, sequence_length, features)
y_train1 = np.random.randn(samples)
y_train2 = np.random.randn(samples)
y_train3 = np.random.randn(samples)
y_train4 = np.random.randn(samples)
# Объединяем целевые данные и изменяем форму для соответствия выходу модели
combined_targets_train = np.stack([y_train1, y_train2, y_train3, y_train4], axis=-1)
combined_targets_train = np.expand_dims(combined_targets_train, axis=1)
combined_targets_train = np.repeat(combined_targets_train, sequence_length, axis=1)
# Создаем набор данных
dataset_train = keras.preprocessing.timeseries_dataset_from_array(
x_train,
combined_targets_train,
sequence_length=sequence_length,
batch_size=16,
shuffle=True,
)
# Архитектура модели
inputs_seq = keras.layers.Input(shape=(sequence_length, features), name='meteo')
lstm_out = LSTM(10, return_sequences=True)(inputs_seq)
output_surfrun = Dense(1, activation='linear', name='pred_surf_runoff')(lstm_out)
output_subsurf = Dense(1, activation='linear', name='pred_sub_surf_runoff')(lstm_out)
output_evap = Dense(1, activation='linear', name='pred_evapo')(lstm_out)
output_een = Dense(1, activation='linear', name='pred_een')(lstm_out)
model = Model(
inputs=inputs_seq,
outputs=[output_surfrun, output_subsurf, output_evap, output_een],
name='model_multi_heads'
)
model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.001), loss="mse")
# Обучаем модель
model.fit(dataset_train, epochs=10)
Лучшие практики для многовыходного прогнозирования
-
Согласованность выравнивания форм: Убедитесь, что форма ваших целевых данных соответствует форме выхода модели. Как показано в примере прогнозирования трафика Keras, параметр
multi_horizonопределяет, предсказываете ли вы несколько временных шагов или только один. -
Согласованность конвейера данных: При использовании
timeseries_dataset_from_arrayцелевые данные должны иметь такое же количество выборок, как и входные данные. Документация API Keras показывает, что входные массивы должны иметь такое же количество выборок, как и целевые массивы. -
Конфигурация выходного слоя: Для многовыходного прогнозирования рассмотрите возможность использования одного выходного слоя с несколькими единицами вместо отдельных Dense-слоев:
pythonoutput = Dense(4, activation='linear', name='multi_output')(lstm_out) -
Обработка последовательностей: Будьте четкими относительно того, хотите ли вы предсказывать на каждом временном шаге (последовательность-в-последовательность) или только в конце (последовательность-в-вектор). Пример прогнозирования погоды Keras демонстрирует правильную обработку последовательностей.
-
Пакетная обработка: При отладке проблем с формой всегда проверяйте формы ваших пакетов:
pythonfor batch in dataset_train.take(1): inputs, targets = batch print("Форма входных данных:", inputs.shape) print("Форма целевых данных:", targets.shape)
Реализовав эти решения, вы устраните ошибку “требуемые трансформируемые формы” и создадите правильно функционирующую модель многовыходного прогнозирования с использованием Keras.
Источники
- Документация Keras: Прогнозирование трафика с использованием графовых нейронных сетей и LSTM
- Документация API Keras: Загрузка временных рядов
- Документация Keras: Прогнозирование временных рядов для прогноза погоды
- GitHub: Пример прогнозирования трафика временных рядов Keras
- Stack Overflow: Формат входных и целевых данных для многомерной регрессии временных рядов
Заключение
Ошибка “требуемые трансформируемые формы” в вашей модели многовыходного прогнозирования возникает из-за несоответствия между формой выхода модели и формой целевых данных. Следуя этим ключевым решениям:
- Решение 1: Измените форму ваших целевых данных, чтобы она соответствовала измерениям выхода модели
- Решение 2: Измените архитектуру вашей модели, чтобы использовать
return_sequences=Falseдля прогнозирования последовательность-в-вектор - Решение 3: Реализуйте правильное многошаговое прогнозирование с выровненными входными и выходными последовательностями
Всегда проверяйте формы ваших данных во время отладки и выбирайте подход, который лучше всего соответствует вашим требованиям прогнозирования. Возможности многовыходного прогнозирования в Keras являются мощными при реализации с правильным выравниванием форм между целевыми данными и выходами модели.