Размер представления несовместим с размером тензора входных данных и шагом.

Вопрос или проблема

Я пытаюсь обучить F-RCNN на наборе данных coco на своих изображениях. Размер изображения 512X512. Я протестировал загрузчик данных отдельно, и он работает и выводит пакетные изображения и детали BB. Также я попытался вывести потери в НН, и он также печатает batch_mean, а после этого возникает ОШИБКА.

img_process = v2.Compose(
    [
        v2.ToTensor(),
        v2.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
    ]
)

class SCocoDetection(datasets.CocoDetection):
    def __init__(
        self,
        image_directory_path: str,
        annotation_path : str,
        train: bool = True,
        image_processor = None
    ):
        super().__init__(image_directory_path, annotation_path)
        self.image_processor = image_processor

    def __getitem__(self, idx):

        image, annotations = super().__getitem__(idx)
        images, targets = [], []
        image_id = self.ids[idx]

        for ann in annotations:
            bbox = ann['bbox']
            #small = (bbox[:, 2] * bbox[:, 3]) <= (image.size[1] * image.size[0] * 0.001)
            small = (bbox[2] * bbox[3]) <= (512 * 512 * 0.001)
            #print(small)
            if small:
                bbox = torch.tensor(bbox).unsqueeze(0).float()
                boxes = ops.box_convert(bbox, in_fmt="xywh", out_fmt="xyxy")
                boxes = boxes.float()
                if (boxes[0][0] < boxes[0][2]) and (boxes[0][1] < boxes[0][3]):
                    output_dict = self.image_processor({"image": image, "boxes": boxes})
                    images.append(output_dict['image'])
                    targets.append({
                        'boxes': output_dict['boxes'],
                        'labels': torch.ones(len(boxes), dtype=int)
                    })
                else:
                    print(f"Неверная коробка : {boxes}")
        #print(f"image_id : {image_id} , idx : {idx} , targets :{targets}")
        return images, targets

TRAIN_DATASET = SCocoDetection(

    image_directory_path="047/v2_coco_train/images",
    annotation_path="047/v2_coco_train/result.json",
    image_processor=img_process,
    train=True)
VAL_DATASET = SCocoDetection(
    image_directory_path="047/v2_coco_test/images",
    annotation_path="047/v2_coco_test/result.json",
    image_processor=img_process,
    train=False)

print("Количество примеров для обучения:", len(TRAIN_DATASET))
print("Количество примеров для проверки:", len(VAL_DATASET))
#print("Количество тестовых примеров:", len(TEST_DATASET))

def collate_fn(batch):
    return tuple(zip(*batch))

TRAIN_DATALOADER = DataLoader(dataset=TRAIN_DATASET, collate_fn=collate_fn, batch_size=2, shuffle=True)
VAL_DATALOADER = DataLoader(dataset=VAL_DATASET, collate_fn=collate_fn, batch_size=4, shuffle=True)
import numpy as np

class CocoDNN(L.LightningModule):
    def __init__(self):
        super().__init__()
        self.model = models.detection.fasterrcnn_mobilenet_v3_large_fpn(weights="DEFAULT")

    def forward(self, images, targets=None):
        return self.model(images, targets)

    def training_step(self, batch, batch_idx):
        imgs, annot = batch
        print(f"Пакет :{batch_idx}")

        batch_losses = []
        for img_b, annot_b in zip(imgs, annot):
            print(len(img_b), len(annot_b))
            if len(img_b) == 0:
                continue
            loss_dict = self.model(img_b, annot_b)
            losses = sum(loss for loss in loss_dict.values())
            #print(losses)
            batch_losses.append(losses)

        batch_mean  = torch.mean(torch.stack(batch_losses))
        #print(batch_mean)
        self.log('train_loss', batch_mean)

    def configure_optimizers(self):
        return optim.SGD(self.parameters(), lr=0.001, momentum=0.9, weight_decay=0.0005)

dnn = CocoDNN()
trainer = L.Trainer(limit_train_batches=100, max_epochs=1)
trainer.fit(model=dnn, train_dataloaders=TRAIN_DATALOADER)

### Сообщения об ошибках и логи

