Стандартные сверточные фильтры:
Чтобы получить отличные результаты, нейронные сети редко рассматривают функцию в одиночку, наоборот, они способствуют корреляции между функциями для извлечения более точных результатов.
Именно поэтому стандартные формы фильтра свертки:
(width, input_features, output_features)
В этой свертке все входные объекты считаются для создания новых выходных объектов.
Как полностью индивидуализировать функции?
предупреждение: при этом используется один и тот же точный фильтр для всех функций (может потребоваться один отдельный фильтр для каждой функции, затем см.следующий ответ)
Вы можете изменить порядок своих данных, чтобы функции стали основной группой, и чтобы каждая группа имела только одну функцию и фильтр.
Эти группы затем могут обрабатываться параллельно со слоем TimeDistributed
.
model = Sequential()
#reordering data and adding 1 dummy feature per group
model.add(Permute((2,1), input_shape = (timesteps,nfeatures))) #(batch, feat, steps)
model.add(Lambda(lambda x: K.expand_dims(x))) #(batch, feat, steps, 1)
#applying the 1 filter convolution for each group
model.add(TimeDistributed(Conv1D(padding = 'valid',filters = 1,strides = 5,
kernel_size = 5, activation = 'relu')))
model.add( TimeDistributed(MaxPooling1D()) )
#restoring to (batch,features)
model.add(Reshape((nfeatures,)))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
Честно говоря, ваша модель будет намного более мощной при использовании стандартной свертки, но у вас могут быть особые причины дляделая это.
Один отдельный фильтр для каждой функции
Это требует больше работы.Нам понадобится либо пользовательский слой, который реализует deepwise_conv1d (который не предлагает Keras), либо мы создадим 128 отдельных слоев conv1D с 1 фильтром (проще).
Используя второй подход (несколько слоев сверток),нам понадобится функциональная модель API для создания параллельных ветвей.
from keras.model import Model
#function to split the input in multiple outputs
def splitter(x):
return [x[:,:,i:i+1] for i in range(nfeatures)]
#model's input tensor
inputs = Input((timesteps,nfeatures))
#splitting in 128 parallel tensors - 128 x (batch,15,1)
multipleFeatures = Lambda(splitter)(inputs)
#applying one individual convolution on each parallel branch
multipleFeatures = [
Conv1D(padding = 'valid',filters = 1,strides = 5, kernel_size = 5)(feat)
for feat in multipleFeatures ]
#joining the branches into (batch, 3, 128)
joinedOutputs = Concatenate()(multipleFeatures)
joinedOutputs = Activation('relu')(joinedOutputs)
outputs = MaxPooling1D()(joinedOutputs)
outputs = Lambda(lambda x: K.squeeze(x,axis=1))(outputs)
outputs = Dropout(0.5)(outputs)
outputs = Dense(1, activation='sigmoid')(outputs)
model = Model(inputs,outputs)