Многофункциональный причинный CNN - реализация Keras - PullRequest
4 голосов
/ 25 апреля 2019

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

Я изо всех сил пытаюсь выяснить, как изменить мою текущуюданные, чтобы соответствовать причинно-следственной ячейке CNN и представлять те же отношения данных / временного шага, а также то, какой должна быть степень расширения.

Мои текущие данные имеют такую ​​форму: (number of examples, lookback, features) и вот базовый примерLSTM NN, который я использую прямо сейчас.

lookback = 20   #  height -- timeseries
n_features = 5  #  width  -- features at each timestep

# Build an LSTM to perform regression on time series input/output data
model = Sequential()
model.add(LSTM(units=256, return_sequences=True, input_shape=(lookback, n_features)))
model.add(Activation('elu'))

model.add(LSTM(units=256, return_sequences=True))
model.add(Activation('elu'))

model.add(LSTM(units=256))
model.add(Activation('elu'))

model.add(Dense(units=1, activation='linear'))

model.compile(optimizer='adam', loss='mean_squared_error')

model.fit(X_train, y_train,
          epochs=50, batch_size=64,
          validation_data=(X_val, y_val),
          verbose=1, shuffle=True)

prediction = model.predict(X_test)

Затем я создал новую модель CNN (хотя и не потому, что заполнение 'causal' является опцией только для Conv1D, а не Conv2D,согласно документации Keras. Если я правильно понимаю, имея несколько функций, мне нужно использовать Conv2D, а не Conv1D, но затем, если я установлю Conv2D(padding='causal'), я получу следующую ошибку - Invalid padding: causal)

В любом случае, я также смог подогнать данные новой формой (number of examples, lookback, features, 1) и запустить следующую модель, используя слой Conv2D:

lookback = 20   #  height -- timeseries
n_features = 5  #  width  -- features at each timestep

 model = Sequential()
            model.add(Conv2D(128, 3, activation='elu', input_shape=(lookback, n_features, 1)))
model.add(MaxPool2D())
model.add(Conv2D(128, 3, activation='elu'))
model.add(MaxPool2D())
model.add(Flatten())
model.add(Dense(1, activation='linear'))

model.compile(optimizer='adam', loss='mean_squared_error')

model.fit(X_train, y_train,
          epochs=50, batch_size=64,
          validation_data=(X_val, y_val),
          verbose=1, shuffle=True)

prediction = model.predict(X_test)

Однако, насколько я понимаю, это не распространяетсяИспользовать данные как причинно-следственные, а не просто весь набор (lookback, features, 1) в виде изображения.

Есть ли способ изменить мои данные, чтобы они соответствовали слою Conv1D(padding='causal'), с несколькими функциями или каким-то образом запустить тот же самыйданные и форма ввода в виде Conv2D с 'causal' заполнением?

Ответы [ 2 ]

1 голос
/ 25 апреля 2019

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

Слой TimeDistributed является ключевым для этого.

Из документации Keras: "Эта обертка применяет слой к каждому временному срезу входа. Вход должен быть не менее 3D, и измерение индекса один будет считаться временным измерением."

Для наших целей мы хотим, чтобы этот слой применял «что-то» к каждому объекту, поэтому мы перемещаем объекты во временный индекс, который равен 1.

Также актуальна документация Conv1D .

В частности, о каналах: "Упорядочение размеров на входах." Channel_last "соответствует входам с формой (партия, шаги, каналы) (формат по умолчанию для временных данных в кератах)"

from tensorflow.python.keras import Sequential, backend
from tensorflow.python.keras.layers import GlobalMaxPool1D, Activation, MaxPool1D, Flatten, Conv1D, Reshape, TimeDistributed, InputLayer

backend.clear_session()
lookback = 20
n_features = 5

filters = 128

model = Sequential()
model.add(InputLayer(input_shape=(lookback, n_features, 1)))
# Causal layers are first applied to the features independently

