НейроАгент

Исправление ошибки формы в мульти-выходном прогнозировании Keras

Решение ошибки 'требуемые трансляционные формы' в мульти-выходном прогнозировании Keras. Узнайте о правильном выравнивании структуры данных и конфигурации модели для timeseries_dataset_from_array.

Как исправить ошибку ‘required broadcastable shapes’ при реализации мульти-выходного прогнозирования с помощью Keras timeseries_dataset_from_array?

Я пытаюсь создать модель мульти-выходного прогнозирования с использованием Keras со следующей настройкой:

Подготовка данных:

python
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)

Архитектура модели:

python
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).

Вот как решить эту проблему:

Содержание

Понимание несоответствия форм

Основная причина заключается в том, что ваш слой 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: Изменение структуры целевых данных

Наиболее прямое решение - изменить форму ваших целевых данных, чтобы она соответствовала форме выхода модели:

python
# Вместо:
# 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:

python
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: Использование подхода многошагового прогнозирования

Для настоящего многошагового прогнозирования структурируйте ваши данные для предсказания будущих временных шагов:

python
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:

python
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)

Лучшие практики для многовыходного прогнозирования

  1. Согласованность выравнивания форм: Убедитесь, что форма ваших целевых данных соответствует форме выхода модели. Как показано в примере прогнозирования трафика Keras, параметр multi_horizon определяет, предсказываете ли вы несколько временных шагов или только один.

  2. Согласованность конвейера данных: При использовании timeseries_dataset_from_array целевые данные должны иметь такое же количество выборок, как и входные данные. Документация API Keras показывает, что входные массивы должны иметь такое же количество выборок, как и целевые массивы.

  3. Конфигурация выходного слоя: Для многовыходного прогнозирования рассмотрите возможность использования одного выходного слоя с несколькими единицами вместо отдельных Dense-слоев:

    python
    output = Dense(4, activation='linear', name='multi_output')(lstm_out)
    
  4. Обработка последовательностей: Будьте четкими относительно того, хотите ли вы предсказывать на каждом временном шаге (последовательность-в-последовательность) или только в конце (последовательность-в-вектор). Пример прогнозирования погоды Keras демонстрирует правильную обработку последовательностей.

  5. Пакетная обработка: При отладке проблем с формой всегда проверяйте формы ваших пакетов:

    python
    for batch in dataset_train.take(1):
        inputs, targets = batch
        print("Форма входных данных:", inputs.shape)
        print("Форма целевых данных:", targets.shape)
    

Реализовав эти решения, вы устраните ошибку “требуемые трансформируемые формы” и создадите правильно функционирующую модель многовыходного прогнозирования с использованием Keras.

Источники

  1. Документация Keras: Прогнозирование трафика с использованием графовых нейронных сетей и LSTM
  2. Документация API Keras: Загрузка временных рядов
  3. Документация Keras: Прогнозирование временных рядов для прогноза погоды
  4. GitHub: Пример прогнозирования трафика временных рядов Keras
  5. Stack Overflow: Формат входных и целевых данных для многомерной регрессии временных рядов

Заключение

Ошибка “требуемые трансформируемые формы” в вашей модели многовыходного прогнозирования возникает из-за несоответствия между формой выхода модели и формой целевых данных. Следуя этим ключевым решениям:

  • Решение 1: Измените форму ваших целевых данных, чтобы она соответствовала измерениям выхода модели
  • Решение 2: Измените архитектуру вашей модели, чтобы использовать return_sequences=False для прогнозирования последовательность-в-вектор
  • Решение 3: Реализуйте правильное многошаговое прогнозирование с выровненными входными и выходными последовательностями

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