Вопрос или проблема
Я создаю модель CNN-LSTM для прогнозирования многомерных временных рядов:
model = Sequential()
#model.build((10,7,1))
model.add(Conv1D(filters=64, kernel_size=2, activation='relu',input_shape=(10,7),strides=1))
model.add(Conv1D(filters=128, kernel_size=2, activation='relu',strides=1))
model.add(MaxPooling1D(pool_size=2))
#model.add(Flatten())
model.add(LSTM(200,return_sequences=True, activation='relu', recurrent_activation="sigmoid"))
model.add(Dense(32, activation='sigmoid'))
model.add(Dense(1))
model.compile(optimizer="RMSprop", loss="mse",metrics=['accuracy'])
model.summary()
print('a new model has been created')
У меня на входе есть 7 признаков (“Временной ряд”) и один выход.
Я создал функцию (make_samples
для выборки данных в виде скользящего окна размером 10, в коде называемого n_steps
def make_samples(self,file, n_steps):
X, y = list(), list()
data=pd.read_csv(file)
for i in range(len(data)):
# find the end of this pattern
end_ix = i + n_steps
# check if we are beyond the dataset
if end_ix > len(data):
break
# gather input and output parts of the pattern
seq_x = data[self.lista].values[i:end_ix]
seq_y = data["Volume"].values[end_ix-1]
X.append(seq_x)
y.append(seq_y)
return array(X).astype("float32"),array(y).astype("float32")
Когда я передаю эти данные в модель, я получаю следующую ошибку:
Error when checking target: expected dense_30 to have 3 dimensions, but got array with shape (659, 1))
Вопрос в том, почему возникает эта ошибка? И как ее исправить?
Вот сводка
_________________________________________________________________
Layer (type) Output Shape Param
conv1d_38 (Conv1D) (None, 9, 64) 960
_________________________________________________________________
conv1d_39 (Conv1D) (None, 8, 128) 16512
_________________________________________________________________
max_pooling1d_18 (MaxPooling (None, 4, 128) 0
_________________________________________________________________
lstm_18 (LSTM) (None, 4, 200) 263200
_________________________________________________________________
dense_29 (Dense) (None, 4, 32) 6432
_________________________________________________________________
dense_30 (Dense) (None, 4, 1) 33
Заранее большое спасибо
Возможно, вы захотите попробовать использовать класс WindowGenerator из документации TensorFlow:
class WindowGenerator():
def __init__(self, input_width, label_width, shift,
train_df=train_df, val_df=val_df, test_df=test_df,
label_columns=None):
# Store the raw data.
self.train_df = train_df
self.val_df = val_df
self.test_df = test_df
# Work out the label column indices.
self.label_columns = label_columns
if label_columns is not None:
self.label_columns_indices = {name: i for i, name in
enumerate(label_columns)}
self.column_indices = {name: i for i, name in
enumerate(train_df.columns)}
# Work out the window parameters.
self.input_width = input_width
self.label_width = label_width
self.shift = shift
self.total_window_size = input_width + shift
self.input_slice = slice(0, input_width)
self.input_indices = np.arange(self.total_window_size)[self.input_slice]
self.label_start = self.total_window_size - self.label_width
self.labels_slice = slice(self.label_start, None)
self.label_indices = np.arange(self.total_window_size)[self.labels_slice]
def __repr__(self):
return '\n'.join([
f'Total window size: {self.total_window_size}',
f'Input indices: {self.input_indices}',
f'Label indices: {self.label_indices}',
f'Label column name(s): {self.label_columns}'])
```
Ответ или решение
При разработке модели CNN-LSTM для прогнозирования многомерных временных рядов вы столкнулись с ошибкой "Error when checking target: expected dense_30 to have 3 dimensions, but got array with shape (659, 1))". Это связано с несоответствием размерностей выходных данных модели и целевых меток. Давайте разберем подробно, почему это происходит и как устранить эту ошибку.
Теория
При разворачивании временных рядов в кольцевое окно (sliding window) на вход вашей модели подается трехмерная структура данных, имеющая форму (samples, timesteps, features). Каждое измерение выполняет определённую роль:
- Samples (Примеры): Количество батчей, которые модель будет обрабатывать.
- Timesteps (Шаги по времени): Количество временных шагов (окно) для каждого примера.
- Features (Признаки): Количество факторов или временных рядов, которые анализируются.
В вашем случае входной слой Conv1D ожидает форму входного тензора (10, 7), что соответствует 10 шагам по времени и 7 признакам.
Когда мы создаем LSTM слой с return_sequences=True
, он возвращает последовательность для каждого временного шага, сохраняя трехмерную форму данных через все выходы LSTM, Dense и другие слои. Если вы хотите, чтобы конечный выход вашего слоя Dense воздействовал только на последний временной шаг, то вам необходимо установить параметр return_sequences=False
либо добавить пояснительный слой, который уменьшит размерность до двухмерной (samples, features).
Пример
Посмотрите на структуру вашей модели:
model = Sequential()
model.add(Conv1D(filters=64, kernel_size=2, activation='relu', input_shape=(10, 7), strides=1))
model.add(Conv1D(filters=128, kernel_size=2, activation='relu', strides=1))
model.add(MaxPooling1D(pool_size=2))
model.add(LSTM(200, return_sequences=False, activation='relu'))
model.add(Dense(32, activation='sigmoid'))
model.add(Dense(1))
model.compile(optimizer="RMSprop", loss="mse", metrics=['accuracy'])
Обратите внимание, мы изменили параметр return_sequences
на False
. Это позволяет избежать возврата полной последовательности и возвращает вместо этого трехмерный тензор, что в конечном итоге преобразует данные к двухмерной форме, необходимой для финальных слоев Dense.
Применение
Чтобы исправить проблему, выполните следующее:
-
Измените параметр
return_sequences
в LSTM слое: Установитеreturn_sequences=False
, если вам необходимы только последние выходные данные временных шагов, а не полная последовательность. -
Преобразуйте выходные данные: Если по-прежнему необходима полная последовательность для последующих слоёв Dense, рассмотрите возможность использования Flatten, GlobalMaxPooling или GlobalAveragePooling слоев, чтобы преобразовать тензор в подходящую форму.
-
Анализ окна временного ряда: Убедитесь, что полноценные выходные данные для данной задачи имеют нужное количество измерений на этапе окончательного прогнозирования. Если работаете с одномерным выходом, убедитесь, что форма данных соответствует
(samples, 1)
. -
Проверка данных: Убедитесь, что подготовленные данные в
make_samples
соответствуют ожиданиям модели. Оба — иX
, иy
— должны быть согласованы по количеству выборок.
Эти темы будут гарантировать, что ваш подход к архитектурному дизайну CNN-LSTM модели останется оптимальным и избавит вас от типичных ошибок, связанных с размерностями. Обязательно протестируйте и верифицируйте изменения на небольших наборах данных прежде чем делать выводы на основе большой выборки. Такой подход позволит вам уделять внимание техническим деталям и подкрепить ваши инженерные решения доказанными практиками.