Что я неправильно понял о размерах слоя keras?

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

Сеть анализа ЭЭГ с https://arxiv.org/abs/1610.01683

Идея такова:

  • входные секции данных ЭЭГ (6000x1 - это то, что я сейчас буду использовать)
  • пропустите это через 20 1D-фильтров (200x1)
  • сделать максимальный пул на выходе каждой из этих фильтров с пулом 20, шагом 10 (в результате получается 20 точек данных 578x1)
  • "сложить" это в матрицу 578x20
  • запустите это через 2D-свертку с размером ядра 30x20
  • Снова макспул, с пулом (10,1), шагом(2,1)
  • два последовательных полносвязных слоя
  • 5-классовая функция softmax.

Мой код:

model = Sequential()
model.add(Conv1D(input_shape=(6000,1),kernel_size=200,strides=1,
             activation='relu',filters=20,name='C1'))
model.add(MaxPooling1D(pool_size=20, strides=10,padding='valid',name='P1'))
model.add(Reshape(( 579, 20,1),name='S1'))
model.add(Conv2D(filters=400,kernel_size=(30,20),strides=(1,1), 
             activation='relu',name='C2'))
model.add(MaxPooling2D(pool_size=(10,1),strides=(2,1),padding='valid',name='P2'))
#model.add(Reshape((271*400,1,1),name='S2'))
model.add(Dense(500,activation='relu',name='F1'))
model.add(Dense(500,activation='relu',name='F2'))
model.add(Dense(5,activation='relu',name='output'))
model.add(Activation(activation='softmax',name='softmax'))

model.summary()

Результат этого:

Layer (type)                 Output Shape              Param #   
=================================================================
C1 (Conv1D)                  (None, 5801, 20)          4020      
_________________________________________________________________
P1 (MaxPooling1D)            (None, 579, 20)           0         
_________________________________________________________________
S1 (Reshape)                 (None, 579, 20, 1)        0         
_________________________________________________________________
C2 (Conv2D)                  (None, 550, 1, 400)       240400    
_________________________________________________________________
P2 (MaxPooling2D)            (None, 271, 1, 400)       0         
_________________________________________________________________
F1 (Dense)                   (None, 271, 1, 500)       200500    
_________________________________________________________________
F2 (Dense)                   (None, 271, 1, 500)       250500    
_________________________________________________________________
output (Dense)               (None, 271, 1, 5)         2505      
_________________________________________________________________
softmax (Activation)         (None, 271, 1, 5)         0         
=================================================================
Total params: 697,925.0
Trainable params: 697,925.0
Non-trainable params: 0.0
_________________________________________________________________

И тут я путаюсь. Я бы хотел, чтобы на выходе F1 было просто 500x1 (500 нейронов), но это совсем не то, что я получаю? Должен ли быть еще один слой изменения формы между P2 и F1? Добавление «model.add(Reshape((271*400,1,1),name='S2'))» после P2 ничего не решает. У меня есть «image_data_format»: «channels_last» в keras.json, поэтому я предполагаю, что мои размеры представляют собой пакет — строку — столбец — канал?

Надеюсь, мой вопрос понятен.


person Kaare    schedule 24.03.2017    source источник
comment
Попробуйте поменять форму на слой Flatten с помощью model.add(Flatten()) keras.io/layers/ ядро/#flatten   -  person maz    schedule 24.03.2017


Ответы (1)


Вам нужно понять, как работает плотный слой. Это немного нелогично, но если ваш ввод имеет более 1 измерения (кроме пакетного измерения), то он будет действовать как плотный слой, распределенный по последнему измерению.

Если вы посмотрите в документ слоя Dense, вы увидите, что для формы ввода (batch_dim, dim1, dim2,..., last_dim) вы получаете выходную форму (batch_dim, dim1, dim2, ..., output_units).

Это означает, что в вашем случае, когда вы делаете Reshape((271*400,1,1),name='S2'), плотный слой будет применяться к последнему измерению и выводить что-то вроде этого (271*400,1,500). Если вы хотите, чтобы вывод был (500,), то вывод S2 должен быть одномерным тензором, содержащим все функции. Затем вы должны сделать Reshape((271*400,),name='S2') или Flatten(), как говорит @maz в комментариях. Flatten() — это изменение формы, которое берет все значения любого тензора и помещает их в одномерный тензор.

Надеюсь, это поможет :-)

person Nassim Ben    schedule 24.03.2017