Почему тензор имеет другую форму при втором вызове функции «вызов»?

#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] , чтобы справиться со значением Нет.