model.add(Reshape(target_shape=(n_features, lookback, 1)))
# After reshape 5 input features are now treated as the temporal layer 
# for the TimeDistributed layer

# When Conv1D is applied to each input feature, it thinks the shape of the layer is (20, 1)
# with the default "channels_last", therefore...

# 20 times steps is the temporal dimension
# 1 is the "channel", the new location for the feature maps

model.add(TimeDistributed(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**0)))
# You could add pooling here if you want. 
# If you want interaction between features AND causal/dilation, then apply later
model.add(TimeDistributed(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**1)))
model.add(TimeDistributed(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**2)))


# Stack feature maps on top of each other so each time step can look at 
# all features produce earlier
model.add(Reshape(target_shape=(lookback, n_features * filters)))  # (20 time steps, 5 features * 128 filters)
# Causal layers are applied to the 5 input features dependently
model.add(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**0))
model.add(MaxPool1D())
model.add(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**1))
model.add(MaxPool1D())
model.add(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**2))
model.add(GlobalMaxPool1D())
model.add(Dense(units=1, activation='linear'))

model.compile(optimizer='adam', loss='mean_squared_error')

model.summary()

Окончательная сводная модель

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
reshape (Reshape)            (None, 5, 20, 1)          0         
_________________________________________________________________
time_distributed (TimeDistri (None, 5, 20, 128)        512       
_________________________________________________________________
time_distributed_1 (TimeDist (None, 5, 20, 128)        49280     
_________________________________________________________________
time_distributed_2 (TimeDist (None, 5, 20, 128)        49280     
_________________________________________________________________
reshape_1 (Reshape)          (None, 20, 640)           0         
_________________________________________________________________
conv1d_3 (Conv1D)            (None, 20, 128)           245888    
_________________________________________________________________
max_pooling1d (MaxPooling1D) (None, 10, 128)           0         
_________________________________________________________________
conv1d_4 (Conv1D)            (None, 10, 128)           49280     
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 5, 128)            0         
_________________________________________________________________
conv1d_5 (Conv1D)            (None, 5, 128)            49280     
_________________________________________________________________
global_max_pooling1d (Global (None, 128)               0         
_________________________________________________________________
dense (Dense)                (None, 1)                 129       
=================================================================
Total params: 443,649
Trainable params: 443,649
Non-trainable params: 0
_________________________________________________________________

Edit:

«почему вам нужно изменить форму и использовать n_features в качестве временного слоя»

Причина, по которой n_features изначально должна находиться на временном слое, заключается в том, что Conv1D с расширением и причинным заполнением работает только с одним объектом за раз, и из-за того, как реализован слой TimeDistributed.

Из их документации "Рассмотрим партию из 32 сэмплов, где каждый сэмпл представляет собой последовательность из 10 векторов 16 измерений. Тогда форма пакетного ввода слоя равна (32, 10, 16), а input_shape без учета размера образцов составляет (10, 16).

Затем вы можете использовать TimeDistributed для нанесения плотного слоя на каждый из 10 временных шагов независимо: "

Применение слоя TimeDistributed независимо к каждому объекту уменьшает размер проблемы, как если бы существовал только один объект (который легко учитывал бы расширение и причинное заполнение). С 5 функциями, они должны сначала обрабатываться отдельно.

  • После ваших изменений эта рекомендация остается в силе.

  • Не должно быть различий с точки зрения сети, независимо от того, включен ли InputLayer в первый слой или отдельно, так что вы определенно можете поместить его в первый CNN, если это решит проблему.

0 голосов
/ 25 апреля 2019

В Conv1D с причинно-следственной прокладкой имеет место дилатационная свертка.Для Conv2D вы можете использовать параметр dilation_rate класса Conv2D.Вы должны назначить dilation_rate с 2 кортежами целых чисел.Дополнительную информацию вы можете прочитать в документации keras или здесь .

...