Как Keras устанавливает размеры в этой сети, которая имеет CNN и плотные слои? - PullRequest
0 голосов
/ 05 октября 2018

Мне нужна помощь, чтобы понять, что здесь происходит.

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

Например, представьте себе сеть обнаружения углов, где выходной слой сообщает, является ли пиксель точно вершиной угла.А именно, мы хотим обнаружить только пиксель этого угла:

enter image description here

Первые слои в сети определены следующим образом:

from keras import models, layers
import numpy as np

size=5

input_image = layers.Input(shape=(size, size, 1))

b = layers.Conv2D(5, (3,3), activation='relu', padding='same')(input_image)
b = layers.MaxPooling2D((2,2), strides=1,  padding='same')(b)
b = layers.Conv2D(5, (3,3), activation='relu', padding='same')(b)
b_out = layers.MaxPooling2D((2,2),strides=1 ,padding='same')(b)

До сих пор я поддерживал размеры исходного входного слоя (sizeXsize).

Теперь я хотел бы иметь плотный слой в качестве выходного слоя с sizeXsize пикселями.

Если я использую output = layers.Dense(size, activation='sigmoid')(b_out), то построенный слой будет sizeXsizeXsize, а если я сделаю output = layers.Dense(1, activation='sigmoid')(b_out), то размер sizeXsize, как получится?!

Это здание ичасть кода компиляции:

model = models.Model(input_image, output)
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
model.summary()

Что мне здесь не хватает?Разве output = layers.Dense(1, activation='sigmoid')(b_out) это не один нейрон?

Дело в том, что если я тренируюсь:

n_images=100
data = np.random.randint(0,2,(n_images,size,size,1))
labels = np.random.randint(0,2,(n_images,size,size,1))
labels = data

model.fit(data, labels, verbose=1, batch_size=4, epochs=20)

и если я проверяю это:

data1 = np.random.randint(0,2,(n_images,size,size,1))
score, acc = model.evaluate(data1,data1, verbose=1)


print('Test score:', score)
print('Test accuracy:', acc)

a=np.random.randint(0,2,(1,size,size,1))
prediction = model.predict(a)

print(a==np.round(prediction))

Я получаю хорошую точность, и кажется, что размерыисправить для выходного слоя:

100/100 [==============================] - 0s 349us/step
Test score: 0.187119951248
Test accuracy: 0.926799981594
[[[[ True]
   [ True]
   [ True]
   [ True]
   [ True]]

  [[ True]
   [ True]
   [ True]
   [ True]
   [ True]]

  [[ True]
   [ True]
   [ True]
   [ True]
   [ True]]

  [[ True]
   [ True]
   [ True]
   [ True]
   [ True]]

  [[ True]
   [ True]
   [ True]
   [ True]
   [ True]]]]

Если я прочитал Плотная документация:

единицы: положительное целое число, размерность выходного пространства.

Итак, как получится, если я поставлю layers.Dense(1, activation='sigmoid')(b_out) Я получу выходной слой sizeXsize?

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Ваша путаница проистекает из того факта, что слой Dense в настоящее время реализован таким образом, что применяется к последней оси входных данных .Вот почему, когда вы подаете выходные данные слоя MaxPooling (т.е. b_out), который имеет форму (size, size, 5), в плотный слой с одной единицей, вы получаете выходные данные формы (size, size, 1).В этом случае один нейрон в слое Dense связан с каждым из 5 элементов в выходном массиве, хотя и с одинаковыми весами (поэтому, если вы посмотрите на вывод summary(), вы увидите, что слой Denseимеет 6 параметров, 5 весов плюс один параметр смещения).

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

0 голосов
/ 05 октября 2018

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

b = layers.Conv2D(5, (3,3), activation='relu', padding='same')(input_image)
b = layers.MaxPooling2D((2,2), strides=1,  padding='same')(b)
b = layers.Conv2D(5, (3,3), activation='relu', padding='same')(b)
b = layers.MaxPooling2D((2,2),strides=1 ,padding='same')(b)
# not use Dense, but Conv2D
binary_out = layers.Conv2D(1, (1,1), activation='sigmoid', padding='same')(b)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...