Convolution1D в Convolution2D - PullRequest
       17

Convolution1D в Convolution2D

0 голосов
/ 11 декабря 2019

Подведите итог проблемы У меня есть необработанный сигнал от датчика длиной 76000 точек данных. Я хочу обработать эти данные с помощью CNN. Чтобы сделать это, я подумал, что мог бы использовать лямбда-слой для формирования кратковременного преобразования Фурье из необработанного сигнала, такого как

x = Lambda(lambda v: tf.abs(tf.signal.stft(v,frame_length=frame_length,frame_step=frame_step)))(x)

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

То, что я пробовал У меня есть два отдельных (пример Conv1D для обработки необработанных данныхи пример Conv2D, где я обрабатываю и запускаю STFT-изображение. Но я хочу объединить их.

Conv1D Где ввод: input = Input (shape = (76000,))

  x = Lambda(lambda v: tf.expand_dims(v,-1))(input)
  x = layers.Conv1D(filters =10,kernel_size=100,activation = 'relu')(x)
  x = Flatten()(x)
  output = Model(input, x)

Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 76000)]           0         
_________________________________________________________________
lambda_2 (Lambda)            (None, 76000, 1)          0         
_________________________________________________________________
conv1d (Conv1D)              (None, 75901, 10)         1010      
________________________________________________________________

Conv2D тот же вход

  x = Lambda(lambda v:tf.expand_dims(tf.abs(tf.signal.stft(v,frame_length=frame_length,frame_step=frame_step)),-1))(input)
  x = BatchNormalization()(x)
Model: "model_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_6 (InputLayer)         [(None, 76000)]           0         
_________________________________________________________________
lambda_8 (Lambda)            (None, 751, 513, 1)       0         
_________________________________________________________________
batch_normalization_3 (Batch (None, 751, 513, 1)       4         
_________________________________________________________________
. . .
. . . 
flatten_4 (Flatten)          (None, 1360)              0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 1360)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 1361      

Im Ищите способ объединить начало от слоя conv1d до слоя lambda_8. Если я соберу их вместе, я получу:

  x = Lambda(lambda v: tf.expand_dims(v,-1))(input)
  x = layers.Conv1D(filters =10,kernel_size=100,activation = 'relu')(x)
  #x = Flatten()(x)
  x = Lambda(lambda v:tf.expand_dims(tf.abs(tf.signal.stft(v,frame_length=frame_length,frame_step=frame_step)),-1))(x)
Layer (type)                 Output Shape              Param #   
=================================================================
input_6 (InputLayer)         [(None, 76000)]           0         
_________________________________________________________________
lambda_17 (Lambda)           (None, 76000, 1)          0         
_________________________________________________________________
conv1d_6 (Conv1D)            (None, 75901, 10)         1010      
_________________________________________________________________
lambda_18 (Lambda)           (None, 75901, 0, 513, 1)  0         <-- Wrong
=================================================================

Это не то, что я ищу. Это должно выглядеть больше как (None, 751,513,10,1). Пока я не смог найти подходящего решения. Кто-нибудь может мне помочь?

Заранее спасибо!

1 Ответ

1 голос
/ 11 декабря 2019

Из документации , похоже, stft принимает только (..., length) входы, но не принимает (..., length, channels).

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

Теперь, конечно, вам понадобятся совпадающие длины, вы не можете сопоставить 76000 с 75901. Таким образом, второе предложение заключается в использовании padding='same' в 1-мерных свертках для сохранения равных длин.

И, наконец, поскольку в результате stft у вас уже будет 10 каналов, вам не нужно расширять затемнения в последней лямбде.

Суммируя:

1D деталь

inputs = Input((76000,)) #(batch, 76000)

c1Out = Lambda(lambda x: K.expand_dims(x, axis=-1))(inputs) #(batch, 76000, 1)
c1Out = Conv1D(10, 100, activation = 'relu', padding='same')(c1Out) #(batch, 76000, 10)

#permute for putting length last, apply stft, put the channels back to their position
c1Stft = Permute((2,1))(c1Out) #(batch, 10, 76000)
c1Stft = x = Lambda(lambda v: tf.abs(tf.signal.stft(v,
                                                    frame_length=frame_length,
                                                    frame_step=frame_step)
                                     )
                    )(c1Stft) #(batch, 10, probably 751, probably 513)
c1Stft = Permute((2,3,1))(c1Stft) #(batch, 751, 513, 10)

2D деталь , ваш код выглядит нормально:

c2Out = Lambda(lambda v: tf.expand_dims(tf.abs(tf.signal.stft(v,
                                                              frame_length=frame_length,
                                                              frame_step=frame_step)
                                               ),
                                        -1))(inputs) #(batch, 751, 513, 1)

Теперь, когда все совместиморазмеры

#maybe
#c2Out = Conv2D(10, ..., padding='same')(c2Out) 

joined = Concatenate()([c1Stft, c2Out]) #(batch, 751, 513, 11) #maybe (batch, 751, 513, 20)

further = BatchNormalization()(joined)
further = Conv2D(...)(further)

Предупреждение: я не знаю, сделали ли они stft дифференцируемыми или нет, часть Conv1D будет работать только если определены градиенты.

...