Как изменяется форма данных во время Conv2D и Dense в Keras?

Как и сказано в названии. Этот код работает только с использованием:

x = Flatten()(x)

Между сверточным слоем и плотным слоем.

import numpy as np
import keras
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, Flatten, Input
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD

# Generate dummy data
x_train = np.random.random((100, 100, 100, 3))
y_train = keras.utils.to_categorical(np.random.randint(10, size=(100, 1)), num_classes=10)

#Build Model
input_layer = Input(shape=(100, 100, 3))
x = Conv2D(32, (3, 3), activation='relu')(input_layer)
x = Dense(256, activation='relu')(x)
x = Dense(10, activation='softmax')(x)
model = Model(inputs=[input_layer],outputs=[x])

#compile network
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)

#train network
model.fit(x_train, y_train, batch_size=32, epochs=10)

В противном случае я получаю такую ​​ошибку:

Traceback (most recent call last):

File "/home/michael/practice_example.py", line 44, in <module>
    model.fit(x_train, y_train, batch_size=32, epochs=10)

File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 1435, in fit
    batch_size=batch_size)

File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 1315, in _standardize_user_data
    exception_prefix='target')

File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 127, in _standardize_input_data
    str(array.shape))

ValueError: Error when checking target: expected dense_2 to have 4 dimensions, but got array with shape (100, 10)

Почему выход будет иметь 4 измерения без слоя flatten()?


person MichaelAndroidNewbie    schedule 07.07.2017    source источник


Ответы (2)


По словам Кераса Док,

Форма вывода Conv2D

4D тензор с формой: (образцы, фильтры, new_rows, new_cols), если data_format = 'channels_first' или 4D тензор с формой: (samples, new_rows, new_cols, filters) if data_format = 'channels_last'. Значения строк и столбцов могли измениться из-за заполнения.

Поскольку вы используете channels_last, форма вывода слоя будет следующей:

# shape=(100, 100, 100, 3)

x = Conv2D(32, (3, 3), activation='relu')(input_layer)
# shape=(100, row, col, 32)

x = Flatten()(x)
# shape=(100, row*col*32)    

x = Dense(256, activation='relu')(x)
# shape=(100, 256)

x = Dense(10, activation='softmax')(x)
# shape=(100, 10)

Объяснение ошибки (отредактировано, спасибо @Marcin)

Связывание четырехмерного тензора (shape = (100, row, col, 32)) с двухмерным (shape = (100, 256)) с использованием слоя Dense по-прежнему будет формировать четырехмерный тензор (shape = (100, row, col, 256 )) чего вы не хотите.

# shape=(100, 100, 100, 3)

x = Conv2D(32, (3, 3), activation='relu')(input_layer)
# shape=(100, row, col, 32)

x = Dense(256, activation='relu')(x)
# shape=(100, row, col, 256)

x = Dense(10, activation='softmax')(x)
# shape=(100, row, col, 10)

И ошибка возникает, когда возникает несоответствие между выходным тензором 4D и целевым тензором 2D.

Вот почему вам нужен слой Flatten, чтобы сгладить его из 4D в 2D.

Ссылка

Conv2D Плотный

person YLJ    schedule 07.07.2017
comment
Собственно - ваш ответ неверен. Вы можете применить слой Dense к 4d. Вот откуда возникает ошибка. - person Marcin Możejko; 07.07.2017
comment
Итак, я могу подключить его, но когда я указываю целевые значения 2D, он выдает ошибку? - person MichaelAndroidNewbie; 07.07.2017
comment
Да, @ MarcinMożejko прав. Спасибо. Я только что отредактировал свой ответ - person YLJ; 07.07.2017

Из документации Dense можно прочитать, что в случае, когда вход в Dense имеет более двух размеры - применяется только к последнему - и все остальные размеры сохраняются:

# shape=(100, 100, 100, 3)

x = Conv2D(32, (3, 3), activation='relu')(input_layer)
# shape=(100, row, col, 32)

x = Dense(256, activation='relu')(x)
# shape=(100, row, col, 256)

x = Dense(10, activation='softmax')(x)
# shape=(100, row, col, 10)

Вот почему ожидается 4d цель.

person Marcin Możejko    schedule 07.07.2017
comment
Извините, что вы имеете в виду, говоря, что он применяется только к последнему, а все остальные измерения сохраняются? - person MichaelAndroidNewbie; 07.07.2017
comment
Это похоже на свертку с размером фильтра (1, 1). Слой Dense применяется для каждого пикселя в каждой строке и столбце, и результат возвращается в виде карты пикселей (как показано в примере). - person Marcin Możejko; 07.07.2017