#python #tensorflow #keras #tensor
Вопрос:
Позвольте мне представить вас: Я пытаюсь запустить алгоритм Fast-RCNN с RoiPoolingLayer, написанный на tensorflow.keras.
Вот текущий код RoIPoolingLayer:
class RoiPoolingConv(Layer): """ Define ROI Pooling Convolutional Layer for 2D inputs. """ def __init__(self, pool_size, num_rois, **kwargs): self.pool_size = pool_size self.num_rois = num_rois self.nb_channels = None super(RoiPoolingConv, self).__init__(**kwargs) def build(self, input_shape): self.nb_channels = input_shape[0][3] super(RoiPoolingConv, self).build(input_shape) def compute_output_shape(self, input_shape): return None, self.num_rois, self.pool_size, self.pool_size, self.nb_channels def call(self, x, mask=None): assert (len(x) == 2) # x[0] is image with shape (rows, cols, channels) img = x[0] # x[1] is roi with shape (num_rois,4) with ordering (x,y,w,h) rois = x[1] outputs = [] print('image shape', img) print('roi shape', rois, self.num_rois) for roi_idx in range(self.num_rois): x = rois[0, roi_idx, 0] y = rois[0, roi_idx, 1] w = rois[0, roi_idx, 2] h = rois[0, roi_idx, 3] x = tf.cast(x, tf.int32) y = tf.cast(y, tf.int32) w = tf.cast(w, tf.int32) h = tf.cast(h, tf.int32) rs = tf.image.resize(img[:, y:y h, x:x w, :], (self.pool_size, self.pool_size)) outputs.append(rs) print(outputs, 'before concatenate', outputs.__len__()) final_output = K.concatenate(outputs, axis=0) print(final_output, 'nreshape to: ', (1, self.num_rois, self.pool_size, self.pool_size, self.nb_channels)) final_output = K.reshape(final_output, (1, self.num_rois, self.pool_size, self.pool_size, self.nb_channels)) final_output = K.permute_dimensions(final_output, (0, 1, 2, 3, 4)) return final_output def get_config(self): config = {'pool_size': self.pool_size, 'num_rois': self.num_rois} base_config = super(RoiPoolingConv, self).get_config() return dict(list(base_config.items()) list(config.items()))
Как вы можете видеть, я пытаюсь отладить этот код, поэтому я печатаю некоторый код. Линия: final_output = K.reshape(final_output, (1, self.num_rois, self.pool_size, self.pool_size, self.nb_channels))
Вызывает ошибку, которая говорит мне, что я не могу изменить форму:
Невозможно преобразовать тензор с 3211264 элементами в форму [1,4,7,7,512] (100352 элемента) для «{{модель узла/roi_pooling_conv/Изменить форму}} = Изменить форму[T=DT_FLOAT, Tshape=DT_INT32](модель/roi_pooling_conv/конкат, модель/roi_pooling_conv/Изменить форму/форму) » с входными формами: [128,7,7,512], [5] и с вычисленными входными тензорами в виде частичных фигур: ввод[1] = [1,4,7,7,512].
Я попытался отладить все это, и самое интересное в call
функциях. Позвольте мне вставить вывод, чтобы я описал его позже:
image shape Tensor("Placeholder:0", shape=(None, 7, 7, 512), dtype=float32) roi shape Tensor("Placeholder_1:0", shape=(None, None, 4), dtype=float32) 4 [lt;tf.Tensor 'roi_pooling_conv/resize/ResizeBilinear:0' shape=(None, 7, 7, 512) dtype=float32gt;, lt;tf.Tensor 'roi_pooling_conv/resize_1/ResizeBilinear:0' shape=(None, 7, 7, 512) dtype=float32gt;, lt;tf.Tensor 'roi_pooling_conv/resize_2/ResizeBilinear:0' shape=(None, 7, 7, 512) dtype=float32gt;, lt;tf.Tensor 'roi_pooling_conv/resize_3/ResizeBilinear:0' shape=(None, 7, 7, 512) dtype=float32gt;] before concatenate 4 Tensor("roi_pooling_conv/concat:0", shape=(None, 7, 7, 512), dtype=float32) reshape to: (1, 4, 7, 7, 512) image shape Tensor("model/block5_pool/MaxPool:0", shape=(32, 7, 7, 512), dtype=float32) roi shape Tensor("model/Cast:0", shape=(32, 16, 4), dtype=float32) 4 [lt;tf.Tensor 'model/roi_pooling_conv/resize/ResizeBilinear:0' shape=(32, 7, 7, 512) dtype=float32gt;, lt;tf.Tensor 'model/roi_pooling_conv/resize_1/ResizeBilinear:0' shape=(32, 7, 7, 512) dtype=float32gt;, lt;tf.Tensor 'model/roi_pooling_conv/resize_2/ResizeBilinear:0' shape=(32, 7, 7, 512) dtype=float32gt;, lt;tf.Tensor 'model/roi_pooling_conv/resize_3/ResizeBilinear:0' shape=(32, 7, 7, 512) dtype=float32gt;] before concatenate 4 Tensor("model/roi_pooling_conv/concat:0", shape=(128, 7, 7, 512), dtype=float32) reshape to: (1, 4, 7, 7, 512)
So, I have 2 inputs, feature map and rois. Shape of feature map on first call
is None, 7, 7, 512
, in second call is 32, 7, 7, 512
.
Why? I have input of 32 images, with input_shape 224x224x3
. Does it mean, I have wrong preprocessed data?
Btw. Data I’m delivering, is MS COCO 2014, I’m loading image by cv2, resizing it to 224x224
and later some numpy operations:
# get RGB from BGR resized_image = resized_image[:, :, (2, 1, 0)] resized_image = resized_image.astype(numpy.float32) resized_image[:, :, 0] -= 103.939 resized_image[:, :, 1] -= 116.779 resized_image[:, :, 2] -= 123.68 resized_image /= 1.0 resized_image = numpy.transpose(resized_image, (2, 0, 1)) resized_image = numpy.expand_dims(resized_image, axis=0) resized_image = numpy.transpose(resized_image, (0, 2, 3, 1)) print('image size: ', resized_image.shape) _train_images.append(resized_image)
и append
к массиву.
Перед доставкой на CNN я делаю numpy.asarray
(пробовал раньше numpy.array
) Roi, в основном, выполняется на изображении с измененным размером путем выборочного поиска в x, y, w, h
формате. Он хранится в виде кортежа в массиве (массив кортежей), и перед его доставкой я тоже это делаю numpy.assarray()
. Делая 16 RoI на изображение — просто чтобы сделать это быстро, я хочу, чтобы сначала этот код работал правильно, а затем сделал 2000 roi на изображение. Неправильно ли предварительно обработаны данные? Я чувствую, что первое call
выполняется при «отсутствии данных», а затем второе call
получает массив изображений. Может кто-нибудь хотя бы сказать, чего мне не хватает?
Ответ №1:
При первом запуске метода вызова или метода подгонки экземпляра класса модели сначала вызывается метод сборки, который, в свою очередь, вызовет методы сборки слоев. Размер входного тензора с input_shape = (7, 7, 512)
будет установлен на (Нет, 7, 7, 512), ни один из которых не соответствует (неизвестному) размеру пакета. Позже размер этого тензора будет заменен (batch_size, 7, 7, 512) на batch_size=32 в вашем случае. В первом случае веса модели устанавливаются и инициализируются, и создается сетевой график. Затем все работает «нормально» с первым измерением входных тензоров, установленным в batch_size (число). В вашем случае вы указали input_shape = (None, 4)
тензор рентабельности инвестиций, верно?
В конце вашего слоя вы получаете тензор размера (128, 7, 7, 512) после объединения вдоль оси 0 (ось пакета). Так что вы не можете изменить его, чтобы (1, 4, 7, 7, 512). Вы могли бы, возможно, изменить его, чтобы (32, 4, 7, 7, 512) вот так :
final_output = K.reshape(final_output, (K.shape(img)[0], self.num_rois, self.pool_size, self.pool_size, self.nb_channels))
Обратите внимание на использование K.shape(img)[0]
, чтобы справиться со значением Нет.