Документация на 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
.