В Керасе, как получить 3D-ввод и 3D-вывод для слоев LSTM - PullRequest
8 голосов
/ 22 мая 2019

В исходных настройках я получил

X1 = (1200,40,1)
y1 = (1200,10)

Затем я отлично работаю с моими кодами:

model = Sequential()
model.add(LSTM(12, input_shape=(40, 1), return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add((Dense(10)))

Теперь я получил еще один размер данных временного ряда тех же размеров, что и X1 и y1.то есть,

X2 = (1200,40,1)
y2 = (1200,10)

Теперь я складываю X1, X2 и y1, y2 как трехмерные массивы:

X_stack = (1200,40,2)
y_stack = (1200,10,2)

Затем я пытаюсь изменить свойkeras код типа:

model = Sequential()
model.add(LSTM(12, input_shape=(40, 2), return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add((Dense((10,2))))

Я хочу, чтобы мой код работал напрямую с 3D-массивами X_stack и y_stack без преобразования их в 2D-массивы.Не могли бы вы помочь мне, как изменить настройки?Спасибо.

Ответы [ 4 ]

0 голосов
/ 01 июня 2019

Я не могу дать краткий ответ на этот вопрос, однако я думаю, что необходимы пояснения относительно некоторых основных понятий LSTM ( один-к-одному, один-ко-многим, ... )

Поскольку RNN надстройки (включая LSTM) являются последовательными , они созданы для поиска корреляций, подобных времени, в то время как CNN являются пространственными , они созданы для поиска пространства.корреляции

Затем происходит дальнейшее дифференцирование LSTM в один-к-одному, один-ко-многим, многие-к-одному и многие-ко-многим , как показано в Многие к одному и многие ко многим примерам LSTM в Keras

Требуемый тип сети - это точка 5 в Многие к одному и многие ко многим примерам LSTMв Керасе и там написано:

Многие ко многим, когда количество шагов отличается от длины ввода / вывода: в Керасе это невероятно сложно.Нет простых фрагментов кода для кодирования этого.

Это тип 5, потому что форма ввода X_stack = (1200,40,2), а форма вывода y_stack = (1200,10,2), поэтому количество временных шагов различается (40 input и 10 output)

Если вам удавалось иметь равное количество входных и выходных временных шагов, вы можете изменить входные и выходные данные (numpy.reshape), как в keras LSTM, вводе с помощьюправильная форма (обратите внимание на расположение [ и ] в массивах).Это не означает изменение формы до 2D (т.е. выравнивание).В https://machinelearningmastery.com/timedistributed-layer-for-long-short-term-memory-networks-in-python/ приведен полный пример построения LSTM «многие ко многим» с равными временными шагами ввода и вывода с использованием TimeDistributed layer

Только для полноты, для пространственно-временные данные также существуют CNN-LSTM , однако это здесь не применимо, потому что у двух накопленных временных рядов нет явных пространственных корреляций:

Если у вас есть трехмерная величина, т.е.распределение в томе, который меняется со временем и вы хотите узнать это, тогда вам нужно использовать сеть CNN-LSTM .В этом подходе сохраняется как трехмерная информация, так и временная информация.Под трехмерной информацией подразумевается, что пространственная информация не отбрасывается.Обычно у учеников, подобных времени, таких как LSTM, эта пространственная информация часто отбрасывается, например, путем выравнивания изображения перед его обработкой в ​​LSTM.Полное руководство о том, как (пространственно-временной) CNN-LSTM может быть встроен в кераты, приведено в https://machinelearningmastery.com/cnn-long-short-term-memory-networks/

0 голосов
/ 29 мая 2019

Я предполагаю, что где-то есть ошибка в формах, которые вы сообщили для своих массивов. Я предполагаю y_stack.shape == (1200, 10, 2), это правильно?

Однако есть одна возможность сделать то, что вы описываете:

model = Sequential()
model.add(LSTM(12, input_shape=(40, 2), return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add(Dense(10 * 2))
model.add(Reshape((10, 2)))

Выходная сеть создается в виде 2D-тензора слоем Dense, а затем преобразуется в 3D-тензор с помощью Reshape. С точки зрения ввода-вывода это должно вести себя так, как вы указали.

0 голосов
/ 31 мая 2019

Я предполагаю, что вам нужно будет поделиться параметрами для каждого массива, который вы складываете.

  • Если бы вы складывали совершенно новые функции, тогда не было бы связанной целис каждым из них.

  • Если бы вы складывали совершенно разные примеры, вы бы не использовали 3D-массивы, а просто добавляли их в конец, как обычно.

Решение

Чтобы решить эту проблему, я бы использовал оболочку TimeDistributed из Keras .

LSTM ожидаютshape (j, k), где j - количество временных шагов, а k - количество функций.Поскольку вы хотите сохранить свой массив в виде 3D для ввода и вывода, вам нужно будет использовать другое измерение, чем измерение элемента.

Краткое примечание:

Я думаю, что важно отметить разницу между подходами.Объединение в размерности объекта дает вам несколько объектов за один и тот же временной шаг.В этом случае вы хотели бы использовать те же слои LSTM и не идти по этому пути.Поскольку вам нужны 3D-вход и 3D-выход, я предлагаю вам создать новое измерение для стека, которое позволит вам независимо применять одни и те же слои LSTM.

TimeDistributed:

Эта оболочка применяет слой к каждому массиву с индексом 1.Укладывая массивы X1 и X2 в индекс 1 и используя оболочку TimeDistributed, вы применяете слои LSTM независимо к каждому массиву, который вы собираете.Обратите внимание, что исходные и обновленные сводки моделей имеют одинаковое количество параметров.

Шаги реализации:

  • Первый шаг - изменить формуввод (40, 2) в (2, 40, 1).Это дает вам эквивалент 2 x (40, 1) входных данных массива.Вы можете сделать это либо в модели, как я, либо при создании набора данных и обновить форму ввода.

    • Добавляя дополнительное измерение (..., 1) в конец, мы сохраняемданные в формате, который LSTM мог бы понять, если бы он просто просматривал один из массивов, которые мы сложили за раз.Обратите внимание, например, на ваш исходный input_shape (40, 1).
  • Затем оберните каждый слой в оболочку TimeDistributed.

  • И наконецизмените вывод y, чтобы он соответствовал вашим данным, поменяв (2, 10) на (10, 2).

код

from tensorflow.python.keras import Sequential
from tensorflow.python.keras.layers import LSTM, Dense, TimeDistributed, InputLayer, Reshape
from tensorflow.python.keras import backend
import numpy as np

# Original Model
model = Sequential()
model.add(LSTM(12, input_shape=(40, 1), return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add((Dense(10)))

model.summary()

Сводка оригинальной модели

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm (LSTM)                  (None, 40, 12)            672       
_________________________________________________________________
lstm_1 (LSTM)                (None, 40, 12)            1200      
_________________________________________________________________
lstm_2 (LSTM)                (None, 6)                 456       
_________________________________________________________________
dense (Dense)                (None, 10)                70        
=================================================================
Total params: 2,398
Trainable params: 2,398
Non-trainable params: 0
_________________________________________________________________

Apply TimeDistributed Wrapper

model = Sequential()
model.add(InputLayer(input_shape=(40, 2)))
model.add(Reshape(target_shape=(2, 40, 1)))
model.add(TimeDistributed(LSTM(12, return_sequences=True)))
model.add(TimeDistributed(LSTM(12, return_sequences=True)))
model.add(TimeDistributed(LSTM(6, return_sequences=False)))
model.add(TimeDistributed(Dense(10)))
model.add(Reshape(target_shape=(10, 2)))

model.summary()

Обновленная сводка модели

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
reshape (Reshape)            (None, 2, 40, 1)          0         
_________________________________________________________________
time_distributed (TimeDistri (None, 2, 40, 12)         672       
_________________________________________________________________
time_distributed_1 (TimeDist (None, 2, 40, 12)         1200      
_________________________________________________________________
time_distributed_2 (TimeDist (None, 2, 6)              456       
_________________________________________________________________
time_distributed_3 (TimeDist (None, 2, 10)             70        
_________________________________________________________________
reshape_1 (Reshape)          (None, 10, 2)             0         
=================================================================
Total params: 2,398
Trainable params: 2,398
Non-trainable params: 0
_________________________________________________________________
0 голосов
/ 22 мая 2019

Вы можете использовать кортеж вывода X_stack.shape():

model = Sequential()
model.add(LSTM(12, input_shape=(X_stack.shape[1], X_stack.shape[2]),return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add((Dense((10,2))))
...