Доброго времени суток, есть массив numpy с 300 изображениями, каждое изображение представляет собой одномерный массив из 2359296 элементов (мне не очень понятно, почему, так как изображения имеют размер 1024x1024 и три канала rgb, что по логике должно давать 3145728 элементов) (! Проблема с размером изображения решилась после удаления data.shuffle() !), и при попытке обучить модель на этих данных: model.fit(data, features, batch_size=64, epochs=3)
Возникает следующая ошибка: ValueError: Error when checking input: expected conv2d_input to have 4 dimensions, but got array with shape (300, 1)
Как мне переделать массив данных, чтобы keras его принял?
У вас размер батча должен быть (64, 1024, 1024, 3), а первый входной слой, соответственно, Input(shape=(1024, 1024, 3)). Причём тут 3145728, вы разве Conv2D не к двумерному изображению применяете? Почему у вас изображения в виде одномерного массива? Вот вам именно об этой ошибке и пишут, потому что Conv2D работает на массивах с 3 измерениями (height, width, channels). Покажите модель вашей нейросети.
Изображение я по аналогии с задачами классификации привел к одномерному массиву numpy.flatten, по крайней мере в таком виде я их подавал на svm классификатор, мне стоит опустить numpy.flatten в задачах свертки?
Модель у меня представляет следующий вид:
Andrei1penguin1, вам стоит изучить теорию свёрточных сетей. И понимать, что и почему вы делаете. Разумеется, на вход свёрточной сети нельзя подавать flattened изображения. У вас же написано input_shape=(1024, 1024, 3) - почему вы подаёте тензор другой размерности? Полная размерность у вас будет (batch_size, height, width, n_channels).
Andrey Dugin, Мой вопрос вы, можно сказать, решили, так как действительно указали на правильную ошибку, но возникла следующая проблема
Теперь сами тренировочные данные, имеющие 300 цветных изображений, принимаются, а вот выходные данные, имеющие 300 массивов с 70 точками, заданными двумя координатами-нет, дело из-за другой размерности выходного слоя: ValueError: Error when checking target: expected conv2d_12 to have 4 dimensions, but got array with shape (300, 70, 2)
Погуглив, нашел следующий способ: после свертки, когда уже начинается голое машинная тренировка, приводить данные к размерности выходных, но мне кажется, что это бред и есть способы лучше
Может быть можно как-то отдельно задать размер выходных данных?
Andrei1penguin1, не бред. Данные надо приводить к размерности выходных - либо в самой нейросети, нибо в процессе интерпретации данных, полученных от нейросети. Так-то можете на выход выдавать хоть плоский массив - если при пост-обработке сделаете reshape. Ну и loss-функцию как-то считать надо - а на данных правильной формы это проще.
Хорошо, то есть мне после последнего слоя свертки conv2d добавить flatten данных, а затем две единички спереди?
Так как последний слой conv2d имеет размерность 30x30, получим его flatten 900
Тогда получится, что из (1, 1, 900) будет получаться нужные мне точки (70, x-координата, y-координата)?
Из (1, 1, 900) не получится (70, 2). Произведения всех размерностей в обоих случаях должны быть одинаковыми. Можете добавить промежуточный Dense-слой, который преобразует размерность к нужной. Но если вы хотите получить на выходе абсолютные координаты, это вряд ли будет работать хорошо. Почитайте, например, как кодируются данные на выходе YOLO и что такое anchor boxes.
Andrei1penguin1, нет, не всё равно. Ещё раз, почитайте, как работает нейросеть YOLO и что там на выходе. Кстати, а confidence вы не учитывате, например?
confidence это же вроде уверенность сети в предсказаниях
Почитал про YOLO, но ответ на мой вопрос это все равно не дало
И почему на выходе будет не 3 значения?
Все же логично: первое значение это количество точек, второе и третье значение: это координаты x, y каждой точки
Аа, ну на выходе-то двумерный массив будет, массив с точками и у каждой точки в одном массиве две координаты через запятую
Получается в таком случае мне просто нужно выходные данные, изображение размерностью 30, 30, 3 привести к размерности (900, 3), где 900-изображение в одномерном виде, а 3-количество каналов?
Изменил размер features (то есть точек) с (300, 70, 2) на (1, 300, 70, 2), на один шаг продвинулся, но теперь лезет ошибка: ValueError: Error when checking target: expected conv2d_12 to have shape (233, 233, 30) but got array with shape (300, 70, 2)
Так как последний слой у меня имеет глубину 30 пикселей, то видимо (233, 233, 30)-это изображение в конце всей свертки
Как мне в таком случае подогнать изображение под такие же размеры. как и массив с точками (features)?
Мне нужен ваш совет
Если взглянуть на размерность данных, то:
x.shape (фотографии) == (300, 1024, 1024, 3)
y.shape (точки) == (300, 70, 2)
Я думаю сделать по логике и получить следующее:
По факту изображение у меня исчисляется как ширина на высоту на количество каналов, следовательно, я могу в таком же виде представить точки
По сути у меня 70 координат x и 70 координат y, то есть я могу массив с точками представить как (300, 70(все координаты по x), 70(все координаты по y), 1(каналов нет, но единичка уравняет размерность))
И для каждой фотографии получу input(1, 1024, 1024, 3) и output(1, 70, 70, 1)
Скажите пожалуйста, сможет ли сеть обучиться на таких данных, или я делаю совершенно неправильно?
Andrei1penguin1, если у вас 70 точек и для каждой 2 координаты, то это массив размерности (70, 2). То есть на выходе должно получиться (300, 70, 2), причём 300 - это размер батча и в явном виде при послойном построении сети не указывается. Той привязки размерности выхода к размерности входа, что вы себе вообразили, нет - размерность выхода может быть практически любой. Совпадать будет только размер батча.
По сути у меня 70 координат x и 70 координат y, то есть я могу массив с точками представить как (300, 70(все координаты по x), 70(все координаты по y), 1(каналов нет, но единичка уравняет размерность))
То есть вы 70 * 2 = 140 чисел хотите уложить в матрицу 70 * 70 = 4900? Это каким образом?
Не забывайте, что после свёрточных слоёв у вас идут один или более Dense-слоёв, с помощью которых вы можете преобразовать размерность (количество чисел) к нужной, и затем преобразовать в тензор нужной формы с помощью Reshape-слоя. Иными словами:
А откуда взялись 4900, почему 70 должно возводиться в квадрат?
Той привязки размерности выхода к размерности входа, что вы себе вообразили, нет - размерность выхода может быть практически любой. Совпадать будет только размер батча.
Но у меня ведь размер батча совпадает, почему тогда ошибка?
Andrei1penguin1, потому что матрица (70, 70) - это квадрат из 4900 значений. Что касается размерности, трейс ошибки говорит, что вы в выхлоп свёртки размерности (batch_size, 233, 233, 30) пытаетесь засунуть Y размерности (batch_size, 70, 2). После последнего свёрточного слоя вам надо преобразовать размерность выхода Conv2D к размерности Y. Как - написал в предыдущем комментарии. Например, сделайте Flatten(), потом Dense() из 140 нейронов, потом Reshape() в финальную форму (70, 2).
По сути у меня 70 координат x и 70 координат y, то есть я могу массив с точками представить как (300, 70(все координаты по x), 70(все координаты по y), 1(каналов нет, но единичка уравняет размерность))
Я пересобрал данные, но почему-то лезет та же ошибка: ValueError: Error when checking input: expected conv2d_input to have 4 dimensions, but got array with shape (300, 1)
Для достоверности я вывел размер данных:
Andrey Dugin, вообще да, но я вчера действительно обнаружил, что через len(data) размерность получается (300, 1024, 1024, 3), а data.shape выводит (300, 1), а происходит это скорее всего из-за того, что размерность данных должна быть идентична, так как данных 300, то во-первых batch-size должен быть кратен этому числу, например 50, если я конечно правильно понимаю, и во-вторых надо проверить размер каждой фотографии, возможно где-то несостыковка в размерах