Как изменить форму ввода в изображении CNN с 40x40 до 13x78? - PullRequest
1 голос
/ 12 мая 2019

Этот CNN хорошо работает для изображений 40x40x2, но теперь я хочу изменить его на 13x78x2 ​​и получить следующую ошибку. Что я должен изменить в архитектуре моего CNN?

Negative dimension size caused by subtracting 3 from 2 for 'conv2d_13/convolution' (op: 'Conv2D') with input shapes: [?,2,35,64], [3,3,64,64].

Мой код:

  data_w = 40 #CHANGE TO 13
  data_h = 40 #CHANGE TO 78
  n_classes = 2
  n_filters_1 = 32
  n_filters_2 = 64
  d_filter = 3
  p_drop_1 = 0.25
  p_drop_2 = 0.50   
  model = Sequential()
  model.add(Convolution2D(n_filters_1, d_filter, d_filter, border_mode='valid', input_shape=(data_w, data_h,2)))
  model.add(Activation('relu'))
  model.add(Convolution2D(n_filters_1, d_filter, d_filter))
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2)))
  model.add(Dropout(p_drop_1))
  model.add(Convolution2D(n_filters_2, d_filter, d_filter, border_mode='valid'))
  model.add(Activation('relu'))
  model.add(Convolution2D(n_filters_2, d_filter, d_filter))
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2)))
  model.add(Dropout(p_drop_1))
  ## Used to flat the input (1, 10, 2, 2) -> (1, 40)
  model.add(Flatten())
  # Full Connected layer
  model.add(Dense(256))
  model.add(Activation('relu'))
  # Drop layer
  model.add(Dropout(p_drop_2))
  # Output Full Connected layer
  model.add(Dense(n_classes))
  model.add(Activation('softmax'))

1 Ответ

2 голосов
/ 12 мая 2019

Поскольку вы выбрали valid в качестве border_mode для свертки, произойдет следующее: при размере фильтра 3 x 3 мы удалим 1 пиксель вокруг границ для сгенерированных выходов фильтра на каждом Convolution2D слой. Также обратите внимание, что пропуск аргумента предполагает также допустимое заполнение. Если вы решите уменьшение выходных размеров на каждом слое, вы попадете в точку, где одно из измерений (строк) размеров выходного фильтра будет равно 0, и, таким образом, вы получите ошибку. С d_filter = 3 давайте пройдемся по размерам выходного фильтра на каждом слое, учитывая, что размер входного изображения равен 13 x 78. Обратите внимание, что я опускаю показ выходных размеров фильтра на слоях Activation и Dropout, так как мы уже знаем, что они поддерживают те же размеры вывода, что и краткость:

  model.add(Convolution2D(n_filters_1, d_filter, d_filter, border_mode='valid', input_shape=(data_w, data_h,2))) # 11 x 76
  model.add(Activation('relu'))
  model.add(Convolution2D(n_filters_1, d_filter, d_filter)) # 9 x 74
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2))) # 4 x 37
  model.add(Dropout(p_drop_1))
  model.add(Convolution2D(n_filters_2, d_filter, d_filter, border_mode='valid')) # 2 x 35
  model.add(Activation('relu'))
  model.add(Convolution2D(n_filters_2, d_filter, d_filter)) # 0 x 33 (!!!!)
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2)))
  model.add(Dropout(p_drop_1))

Я хотел бы сразу предложить изменить border_mode, чтобы он стал 'same'. Таким образом, размеры выходного фильтра сохраняются для каждого слоя Convolution2D, прежде чем он достигнет слоя пула. Я не уверен относительно вашей цели выбора правильной свертки, но попробуйте сделать это:

  model.add(Convolution2D(n_filters_1, d_filter, d_filter, border_mode='same', input_shape=(data_w, data_h,2))) # 13 x 78
  model.add(Activation('relu'))
  model.add(Convolution2D(n_filters_1, d_filter, d_filter), border_mode='same') # 13 x 78
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2))) # 6 x 39
  model.add(Dropout(p_drop_1))
  model.add(Convolution2D(n_filters_2, d_filter, d_filter, border_mode='same')) # 6 x 39
  model.add(Activation('relu'))
  model.add(Convolution2D(n_filters_2, d_filter, d_filter), border_mode='same') # 6 x 39
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2))) # 3 x 19
  model.add(Dropout(p_drop_1))

Если нет, вам нужно удалить некоторые слои Convolution2D и MaxPooling2D, чтобы можно было генерировать ненулевые выходные результаты фильтра. Проделайте ту же работу, что и я выше, чтобы выяснить, сколько вам нужно, чтобы удалить нужные слои. Я бы предложил удалить слои после первых Convolution2D и Activation слоев с фильтрами n_filters_2:

  model.add(Convolution2D(n_filters_1, d_filter, d_filter, border_mode='valid', input_shape=(data_w, data_h,2))) # 11 x 76
  model.add(Activation('relu'))
  model.add(Convolution2D(n_filters_1, d_filter, d_filter)) # 9 x 74
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2))) # 4 x 37
  model.add(Dropout(p_drop_1))
  model.add(Convolution2D(n_filters_2, d_filter, d_filter, border_mode='valid')) # 2 x 35
  model.add(Activation('relu'))
#  model.add(Convolution2D(n_filters_2, d_filter, d_filter)) # 0 x 33 (!!!!)
#  model.add(Activation('relu'))
#  model.add(MaxPooling2D(pool_size=(2, 2)))
#  model.add(Dropout(p_drop_1))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...