Начинающий Керас: какова должна быть выходная форма последнего слоя? - PullRequest
0 голосов
/ 13 мая 2018

Мне трудно обернуть голову вокруг математики за CNN и как именно мне следует изменить выходную форму между слоями моей нейронной сети.

Я пытаюсь сделать маскировку изображения карванывызов на kaggle https://www.kaggle.com/c/carvana-image-masking-challenge.Другими словами, я пытаюсь создать нейронную сеть, которая, учитывая изображение автомобиля, может определить границы автомобиля на этом изображении и вырезать его из остального фона.

Таким образом, мои входные данные - все изображения, ширина = 959 пикселей и высота = 640 пикселей.Форма моего входного массива (159, 640, 959, 3), где 159 представляет тот факт, что входной массив содержит в общей сложности 159 изображений.Цели, которые я создал, представляют собой матрицы с 640 строками и 959 столбцами (запись для каждого пикселя), использующие логические значения для представления того, является ли соответствующий пиксель автомобилем / в границах автомобиля.Форма данных цели (159, 640, 959), где 159, вероятно, представляет тот факт, что цель содержит 159 изображений

Я создал преждевременно структурированную сверточную сеть (под этим я просто подразумеваю, что очень мало фильтровиспользуемый).Код для архитектуры здесь.

  nn = Sequential()

  nn.add(Conv2D(8,(3,3), input_shape = (IMG_HEIGHT, IMG_WIDTH, 3),    activation = 'relu', padding = 'same'))
  nn.add(Conv2D(8, (3,3), activation='relu', padding='same'))
  nn.add(Dense(1, activation='softmax'))

Summary () показывает следующее:

# Summary:
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 640, 959, 8)       224       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 640, 959, 8)       584       
_________________________________________________________________
dense_1 (Dense)              (None, 640, 959, 6)       54        
=================================================================
Total params: 862
Trainable params: 862

И ошибка, с которой я застрял, это просто ...

ValueError: Ошибка при проверке цели: ожидалось, что плотность_1 имеет 4 измерения, но получен массив с формой (159, 640, 959)

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

edit: изначально говорилось, что изображения имели форму 440px X 959px.Это неверно, на самом деле это 640px X 959px.Действительно неудобная опечатка с моей стороны.

1 Ответ

0 голосов
/ 13 мая 2018

Документация на Dense не является самой ясной, но это ясно из раздела, описывающего формы ввода и вывода.

Примечание: если входное значение для слоя имеет ранг больше 2, то оно выравнивается до начального точечного произведения с помощью kernel.

...

Форма ввода

nD тензор с формой: (batch_size, ..., input_dim). Наиболее распространенная ситуация - это двумерный ввод с формой (batch_size, input_dim).

Форма вывода

nD тензор с формой: (batch_size, ..., units). Например, для двумерного ввода с формой (batch_size, input_dim) вывод будет иметь форму (batch_size, units).

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

Таким образом, если вы введете входное значение, равное (None, 640, 959, 8), это означает, что Dense будет обрабатывать конечное измерение как единое целое для полных соединений и обрабатывать каждую отдельную единицу среди 640x959 местоположений, указанных внутренними измерениями. как отдельный выход нейрона ...

Итак, если ваша сеть это:

nn = Sequential()
nn.add(Conv2D(8, (3,3), input_shape = (640, 959, 3), activation='relu', padding='same'))
nn.add(Conv2D(8, (3,3), activation='relu', padding='same'))
nn.add(Dense(1, activation='softmax'))

тогда конечная форма вывода будет

(None, 640, 959, 1)

То есть каждый выходной «пиксель» (i, j) в сетке 640x959 рассчитывается как плотная комбинация из 8 различных каналов свертки в точке (i, j) из предыдущего слоя.

Существуют различные способы достижения одной и той же цели, например, свертка 1x1, которая уменьшает размер канала с 8 до 1, что также дает одинаковую выходную форму со слоем, подобным

Conv2D(1, (1,1), activation='relu', padding='same')

или вы можете сослаться на пример "naive Keras" для конкретного соревнования Kaggle, над которым вы работаете, которое использует это:

model = Sequential()
model.add( Conv2D(16, 3, activation='relu', padding='same', input_shape=(320, 480, 12) ) )
model.add( Conv2D(32, 3, activation='relu', padding='same') )
model.add( Conv2D(1, 5, activation='sigmoid', padding='same') )

Отдельно от всего этого у нас есть две проблемы неправильных измерений данных из кода, который вы напечатали для нас.

Во-первых, вы утверждаете, что высота изображения равна 440, но вывод keras говорит о 640.

Другое - ваш последний плотный слой имеет 6 каналов на выходе, но соответствующий код, который вы указали, может привести только к 1 каналу.

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

Например, уровень потерь для этой сети должен сравнивать битовые маски наземной истинности пикселей местоположения автомобиля с выводом 640x959 Dense вашего последнего слоя (как только вы исправите странную проблему, когда вы показываете 6 каналов в выход).

Но сообщенное вами сообщение об ошибке

ValueError: Ошибка при проверке цели: ожидалось, что плотность_1 имеет 4 измерения, но получен массив с формой (159, 640, 959)

и это говорит о том, что пакет целевых данных, возможно, необходимо преобразовать в тензор формы (159, 640, 959, 1), просто ради совместимости с формой, которая выходит из вашего слоя Dense.

...