Проблема с выяснением того, как определить input_shape в слое Conv2D в Keras для моего собственного набора данных

TL,DR

Я получаю эти ошибки при определении формы ввода

ValueError: Error when checking input: expected conv2d_1_input to have 4 dimensions, but got array with shape (4000, 20, 20)

or

ValueError: Input 0 is incompatible with layer conv2d_1: expected ndim=4, found ndim=5

Длинная явная версия:

Я использую разные Keras NN, чтобы попробовать классифицировать свой собственный набор данных.

До сих пор у меня был успех с моей ANN, но у меня проблемы с CNN.

набор данных

Полный код

Набор данных состоит из матриц заданного размера, заполненных нулями, которые содержат подматрицу заданного размера и заполнены единицами. Подматрица необязательна, и цель состоит в том, чтобы научить NN предсказывать, содержит ли матрица подматрицу или нет. Чтобы его было сложнее обнаружить, я добавляю в матрицы различные типы шума.

Вот изображение того, как выглядит отдельная матрица, черные части - это 0, а белые части - это 1. Между пикселями изображения и элементами матрицы существует соответствие 1:1.

введите здесь описание изображения

Я сохраняю их в тексте, используя numpy savetxt и loadtxt. Тогда это выглядит так:

#________________Array__Info:__(4000, 20, 20)__________
#________________Entry__Number__1________
0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 1
0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 1
0 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1
0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 1
0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0
0 1 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0
#________________Entry__Number__2________
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0
1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1
1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0
0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0
1 0 1 0 0 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1
0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
1 0 0 0 1 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0
0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 1 0 0
0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 0 0 1
0 1 0 0 0 0. . . . . . (and so on)

Полный набор данных

код CNN

Github

Код: (импорт опущен)

# data

inputData = dsg.loadDataset("test_input.txt")
outputData = dsg.loadDataset("test_output.txt")
print("the size of the dataset is: ", inputData.shape, " of type: ", type(inputData))


# parameters

# CNN

cnn = Sequential()

cnn.add(Conv2D(32, (3, 3), input_shape = inputData.shape, activation = 'relu'))

cnn.add(MaxPooling2D(pool_size = (2, 2)))

cnn.add(Flatten())

cnn.add(Dense(units=64, activation='relu'))

cnn.add(Dense(units=1, activation='sigmoid'))

cnn.compile(optimizer = "adam", loss = 'binary_crossentropy', metrics = ['accuracy'])

cnn.summary()

cnn.fit(inputData,
        outputData,
        epochs=100,
        validation_split=0.2)

Проблема:

Я получаю это сообщение об ошибке вывода

Using TensorFlow backend.
the size of the dataset is:  (4000, 20, 20)  of type:  <class 'numpy.ndarray'>
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 3998, 18, 32)      5792      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 1999, 9, 32)       0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 575712)            0         
_________________________________________________________________
dense_1 (Dense)              (None, 64)                36845632  
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 65        
=================================================================
Total params: 36,851,489
Trainable params: 36,851,489
Non-trainable params: 0
_________________________________________________________________
Traceback (most recent call last):
  File "D:\GOOGLE DRIVE\School\sem-2-2018\BSP2\BiCS-BSP-2\CNN\matrixCNN.py", line 47, in <module>
    validation_split=0.2)
  File "C:\Code\Python\lib\site-packages\keras\models.py", line 963, in fit
    validation_steps=validation_steps)
  File "C:\Code\Python\lib\site-packages\keras\engine\training.py", line 1637, in fit
    batch_size=batch_size)
  File "C:\Code\Python\lib\site-packages\keras\engine\training.py", line 1483, in _standardize_user_data
    exception_prefix='input')
  File "C:\Code\Python\lib\site-packages\keras\engine\training.py", line 113, in _standardize_input_data
    'with shape ' + str(data_shape))
ValueError: Error when checking input: expected conv2d_1_input to have 4 dimensions, but got array with shape (4000, 20, 20)

Я действительно не знаю, как я могу решить эту проблему. Я просмотрел документацию Conv2D, в которой говорится, что нужно поместить ее в такую ​​форму: (партия, высота, ширина, каналы). В моем случае это (я думаю):

input_shape=(4000, 20, 20, 1)

, так как у меня есть 4000 матриц 20 * 20 только с 1 и 0

Но затем я получаю это сообщение об ошибке:

Using TensorFlow backend.
the size of the dataset is:  (4000, 20, 20)  of type:  <class 'numpy.ndarray'>
Traceback (most recent call last):
  File "D:\GOOGLE DRIVE\School\sem-2-2018\BSP2\BiCS-BSP-2\CNN\matrixCNN.py", line 30, in <module>
    cnn.add(Conv2D(32, (3, 3), input_shape = (4000, 12, 12, 1), activation = 'relu'))
  File "C:\Code\Python\lib\site-packages\keras\models.py", line 467, in add
    layer(x)
  File "C:\Code\Python\lib\site-packages\keras\engine\topology.py", line 573, in __call__
    self.assert_input_compatibility(inputs)
  File "C:\Code\Python\lib\site-packages\keras\engine\topology.py", line 472, in assert_input_compatibility
    str(K.ndim(x)))
ValueError: Input 0 is incompatible with layer conv2d_1: expected ndim=4, found ndim=5

В какой именно форме я должен передавать данные в CNN?

Все файлы доступны здесь Спасибо за ваше время.


person charel-f    schedule 15.04.2018    source источник


Ответы (2)


Ваш CNN ожидает форму (num_samples, 20, 20, 1), а ваши данные имеют формат (num_samples, 20, 20).

Поскольку у вас есть только 1 канал, вы можете просто изменить данные на (4000, 20, 20, 1)

inputData = inputData.reshape(-1, 20, 20, 1)

Если вы хотите изменить форму внутри модели, вы можете просто добавить слой Reshape. В качестве первого слоя:

model.add(Reshape(input_shape = (20, 20), target_shape=(20, 20, 1)))
person Primusa    schedule 15.04.2018
comment
Наконец-то он заработал, используя ваш ответ и другой поток. Хотя ваш ответ не дал окончательного решения, он помог мне понять и найти решение. Большое тебе спасибо. Для всех, кто интересуется полным решением, я опубликую его как ответ на мой вопрос. - person charel-f; 16.04.2018
comment
Я рад, что помог вам найти решение. Удачи и хороших тренировок :) - person Primusa; 16.04.2018

Благодаря помощи Primusa и эту другую тему, которую я нашел, я заставил ее работать. Вот что я добавил:

inputData = inputData.reshape(4000, 20, 20, 1)
outputData = outputData.reshape(4000, 1)

со слоем conv2D

cnn.add(Conv2D(32, (3, 3), input_shape = (20, 20, 1), activation = 'relu'))
person charel-f    schedule 15.04.2018
comment
почему вам нужно изменить форму выходных данных? - person Daniel Vilas-Boas; 10.12.2020
comment
Это было давно, но я думаю, потому что выход и ввод должны были иметь одинаковое последнее измерение или что-то в этом роде, не уверен.. - person charel-f; 10.12.2020
comment
Я пытался использовать свёрточную сеть для решения задачи 1d. Для тех, кто не советуется, как я, пожалуйста, не... это не настоящая цель такого алгоритма - person Daniel Vilas-Boas; 10.12.2020