{
    "name": "RuntimeError",
    "message": "размер представления несовместим с размером входного тензора и шагом (по крайней мере одно измерение охватывает два смежных подпространства). Вместо этого используйте .reshape(...).",
    "stack": "---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[192], line 3
      1 dnn = CocoDNN()
      2 trainer = L.Trainer(limit_train_batches=100, max_epochs=1)
----> 3 trainer.fit(model=dnn, train_dataloaders=TRAIN_DATALOADER)

File site-packages/lightning/pytorch/trainer/trainer.py:538, in Trainer.fit(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)
    536 self.state.status = TrainerStatus.RUNNING
    537 self.training = True
--> 538 call._call_and_handle_interrupt(
    539     self, self._fit_impl, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)
    540 )

File site-packages/lightning/pytorch/trainer/call.py:47, in _call_and_handle_interrupt(trainer, trainer_fn, *args, **kwargs)
     45     if trainer.strategy.launcher is not None:
         return trainer.strategy.launcher.launch(trainer_fn, *args, trainer=trainer, **kwargs)
---> 47     return trainer_fn(*args, **kwargs)
     49 except _TunerExitException:
     50     _call_teardown_hook(trainer)

File site-packages/lightning/pytorch/trainer/trainer.py:574, in Trainer._fit_impl(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)
    567 assert self.state.fn is not None
    568 ckpt_path = self._checkpoint_connector._select_ckpt_path(
    569     self.state.fn,
    570     ckpt_path,
    571     model_provided=True,
    572     model_connected=self.lightning_module is not None,
    573 )
--> 574 self._run(model, ckpt_path=ckpt_path)
    576 assert self.state.stopped
    577 self.training = False

File site-packages/lightning/pytorch/trainer/trainer.py:981, in Trainer._run(self, model, ckpt_path)
    976 self._signal_connector.register_signal_handlers()
    978 # ----------------------------
    979 # ЗАПУСК ТРЕНЕРА
    980 # ----------------------------
