Как работать с изображением переменного размера в CNN, используя Keras?

В настоящее время я работаю над CNN над изображением для извлечения объектов с использованием керас. Все изображения в виде 276 строк, x столбцов и 3 цветовых измерений (RGB). Количество столбцов равно длине вектора выходного объекта, который он должен сгенерировать.

Представление входных данных - редактировать:

Входные данные, данные для изображения, состоят из срезов изображения по столбцам. это означает, что фактический входной сигнал для изображения равен (276,3), а количество столбцов равно длине объекта, которую он должен сгенерировать.

Моя начальная модель такова:

    print "Model Definition"
    model = Sequential()

    model.add(Convolution2D(64,row,1,input_shape=(row,None,3)))
    print model.output_shape
    model.add(MaxPooling2D(pool_size=(1,64)))
    print model.output_shape
    model.add(Dense(1,activation='relu'))

Мои отпечатки между печатями output.shape и я, кажется, немного смущен на выходе.

Model Definition
(None, 1, None, 64)
(None, 1, None, 64)

Как получилось, что 3D-данные стали 4d? И так будет после слоя maxpoolling2d?

Мой плотный слой / полностью связанный слой вызывает у меня некоторые проблемы с размерами здесь:

Traceback (most recent call last):
  File "keras_convolutional_feature_extraction.py", line 466, in <module>
    model(0,train_input_data,output_data_train,test_input_data,output_data_test)
  File "keras_convolutional_feature_extraction.py", line 440, in model
    model.add(Dense(1,activation='relu'))
  File "/usr/local/lib/python2.7/dist-packages/keras/models.py", line 324, in add
    output_tensor = layer(self.outputs[0])
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/topology.py", line 474, in __call__
    self.assert_input_compatibility(x)
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/topology.py", line 415, in assert_input_compatibility
    str(K.ndim(x)))
Exception: Input 0 is incompatible with layer dense_1: expected ndim=2, found ndim=4

Так почему же я не могу получить данные до одного значения из трехмерного изображения.?

1 ответ

Решение

Вы работаете на 276 x None x 3 изображение с использованием 64 сверточных фильтров, каждый размером 276 x 1 (при условии, rows = 276). Один сверточный фильтр выведет матрицу размера 1 x None, Прочтите это подробно, если вы не знаете, как работают сверточные фильтры. Таким образом, для 64 фильтров (в бэкэнде Theano) вы получите матрицу размера 64 x 1 x None, В бэкенде Tensorflow, думаю, будет 1 x None x 64, Теперь первое измерение для Keras-Theano - это всегда образцы. Итак, ваша конечная форма будет None x 64 x 1 x None, Для Tensorflow это будет None x 1 x None x 64, Прочитайте это для получения дополнительной информации о различных бэкэндах в Keras.

Чтобы убрать ошибку плотного слоя, я думаю, вам нужно сгладить вывод, введя следующую строку перед добавлением Dense слой.

model.add(Flatten())

Тем не менее, я не очень понимаю использование плотного слоя здесь. Как вы должны знать, плотный слой принимает только фиксированный размер ввода и обеспечивает вывод фиксированного размера. Так что ваши None измерение будет в основном ограничено одним значением, если вы хотите, чтобы ваша сеть работала без ошибок. Если вы хотите иметь вывод формы 1 x Noneтогда не стоит включать плотные слои и использовать average объединение в конце, чтобы свернуть ответ на 1 x 1 x None выход.

Изменить: если у вас есть изображение размера 276 x n x 3где он имеет переменное количество столбцов и если вы хотите, чтобы вывод размера 1 x nТогда вы можете сделать следующее:

model = Sequential()
model.add(Convolution2D(64,row,1,input_shape=(row,None,3)))
model.add(Convolution2D(1,1,1))
print model.output_shape  # this should print `None x 1 x None x 1`
model.add(flatten())

Теперь я сомневаюсь, что эта сеть будет работать очень хорошо, поскольку в ней всего один слой из 64 фильтров. Чувствительное поле также слишком велико (например, 276 - высота изображения). Вы можете сделать две вещи:

  1. Уменьшите рецептивное поле, то есть вместо того, чтобы сворачивать весь столбец изображения одновременно, вы можете свертывать только 3 пикселя столбца за раз.
  2. Есть несколько сверточных слоев.

В дальнейшем я буду считать, что высота изображения равна 50. Затем вы можете написать сеть следующим образом:

model = Sequential()
model.add(Convolution2D(32,3,1,activation='relu',
          init='he_normal',input_shape=(row,None,3)))  # row = 50
model.add(Convolution2D(32,3,1,activation='relu',init='he_normal'))
model.add(MaxPooling2D(pool_size=(2,1), strides=(2,1), name='pool1'))
model.add(Convolution2D(64,3,1,activation='relu',init='he_normal'))
model.add(Convolution2D(64,3,1,activation='relu',init='he_normal'))
model.add(MaxPooling2D(pool_size=(2,1), strides=(2,1), name='pool2'))
model.add(Convolution2D(128,3,1,activation='relu',init='he_normal'))
model.add(Convolution2D(128,3,1,activation='relu',init='he_normal'))
model.add(Convolution2D(128,3,1,activation='relu',init='he_normal'))
model.add(MaxPooling2D(pool_size=(2,1), strides=(2,1), name='pool3'))
model.add(Convolution2D(1,1,1), name='squash_channels')
print model.output_shape  # this should print `None x 1 x None x 1`
model.add(flatten(), name='flatten_input')

Вы должны убедиться, что все эти слои сверточного и максимального пула уменьшают входную высоту с 50 до 1 после последнего максимального пула.

Как работать с изображениями переменного размера

Один из способов - сначала определить общий размер для вашего набора данных, например 224. Затем построить сеть для 224 x n изображение, как показано выше (может быть, немного глубже). Теперь позвольте нам сказать, что вы получите изображение с другим размером, скажем, p x n' где p > 224 а также n' != n, Вы можете взять центральную часть изображения размером 224 x n' и передать его через изображение. У вас есть свой вектор признаков.

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

Редактировать:

Смотрите CNN, который я определил, используя 3 x 3 извилины. Предположим, что вход имеет размер 50 x n x 3, Допустим, мы передаем ввод размера p x q x r через сверточный слой, который имеет f фильтры каждого размера 3 x 3, шаг 1. Вход не имеет отступов. Тогда выход сверточного слоя будет иметь размер (p-2) x (q-2) x f т.е. высота и ширина на выходе будут вдвое меньше, чем на входе. Наши объединяющие слои имеют размер (2,1) и шагать (2,1), Они будут вдвое уменьшать входные данные в направлении y (или уменьшать вдвое высоту изображения). Имея это в виду, следующее легко вывести (обратите внимание на названия слоев, которые я дал в моем CNN, они указаны ниже).

Вход CNN: None x 50 x n x 3

Ввод pool1 слой: None x 46 x n x 32
Выход из pool1 слой: None x 23 x n x 32

Ввод pool2 слой: None x 19 x n x 64
Выход из pool2 слой: None x 9 x n x 64 (Я думаю, что объединение Keras занимает слово, т.е. слово (19/2) = 9)

Ввод pool3 слой: None x 3 x n x 128
Выход из pool3 слой: None x 1 x n x 128

Ввод squash_channels слой: None x 1 x n x 128
Выход из squash_channels слой: None x 1 x n x 1

Ввод flatten_input слой: None x 1 x n x 1
Выход из flatten_input слой: None x n

Я думаю, что это то, что вы хотели. Я надеюсь, теперь все ясно.

Другие вопросы по тегам