--> 981 results = self._run_stage()
    983 # ----------------------------
    984 # ПОСЛЕ ТРЕНИРОВКИ ЧИСТКА
    985 # ----------------------------
    986 log.debug(f\"{self.__class__.__name__}: тренер отключается\")

File site-packages/lightning/pytorch/trainer/trainer.py:1025, in Trainer._run_stage(self)
   1023         self._run_sanity_check()
   1024     with torch.autograd.set_detect_anomaly(self._detect_anomaly):
--> 1025         self.fit_loop.run()
   1026     return None
   1027 raise RuntimeError(f\"Неожиданное состояние {self.state}\")

File site-packages/lightning/pytorch/loops/fit_loop.py:205, in _FitLoop.run(self)
    203 try:
    204     self.on_advance_start()
--> 205     self.advance()
    206     self.on_advance_end(data_fetcher)
    207     self._restarting = False

File site-packages/lightning/pytorch/loops/training_epoch_loop.py:140, in _TrainingEpochLoop.run(self, data_fetcher)
    138 while not self.done:
    139     try:
--> 140         self.advance(data_fetcher)
    141         self.on_advance_end(data_fetcher)
    142     self._restarting = False

File site-packages/lightning/pytorch/loops/training_epoch_loop.py:250, in _TrainingEpochLoop.advance(self, data_fetcher)
    247 with trainer.profiler.profile(\"run_training_batch\"):
    248     if trainer.lightning_module.automatic_optimization:
    249         # при автоматической оптимизации может быть только один оптимизатор
--> 250         batch_output = self.automatic_optimization.run(trainer.optimizers[0], batch_idx, kwargs)
    251     else:
    252         batch_output = self.manual_optimization.run(kwargs)

File site-packages/lightning/pytorch/loops/optimization/automatic.py:190, in _AutomaticOptimization.run(self, optimizer, batch_idx, kwargs)
    183         closure()
    185 # ------------------------------
    186 # ЗАДЕЛ ЗА КЛИЕНТА
    187 # ------------------------------
    189 else:
--> 190     self._optimizer_step(batch_idx, closure)
    192 result = closure.consume_result()
    193 if result.loss is None:

File site-packages/lightning/pytorch/loops/optimization/automatic.py:268, in _AutomaticOptimization._optimizer_step(self, batch_idx, train_step_and_backward_closure)
    265     self.optim_progress.optimizer.step.increment_ready()
    267 # модельный хук
--> 268 call._call_lightning_module_hook(
    269     trainer,
    270     \"optimizer_step\",
    271     trainer.current_epoch,
    272     batch_idx,
    273     optimizer,
    274     train_step_and_backward_closure,
    275 )
    277 if not should_accumulate:
    278     self.optim_progress.optimizer.step.increment_completed()

File site-packages/lightning/pytorch/trainer/call.py:167, in _call_lightning_module_hook(trainer, hook_name, pl_module, *args, **kwargs)
    164 pl_module._current_fx_name = hook_name
    166 with trainer.profiler.profile(f\"[LightningModule]{pl_module.__class__.__name__}.{hook_name}\"):
--> 167     output = fn(*args, **kwargs)
    169 # восстанавливаем current_fx, когда вложенный контекст
    170 pl_module._current_fx_name = prev_fx_name

File site-packages/lightning/pytorch/core/module.py:1306, in LightningModule.optimizer_step(self, epoch, batch_idx, optimizer, optimizer_closure)
   1275 def optimizer_step(
   1276     self,
   1277     epoch: int,
   (...)
   1280     optimizer_closure: Optional[Callable[[], Any]] = None,
   1281 ) -> None:
   1282 r\"\"\"Переопределите этот метод, чтобы изменить способ, которым :class:`~lightning.pytorch.trainer.trainer.Trainer` вызывает оптимизатор.
   1283 
   (...)
   1304 
   1305     \"\"\"
-> 1306     optimizer.step(closure=optimizer_closure)

File site-packages/lightning/pytorch/core/optimizer.py:153, in LightningOptimizer.step(self, closure, **kwargs)
    150     raise MisconfigurationException(\"Когда `optimizer.step(closure)` вызывается, замыкание должно быть вызываемым\")
    152 assert self._strategy is not None
--> 153 step_output = self._strategy.optimizer_step(self._optimizer, closure, model, **kwargs)

File site-packages/lightning/pytorch/strategies/strategy.py:238, in Strategy.optimizer_step(self, optimizer, closure, model, **kwargs)
    236 # TODO(fabric): удалить утверждение, как только типизация optimizer_step стратегии будет исправлена
    237 assert isinstance(model, pl.LightningModule)
--> 238 return self.precision_plugin.optimizer_step(optimizer, model=model, closure=closure, **kwargs)

File site-packages/lightning/pytorch/plugins/precision/precision.py:122, in Precision.optimizer_step(self, optimizer, model, closure, **kwargs)
     120 \"\"\"Хук для выполнения шага оптимизатора.\"\"\"
     121 closure = partial(self._wrap_closure, model, optimizer, closure)
--> 122 return optimizer.step(closure=closure, **kwargs)

File site-packages/torch/optim/optimizer.py:487, in Optimizer.profile_hook_step.<locals>.wrapper(*args, **kwargs)
    482         else:
    483             raise RuntimeError(
    484                 f\"{func} должен возвращать None или кортеж из (new_args, new_kwargs), но вместо этого получил {result}.\"
    485             )
--> 487 out = func(self, *args, **kwargs)
     488 self._optimizer_step_code()
     490 # вызов пост-хуков шага оптимизатора

File site-packages/torch/optim/optimizer.py:91, in _use_grad_for_differentiable.<locals>._use_grad(self, *args, **kwargs)
     89     torch.set_grad_enabled(self.defaults[\"differentiable\"])
     90     torch._dynamo.graph_break()
---> 91     ret = func(self, *args, **kwargs)
     92 finally:
     93     torch._dynamo.graph_break()

File site-packages/torch/optim/sgd.py:112, in SGD.step(self, closure)
    110 if closure is not None:
    111     with torch.enable_grad():
--> 112         loss = closure()
    114 for group in self.param_groups:
    115     params: List[Tensor] = []

File site-packages/lightning/pytorch/plugins/precision/precision.py:108, in Precision._wrap_closure(self, model, optimizer, closure)
     95 def _wrap_closure(
     96     self,
     97     model: \"pl.LightningModule\",
     98     optimizer: Steppable,
     99     closure: Callable[[], Any],
    100 ) -> Any:
     101 \"\"\"Это двойное замыкание позволяет убедиться в том, что ``closure`` выполняется перед вызовом хука ``on_before_optimizer_step``.
     102 
   (...)
    106 
    107     \"\"\"
--> 108     closure_result = closure()
    109     self._after_closure(model, optimizer)
    110     return closure_result

File site-packages/lightning/pytorch/loops/optimization/automatic.py:144, in Closure.__call__(self, *args, **kwargs)
    142 @override
    143 def __call__(self, *args: Any, **kwargs: Any) -> Optional[Tensor]:
--> 144     self._result = self.closure(*args, **kwargs)
    145     return self._result.loss

File site-packages/torch/utils/_contextlib.py:116, in context_decorator.<locals>.decorate_context(*args, **kwargs)
    113 @functools.wraps(func)
    114 def decorate_context(*args, **kwargs):
    115     with ctx_factory():
--> 116         return func(*args, **kwargs)

File site-packages/lightning/pytorch/loops/optimization/automatic.py:138, in Closure.closure(self, *args, **kwargs)
    135     self._zero_grad_fn()
    137 if self._backward_fn is not None and step_output.closure_loss is not None:
--> 138     self._backward_fn(step_output.closure_loss)
    140 return step_output

File site-packages/lightning/pytorch/loops/optimization/automatic.py:239, in _AutomaticOptimization._make_backward_fn.<locals>.backward_fn(loss)
    238 def backward_fn(loss: Tensor) -> None:
    239     call._call_strategy_hook(self.trainer, \"backward\", loss, optimizer)

File site-packages/lightning/pytorch/trainer/call.py:319, in _call_strategy_hook(trainer, hook_name, *args, **kwargs)
    316     return None
    318 with trainer.profiler.profile(f\"[Strategy]{trainer.strategy.__class__.__name__}.{hook_name}\"):
--> 319     output = fn(*args, **kwargs)
    321 # восстановление current_fx при вложенном контексте
    322 pl_module._current_fx_name = prev_fx_name

File site-packages/lightning/pytorch/strategies/strategy.py:212, in Strategy.backward(self, closure_loss, optimizer, *args, **kwargs)
    209 assert self.lightning_module is not None
    210 closure_loss = self.precision_plugin.pre_backward(closure_loss, self.lightning_module)
--> 212 self.precision_plugin.backward(closure_loss, self.lightning_module, optimizer, *args, **kwargs)
    214 closure_loss = self.precision_plugin.post_backward(closure_loss, self.lightning_module)
    215 self.post_backward(closure_loss)

File site-packages/lightning/pytorch/plugins/precision/precision.py:72, in Precision.backward(self, tensor, model, optimizer, *args, **kwargs)
     52 @override
     53 def backward(  # type: ignore[override]
     54     self,
   (...)
     59     **kwargs: Any,
     60 ) -> None:
     61     r\"\"\"Выполняет фактическое обратное распространение.
     62 
     63     Аргументы:
   (...)
     70 
     71     \"\"\"
---> 72     model.backward(tensor, *args, **kwargs)

File site-packages/lightning/pytorch/core/module.py:1101, in LightningModule.backward(self, loss, *args, **kwargs)
   1099     self._fabric.backward(loss, *args, **kwargs)
   1100 else:
-> 1101     loss.backward(*args, **kwargs)

File site-packages/torch/_tensor.py:581, in Tensor.backward(self, gradient, retain_graph, create_graph, inputs)
    571 if has_torch_function_unary(self):
    572     return handle_torch_function(
    573, 
    (self,),
   (...)
    579, 
    inputs=inputs)
    581 torch.autograd.backward(
    582     self, gradient, retain_graph, create_graph, inputs=inputs)

File site-packages/torch/autograd/__init__.py:347, in backward(tensors, grad_tensors, retain_graph, create_graph, grad_variables, inputs)
    342     retain_graph = create_graph
    344 # Причина, по которой мы повторяем тот же комментарий ниже, в том, что
    345 # некоторые версии Python выводят первую строку многострочной функции
    346 # вызовов в трассировке, а некоторые выводят последнюю строку
--> 347 _engine_run_backward(
    348     tensors,
    349     grad_tensors_,
    350     retain_graph,
    351     create_graph,
    352     inputs,
    353     allow_unreachable=True,
    354     accumulate_grad=True,
    355 )

File site-packages/torch/autograd/graph.py:825, in _engine_run_backward(t_outputs, *args, **kwargs)
    823     unregister_hooks = _register_logging_hooks_on_whole_graph(t_outputs)
    824 try:
--> 825     return Variable._execution_engine.run_backward(  # Вызов в C++-двигатель для выполнения обратного прохода
    826         t_outputs, *args, **kwargs
    827     )  # Вызов в C++-двигатель для выполнения обратного прохода
    828 finally:
    829     if attach_logging_hooks:

RuntimeError: размер представления несовместим с размером входного тензора и шагом (по крайней мере одно измерение охватывает два смежных подпространства). Используйте .reshape(...) вместо."
}

Среда

Текущая среда

#- Версия PyTorch Lightning (например, 2.4.0):  2.4.0
#- Версия PyTorch (например, 2.4): 2.5.1
#- Версия Python (например, 3.12): 3.11
#- ОС (например, Linux): MacOS
#- Версия CUDA/cuDNN:
#- Модели и конфигурация GPU: MPS
#- Как вы установили Lightning (`conda`, `pip`, source): pip

Больше информации

Нет ответа

Ответ или решение

Ошибка "view size is not compatible with input tensor’s size and stride"

Когда вы работаете с моделями глубокого обучения, такими как Faster R-CNN (F-RCNN), часто возникают ошибки, связанные с несовместимостью размеров тензоров. Одной из распространенных ошибок является ошибка RuntimeError: view size is not compatible with input tensor's size and stride. В вашем случае это происходит во время тренировки модели на COCO-данных с размером изображений 512×512. Давайте разберемся с этой проблемой более подробно.

Причины ошибки

  1. Несоответствие размеров тензоров: Эта ошибка может возникнуть в результате попытки изменить форму (view) тензора на такие размеры, которые не совместимы с его фактическими размерами и шагами (stride). Например, если вы пытаетесь изменить размер тензора, у которого есть "пробелы" по сравнению с ожидаемыми размерами.

  2. Неправильная обработка изображений: В вашем коде вы используете преобразования изображения и обработку аннотаций (bounding boxes). Если какая-то часть кода производит тензоры неправильного размера или формы, это может привести к ошибкам во время выполнения.

  3. Использование неправильных индексов или неправильные данные: Ваша модель может получать входные данные, которые не были обработаны должным образом. Например, если в target нет валидных аннотаций или если вы передаете пустой список изображений в модель.

Решение проблемы

  1. Проверка размеров тензоров: Перед тем, как передавать данные в модель, добавьте проверки, выводящие формы входных тензоров. Например, вы можете добавить print() для проверки форм img_b и annot_b перед вызовом self.model(img_b, annot_b) в методе training_step.

    for img_b, annot_b in zip(imgs, annot):
        print(f"Image batch shape: {img_b.shape}, Annotations: {annot_b}")
        if len(img_b) == 0:
            continue
        # ...
  2. Убедитесь, что bounding boxes корректны: Ошибка также может возникнуть, если боксы (bounding boxes) формируются неправильно. Убедитесь, что все аннотации имеют правильную форму и размер.

  3. Использование .reshape(...) вместо .view(...): Как указывает сообщение об ошибке, попытка изменить размер тензора с использованием .view(...) может привести к проблемам, если тензор не является непрерывным. Вместо view, попробуйте использовать reshape, который, в отличие от view, может работать с не контингентными тензорами.

  4. Проверка на пустые аннотации: Ваш код использует проверку на количество аннотаций в annot_b, но важно удостовериться, что аннотации действительно содержат ожидаемые данные.

    if len(annot_b) == 0:
        print("Skipping empty annotation batch")
        continue
  5. Контроль обработки данных в DataLoader: Убедитесь, что ваш collate_fn корректно обрабатывает пакеты данных. В некоторых случаях может потребоваться изменить способ их объединения в зависимости от того, как формируются ваши изображения и аннотации.

  6. Логирование и исключения: Добавьте более детальное логирование, использовав try-except вокруг частей кода, где возникает ошибка, чтобы лучше понять, какие данные передаются и где именно происходит сбой.

Заключение

Решение проблемы несовместимости размеров тензоров во время тренировки вашей модели может потребовать внимания к деталям в обработке данных. Используйте упомянутые выше подходы для отладки и устранения причин ошибок. Кроме того, не забывайте следить за совместимостью используемой вами версии библиотек, таких как PyTorch и PyTorch Lightning, так как несовместимости между версиями также могут влиять на стабильность и производительность ваших экспериментов.

Оцените материал
Добавить комментарий

Капча загружается...