{
  "source_file": "0930",
  "source_platform": "研究机构",
  "author": "PyTorch Tutorials",
  "title_listed": "TorchVision Object Detection Finetuning Tutorial",
  "keywords": "目标检测,Mask R-CNN,微调",
  "domain": "图像处理",
  "content_type": "教程",
  "is_paid_flag": "否",
  "url": "https://pytorch.org/tutorials/intermediate/torchvision_tutorial.html",
  "publish_date": "持续更新",
  "corpus_stage": "图像处理",
  "notes": "目标检测微调",
  "id": "af06ea56361a",
  "collected_at": "2026-10-02T16:30:19",
  "title": "TorchVision Object Detection Finetuning Tutorial — PyTorch Tutorials 2.14.0+cu130 documentation",
  "body_markdown": "Note\nGo to the end\nto download the full example code.\nTorchVision Object Detection Finetuning Tutorial\n#\nCreated On: Dec 14, 2023 | Last Updated: Sep 05, 2025 | Last Verified: Nov 05, 2024\nFor this tutorial, we will be finetuning a pre-trained\nMask\nR-CNN\nmodel on the\nPenn-Fudan\nDatabase for Pedestrian Detection and\nSegmentation\n. It contains\n170 images with 345 instances of pedestrians, and we will use it to\nillustrate how to use the new features in torchvision in order to train\nan object detection and instance segmentation model on a custom dataset.\nNote\nThis tutorial works only with torchvision version >=0.16 or nightly.\nIf you’re using torchvision<=0.15, please follow\nthis tutorial instead\n.\nDefining the Dataset\n#\nThe reference scripts for training object detection, instance\nsegmentation and person keypoint detection allows for easily supporting\nadding new custom datasets. The dataset should inherit from the standard\ntorch.utils.data.Dataset\nclass, and implement\n__len__\nand\n__getitem__\n.\nThe only specificity that we require is that the dataset\n__getitem__\nshould return a tuple:\nimage:\ntorchvision.tv_tensors.Image\nof shape\n[3,\nH,\nW]\n, a pure tensor, or a PIL Image of size\n(H,\nW)\ntarget: a dict containing the following fields\nboxes\n,\ntorchvision.tv_tensors.BoundingBoxes\nof shape\n[N,\n4]\n:\nthe coordinates of the\nN\nbounding boxes in\n[x0,\ny0,\nx1,\ny1]\nformat, ranging from\n0\nto\nW\nand\n0\nto\nH\nlabels\n, integer\ntorch.Tensor\nof shape\n[N]\n: the label for each bounding box.\n0\nrepresents always the background class.\nimage_id\n, int: an image identifier. It should be\nunique between all the images in the dataset, and is used during\nevaluation\narea\n, float\ntorch.Tensor\nof shape\n[N]\n: the area of the bounding box. This is used\nduring evaluation with the COCO metric, to separate the metric\nscores between small, medium and large boxes.\niscrowd\n, uint8\ntorch.Tensor\nof shape\n[N]\n: instances with\niscrowd=True\nwill be\nignored during evaluation.\n(optionally)\nmasks\n,\ntorchvision.tv_tensors.Mask\nof shape\n[N,\nH,\nW]\n: the segmentation\nmasks for each one of the objects\nIf your dataset is compliant with above requirements then it will work for both\ntraining and evaluation codes from the reference script. Evaluation code will use scripts from\npycocotools\nwhich can be installed with\npip\ninstall\npycocotools\n.\nNote\nFor Windows, please install\npycocotools\nfrom\ngautamchitnis\nwith command\npip\ninstall\ngit+https://github.com/gautamchitnis/cocoapi.git@cocodataset-master#subdirectory=PythonAPI\nOne note on the\nlabels\n. The model considers class\n0\nas background. If your dataset does not contain the background class,\nyou should not have\n0\nin your\nlabels\n. For example, assuming you have just two classes,\ncat\nand\ndog\n, you can\ndefine\n1\n(not\n0\n) to represent\ncats\nand\n2\nto represent\ndogs\n. So, for instance, if one of the images has both\nclasses, your\nlabels\ntensor should look like\n[1,\n2]\n.\nAdditionally, if you want to use aspect ratio grouping during training\n(so that each batch only contains images with similar aspect ratios),\nthen it is recommended to also implement a\nget_height_and_width\nmethod, which returns the height and the width of the image. If this\nmethod is not provided, we query all elements of the dataset via\n__getitem__\n, which loads the image in memory and is slower than if\na custom method is provided.\nWriting a custom dataset for PennFudan\n#\nLet’s write a dataset for the PennFudan dataset. First, let’s download the dataset and\nextract the\nzip file\n:\nwget\nhttps\n:\n//\nwww\n.\ncis\n.\nupenn\n.\nedu\n/~\njshi\n/\nped_html\n/\nPennFudanPed\n.\nzip\n-\nP\ndata\ncd\ndata\n&&\nunzip\nPennFudanPed\n.\nzip\nWe have the following folder structure:\nPennFudanPed\n/\nPedMasks\n/\nFudanPed00001_mask\n.\npng\nFudanPed00002_mask\n.\npng\nFudanPed00003_mask\n.\npng\nFudanPed00004_mask\n.\npng\n...\nPNGImages\n/\nFudanPed00001\n.\npng\nFudanPed00002\n.\npng\nFudanPed00003\n.\npng\nFudanPed00004\n.\npng\nHere is one example of a pair of images and segmentation masks\nimport\nmatplotlib.pyplot\nas\nplt\nfrom\ntorchvision.io\nimport\nread_image\nimage\n=\nread_image\n(\n\"data/PennFudanPed/PNGImages/FudanPed00046.png\"\n)\nmask\n=\nread_image\n(\n\"data/PennFudanPed/PedMasks/FudanPed00046_mask.png\"\n)\nplt\n.\nfigure\n(\nfigsize\n=\n(\n16\n,\n8\n))\nplt\n.\nsubplot\n(\n121\n)\nplt\n.\ntitle\n(\n\"Image\"\n)\nplt\n.\nimshow\n(\nimage\n.\npermute\n(\n1\n,\n2\n,\n0\n))\nplt\n.\nsubplot\n(\n122\n)\nplt\n.\ntitle\n(\n\"Mask\"\n)\nplt\n.\nimshow\n(\nmask\n.\npermute\n(\n1\n,\n2\n,\n0\n))\n<matplotlib.image.AxesImage object at 0x7f664aa93ee0>\nSo each image has a corresponding\nsegmentation mask, where each color correspond to a different instance.\nLet’s write a\ntorch.utils.data.Dataset\nclass for this dataset.\nIn the code below, we are wrapping images, bounding boxes and masks into\ntorchvision.tv_tensors.TVTensor\nclasses so that we will be able to apply torchvision\nbuilt-in transformations (\nnew Transforms API\n)\nfor the given object detection and segmentation task.\nNamely, image tensors will be wrapped by\ntorchvision.tv_tensors.Image\n, bounding boxes into\ntorchvision.tv_tensors.BoundingBoxes\nand masks into\ntorchvision.tv_tensors.Mask\n.\nAs\ntorchvision.tv_tensors.TVTensor\nare\ntorch.Tensor\nsubclasses, wrapped objects are also tensors and inherit the plain\ntorch.Tensor\nAPI. For more information about torchvision\ntv_tensors\nsee\nthis documentation\n.\nimport\nos\nimport\ntorch\nfrom\ntorchvision.io\nimport\nread_image\nfrom\ntorchvision.ops.boxes\nimport\nmasks_to_boxes\nfrom\ntorchvision\nimport\ntv_tensors\nfrom\ntorchvision.transforms.v2\nimport\nfunctional\nas\nF\nclass\nPennFudanDataset\n(\ntorch\n.\nutils\n.\ndata\n.\nDataset\n):\ndef\n__init__\n(\nself\n,\nroot\n,\ntransforms\n):\nself\n.\nroot\n=\nroot\nself\n.\ntransforms\n=\ntransforms\n# load all image files, sorting them to\n# ensure that they are aligned\nself\n.\nimgs\n=\nlist\n(\nsorted\n(\nos\n.\nlistdir\n(\nos\n.\npath\n.\njoin\n(\nroot\n,\n\"PNGImages\"\n))))\nself\n.\nmasks\n=\nlist\n(\nsorted\n(\nos\n.\nlistdir\n(\nos\n.\npath\n.\njoin\n(\nroot\n,\n\"PedMasks\"\n))))\ndef\n__getitem__\n(\nself\n,\nidx\n):\n# load images and masks\nimg_path\n=\nos\n.\npath\n.\njoin\n(\nself\n.\nroot\n,\n\"PNGImages\"\n,\nself\n.\nimgs\n[\nidx\n])\nmask_path\n=\nos\n.\npath\n.\njoin\n(\nself\n.\nroot\n,\n\"PedMasks\"\n,\nself\n.\nmasks\n[\nidx\n])\nimg\n=\nread_image\n(\nimg_path\n)\nmask\n=\nread_image\n(\nmask_path\n)\n# instances are encoded as different colors\nobj_ids\n=\ntorch\n.\nunique\n(\nmask\n)\n# first id is the background, so remove it\nobj_ids\n=\nobj_ids\n[\n1\n:]\nnum_objs\n=\nlen\n(\nobj_ids\n)\n# split the color-encoded mask into a set\n# of binary masks\nmasks\n=\n(\nmask\n==\nobj_ids\n[:,\nNone\n,\nNone\n])\n.\nto\n(\ndtype\n=\ntorch\n.\nuint8\n)\n# get bounding box coordinates for each mask\nboxes\n=\nmasks_to_boxes\n(\nmasks\n)\n# there is only one class\nlabels\n=\ntorch\n.\nones\n((\nnum_objs\n,),\ndtype\n=\ntorch\n.\nint64\n)\nimage_id\n=\nidx\narea\n=\n(\nboxes\n[:,\n3\n]\n-\nboxes\n[:,\n1\n])\n*\n(\nboxes\n[:,\n2\n]\n-\nboxes\n[:,\n0\n])\n# suppose all instances are not crowd\niscrowd\n=\ntorch\n.\nzeros\n((\nnum_objs\n,),\ndtype\n=\ntorch\n.\nint64\n)\n# Wrap sample and targets into torchvision tv_tensors:\nimg\n=\ntv_tensors\n.\nImage\n(\nimg\n)\ntarget\n=\n{}\ntarget\n[\n\"boxes\"\n]\n=\ntv_tensors\n.\nBoundingBoxes\n(\nboxes\n,\nformat\n=\n\"XYXY\"\n,\ncanvas_size\n=\nF\n.\nget_size\n(\nimg\n))\ntarget\n[\n\"masks\"\n]\n=\ntv_tensors\n.\nMask\n(\nmasks\n)\ntarget\n[\n\"labels\"\n]\n=\nlabels\ntarget\n[\n\"image_id\"\n]\n=\nimage_id\ntarget\n[\n\"area\"\n]\n=\narea\ntarget\n[\n\"iscrowd\"\n]\n=\niscrowd\nif\nself\n.\ntransforms\nis\nnot\nNone\n:\nimg\n,\ntarget\n=\nself\n.\ntransforms\n(\nimg\n,\ntarget\n)\nreturn\nimg\n,\ntarget\ndef\n__len__\n(\nself\n):\nreturn\nlen\n(\nself\n.\nimgs\n)\nThat’s all for the dataset. Now let’s define a model that can perform\npredictions on this dataset.\nDefining your model\n#\nIn this tutorial, we will be using\nMask\nR-CNN\n, which is based on top of\nFaster R-CNN\n. Faster R-CNN is a\nmodel that predicts both bounding boxes and class scores for potential\nobjects in the image.\nMask R-CNN adds an extra branch\ninto Faster R-CNN, which also predicts segmentation masks for each\ninstance.\nThere are two common\nsituations where one might want\nto modify one of the available models in TorchVision Model Zoo. The first\nis when we want to start from a pre-trained model, and just finetune the\nlast layer. The other is when we want to replace the backbone of the\nmodel with a different one (for faster predictions, for example).\nLet’s go see how we would do one or another in the following sections.\n1 - Finetuning from a pretrained model\n#\nLet’s suppose that you want to start from a model pre-trained on COCO\nand want to finetune it for your particular classes. Here is a possible\nway of doing it:\nimport\ntorchvision\nfrom\ntorchvision.models.detection.faster_rcnn\nimport\nFastRCNNPredictor\n# load a model pre-trained on COCO\nmodel\n=\ntorchvision\n.\nmodels\n.\ndetection\n.\nfasterrcnn_resnet50_fpn\n(\nweights\n=\n\"DEFAULT\"\n)\n# replace the classifier with a new one, that has\n# num_classes which is user-defined\nnum_classes\n=\n2\n# 1 class (person) + background\n# get number of input features for the classifier\nin_features\n=\nmodel\n.\nroi_heads\n.\nbox_predictor\n.\ncls_score\n.\nin_features\n# replace the pre-trained head with a new one\nmodel\n.\nroi_heads\n.\nbox_predictor\n=\nFastRCNNPredictor\n(\nin_features\n,\nnum_classes\n)\nDownloading: \"https://download.pytorch.org/models/fasterrcnn_resnet50_fpn_coco-258fb6c6.pth\" to /var/lib/ci-user/.cache/torch/hub/checkpoints/fasterrcnn_resnet50_fpn_coco-258fb6c6.pth\n\n  0%|          | 0.00/160M [00:00<?, ?B/s]\n 21%|██        | 33.6M/160M [00:00<00:00, 353MB/s]\n 47%|████▋     | 75.2M/160M [00:00<00:00, 401MB/s]\n 73%|███████▎  | 117M/160M [00:00<00:00, 419MB/s]\n 98%|█████████▊| 157M/160M [00:00<00:00, 382MB/s]\n100%|██████████| 160M/160M [00:00<00:00, 383MB/s]\n2 - Modifying the model to add a different backbone\n#\nimport\ntorchvision\nfrom\ntorchvision.models.detection\nimport\nFasterRCNN\nfrom\ntorchvision.models.detection.rpn\nimport\nAnchorGenerator\n# load a pre-trained model for classification and return\n# only the features\nbackbone\n=\ntorchvision\n.\nmodels\n.\nmobilenet_v2\n(\nweights\n=\n\"DEFAULT\"\n)\n.\nfeatures\n# ``FasterRCNN`` needs to know the number of\n# output channels in a backbone. For mobilenet_v2, it's 1280\n# so we need to add it here\nbackbone\n.\nout_channels\n=\n1280\n# let's make the RPN generate 5 x 3 anchors per spatial\n# location, with 5 different sizes and 3 different aspect\n# ratios. We have a Tuple[Tuple[int]] because each feature\n# map could potentially have different sizes and\n# aspect ratios\nanchor_generator\n=\nAnchorGenerator\n(\nsizes\n=\n((\n32\n,\n64\n,\n128\n,\n256\n,\n512\n),),\naspect_ratios\n=\n((\n0.5\n,\n1.0\n,\n2.0\n),)\n)\n# let's define what are the feature maps that we will\n# use to perform the region of interest cropping, as well as\n# the size of the crop after rescaling.\n# if your backbone returns a Tensor, featmap_names is expected to\n# be [0]. More generally, the backbone should return an\n# ``OrderedDict[Tensor]``, and in ``featmap_names`` you can choose which\n# feature maps to use.\nroi_pooler\n=\ntorchvision\n.\nops\n.\nMultiScaleRoIAlign\n(\nfeatmap_names\n=\n[\n'0'\n],\noutput_size\n=\n7\n,\nsampling_ratio\n=\n2\n)\n# put the pieces together inside a Faster-RCNN model\nmodel\n=\nFasterRCNN\n(\nbackbone\n,\nnum_classes\n=\n2\n,\nrpn_anchor_generator\n=\nanchor_generator\n,\nbox_roi_pool\n=\nroi_pooler\n)\nDownloading: \"https://download.pytorch.org/models/mobilenet_v2-7ebf99e0.pth\" to /var/lib/ci-user/.cache/torch/hub/checkpoints/mobilenet_v2-7ebf99e0.pth\n\n  0%|          | 0.00/13.6M [00:00<?, ?B/s]\n100%|██████████| 13.6M/13.6M [00:00<00:00, 341MB/s]\nObject detection and instance segmentation model for PennFudan Dataset\n#\nIn our case, we want to finetune from a pre-trained model, given that\nour dataset is very small, so we will be following approach number 1.\nHere we want to also compute the instance segmentation masks, so we will\nbe using Mask R-CNN:\nimport\ntorchvision\nfrom\ntorchvision.models.detection.faster_rcnn\nimport\nFastRCNNPredictor\nfrom\ntorchvision.models.detection.mask_rcnn\nimport\nMaskRCNNPredictor\ndef\nget_model_instance_segmentation\n(\nnum_classes\n):\n# load an instance segmentation model pre-trained on COCO\nmodel\n=\ntorchvision\n.\nmodels\n.\ndetection\n.\nmaskrcnn_resnet50_fpn\n(\nweights\n=\n\"DEFAULT\"\n)\n# get number of input features for the classifier\nin_features\n=\nmodel\n.\nroi_heads\n.\nbox_predictor\n.\ncls_score\n.\nin_features\n# replace the pre-trained head with a new one\nmodel\n.\nroi_heads\n.\nbox_predictor\n=\nFastRCNNPredictor\n(\nin_features\n,\nnum_classes\n)\n# now get the number of input features for the mask classifier\nin_features_mask\n=\nmodel\n.\nroi_heads\n.\nmask_predictor\n.\nconv5_mask\n.\nin_channels\nhidden_layer\n=\n256\n# and replace the mask predictor with a new one\nmodel\n.\nroi_heads\n.\nmask_predictor\n=\nMaskRCNNPredictor\n(\nin_features_mask\n,\nhidden_layer\n,\nnum_classes\n)\nreturn\nmodel\nThat’s it, this will make\nmodel\nbe ready to be trained and evaluated\non your custom dataset.\nPutting everything together\n#\nIn\nreferences/detection/\n, we have a number of helper functions to\nsimplify training and evaluating detection models. Here, we will use\nreferences/detection/engine.py\nand\nreferences/detection/utils.py\n.\nJust download everything under\nreferences/detection\nto your folder and use them here.\nOn Linux if you have\nwget\n, you can download them using below commands:\nos\n.\nsystem\n(\n\"wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/engine.py\"\n)\nos\n.\nsystem\n(\n\"wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/utils.py\"\n)\nos\n.\nsystem\n(\n\"wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/coco_utils.py\"\n)\nos\n.\nsystem\n(\n\"wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/coco_eval.py\"\n)\nos\n.\nsystem\n(\n\"wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/transforms.py\"\n)\n0\nSince v0.15.0 torchvision provides\nnew Transforms API\nto easily write data augmentation pipelines for Object Detection and Segmentation tasks.\nLet’s write some helper functions for data augmentation /\ntransformation:\nfrom\ntorchvision.transforms\nimport\nv2\nas\nT\ndef\nget_transform\n(\ntrain\n):\ntransforms\n=\n[]\nif\ntrain\n:\ntransforms\n.\nappend\n(\nT\n.\nRandomHorizontalFlip\n(\n0.5\n))\ntransforms\n.\nappend\n(\nT\n.\nToDtype\n(\ntorch\n.\nfloat\n,\nscale\n=\nTrue\n))\ntransforms\n.\nappend\n(\nT\n.\nToPureTensor\n())\nreturn\nT\n.\nCompose\n(\ntransforms\n)\nTesting\nforward()\nmethod (Optional)\n#\nBefore iterating over the dataset, it’s good to see what the model\nexpects during training and inference time on sample data.\nimport\nutils\nmodel\n=\ntorchvision\n.\nmodels\n.\ndetection\n.\nfasterrcnn_resnet50_fpn\n(\nweights\n=\n\"DEFAULT\"\n)\ndataset\n=\nPennFudanDataset\n(\n'data/PennFudanPed'\n,\nget_transform\n(\ntrain\n=\nTrue\n))\ndata_loader\n=\ntorch\n.\nutils\n.\ndata\n.\nDataLoader\n(\ndataset\n,\nbatch_size\n=\n2\n,\nshuffle\n=\nTrue\n,\ncollate_fn\n=\nutils\n.\ncollate_fn\n)\n# For Training\nimages\n,\ntargets\n=\nnext\n(\niter\n(\ndata_loader\n))\nimages\n=\nlist\n(\nimage\nfor\nimage\nin\nimages\n)\ntargets\n=\n[{\nk\n:\nv\nfor\nk\n,\nv\nin\nt\n.\nitems\n()}\nfor\nt\nin\ntargets\n]\noutput\n=\nmodel\n(\nimages\n,\ntargets\n)\n# Returns losses and detections\nprint\n(\noutput\n)\n# For inference\nmodel\n.\neval\n()\nx\n=\n[\ntorch\n.\nrand\n(\n3\n,\n300\n,\n400\n),\ntorch\n.\nrand\n(\n3\n,\n500\n,\n400\n)]\npredictions\n=\nmodel\n(\nx\n)\n# Returns predictions\nprint\n(\npredictions\n[\n0\n])\n{'loss_classifier': tensor(0.2094, grad_fn=<NllLossBackward0>), 'loss_box_reg': tensor(0.0927, grad_fn=<DivBackward0>), 'loss_objectness': tensor(0.0407, grad_fn=<BinaryCrossEntropyWithLogitsBackward0>), 'loss_rpn_box_reg': tensor(0.0073, grad_fn=<DivBackward0>)}\n{'boxes': tensor([], size=(0, 4), grad_fn=<StackBackward0>), 'labels': tensor([], dtype=torch.int64), 'scores': tensor([], grad_fn=<IndexBackward0>)}\nWe want to be able to train our model on an\naccelerator\nsuch as CUDA, MPS, MTIA, or XPU. Let’s now write the main function which performs the training and the validation:\nfrom\nengine\nimport\ntrain_one_epoch\n,\nevaluate\n# train on the accelerator or on the CPU, if an accelerator is not available\ndevice\n=\ntorch\n.\naccelerator\n.\ncurrent_accelerator\n()\nif\ntorch\n.\naccelerator\n.\nis_available\n()\nelse\ntorch\n.\ndevice\n(\n'cpu'\n)\n# our dataset has two classes only - background and person\nnum_classes\n=\n2\n# use our dataset and defined transformations\ndataset\n=\nPennFudanDataset\n(\n'data/PennFudanPed'\n,\nget_transform\n(\ntrain\n=\nTrue\n))\ndataset_test\n=\nPennFudanDataset\n(\n'data/PennFudanPed'\n,\nget_transform\n(\ntrain\n=\nFalse\n))\n# split the dataset in train and test set\nindices\n=\ntorch\n.\nrandperm\n(\nlen\n(\ndataset\n))\n.\ntolist\n()\ndataset\n=\ntorch\n.\nutils\n.\ndata\n.\nSubset\n(\ndataset\n,\nindices\n[:\n-\n50\n])\ndataset_test\n=\ntorch\n.\nutils\n.\ndata\n.\nSubset\n(\ndataset_test\n,\nindices\n[\n-\n50\n:])\n# define training and validation data loaders\ndata_loader\n=\ntorch\n.\nutils\n.\ndata\n.\nDataLoader\n(\ndataset\n,\nbatch_size\n=\n2\n,\nshuffle\n=\nTrue\n,\ncollate_fn\n=\nutils\n.\ncollate_fn\n)\ndata_loader_test\n=\ntorch\n.\nutils\n.\ndata\n.\nDataLoader\n(\ndataset_test\n,\nbatch_size\n=\n1\n,\nshuffle\n=\nFalse\n,\ncollate_fn\n=\nutils\n.\ncollate_fn\n)\n# get the model using our helper function\nmodel\n=\nget_model_instance_segmentation\n(\nnum_classes\n)\n# move model to the right device\nmodel\n.\nto\n(\ndevice\n)\n# construct an optimizer\nparams\n=\n[\np\nfor\np\nin\nmodel\n.\nparameters\n()\nif\np\n.\nrequires_grad\n]\noptimizer\n=\ntorch\n.\noptim\n.\nSGD\n(\nparams\n,\nlr\n=\n0.005\n,\nmomentum\n=\n0.9\n,\nweight_decay\n=\n0.0005\n)\n# and a learning rate scheduler\nlr_scheduler\n=\ntorch\n.\noptim\n.\nlr_scheduler\n.\nStepLR\n(\noptimizer\n,\nstep_size\n=\n3\n,\ngamma\n=\n0.1\n)\n# let's train it just for 2 epochs\nnum_epochs\n=\n2\nfor\nepoch\nin\nrange\n(\nnum_epochs\n):\n# train for one epoch, printing every 10 iterations\ntrain_one_epoch\n(\nmodel\n,\noptimizer\n,\ndata_loader\n,\ndevice\n,\nepoch\n,\nprint_freq\n=\n10\n)\n# update the learning rate\nlr_scheduler\n.\nstep\n()\n# evaluate on the test dataset\nevaluate\n(\nmodel\n,\ndata_loader_test\n,\ndevice\n=\ndevice\n)\nprint\n(\n\"That's it!\"\n)\nDownloading: \"https://download.pytorch.org/models/maskrcnn_resnet50_fpn_coco-bf2d0c1e.pth\" to /var/lib/ci-user/.cache/torch/hub/checkpoints/maskrcnn_resnet50_fpn_coco-bf2d0c1e.pth\n\n  0%|          | 0.00/170M [00:00<?, ?B/s]\n 21%|██        | 35.2M/170M [00:00<00:00, 368MB/s]\n 43%|████▎     | 72.2M/170M [00:00<00:00, 380MB/s]\n 64%|██████▍   | 109M/170M [00:00<00:00, 382MB/s]\n 87%|████████▋ | 148M/170M [00:00<00:00, 390MB/s]\n100%|██████████| 170M/170M [00:00<00:00, 390MB/s]\n/var/lib/workspace/intermediate_source/engine.py:30: FutureWarning: `torch.cuda.amp.autocast(args...)` is deprecated. Please use `torch.amp.autocast('cuda', args...)` instead.\n  with torch.cuda.amp.autocast(enabled=scaler is not None):\nEpoch: [0]  [ 0/60]  eta: 0:00:46  lr: 0.000090  loss: 4.0005 (4.0005)  loss_classifier: 0.8221 (0.8221)  loss_box_reg: 0.3171 (0.3171)  loss_mask: 2.8385 (2.8385)  loss_objectness: 0.0170 (0.0170)  loss_rpn_box_reg: 0.0058 (0.0058)  time: 0.7714  data: 0.0163  max mem: 2208\nEpoch: [0]  [10/60]  eta: 0:00:12  lr: 0.000936  loss: 1.6376 (2.0917)  loss_classifier: 0.4847 (0.4744)  loss_box_reg: 0.3171 (0.3194)  loss_mask: 0.7427 (1.2690)  loss_objectness: 0.0199 (0.0229)  loss_rpn_box_reg: 0.0053 (0.0060)  time: 0.2598  data: 0.0162  max mem: 2904\nEpoch: [0]  [20/60]  eta: 0:00:09  lr: 0.001783  loss: 0.9652 (1.4459)  loss_classifier: 0.2373 (0.3447)  loss_box_reg: 0.2265 (0.2889)  loss_mask: 0.3423 (0.7873)  loss_objectness: 0.0188 (0.0194)  loss_rpn_box_reg: 0.0045 (0.0055)  time: 0.2082  data: 0.0170  max mem: 2904\nEpoch: [0]  [30/60]  eta: 0:00:06  lr: 0.002629  loss: 0.6051 (1.1502)  loss_classifier: 0.1462 (0.2636)  loss_box_reg: 0.1987 (0.2620)  loss_mask: 0.2172 (0.6032)  loss_objectness: 0.0116 (0.0157)  loss_rpn_box_reg: 0.0045 (0.0057)  time: 0.2027  data: 0.0162  max mem: 2904\nEpoch: [0]  [40/60]  eta: 0:00:04  lr: 0.003476  loss: 0.4705 (0.9836)  loss_classifier: 0.0638 (0.2145)  loss_box_reg: 0.1968 (0.2540)  loss_mask: 0.1722 (0.4963)  loss_objectness: 0.0032 (0.0126)  loss_rpn_box_reg: 0.0071 (0.0061)  time: 0.2056  data: 0.0155  max mem: 2904\nEpoch: [0]  [50/60]  eta: 0:00:02  lr: 0.004323  loss: 0.4107 (0.8675)  loss_classifier: 0.0439 (0.1806)  loss_box_reg: 0.1483 (0.2307)  loss_mask: 0.1617 (0.4377)  loss_objectness: 0.0025 (0.0115)  loss_rpn_box_reg: 0.0073 (0.0069)  time: 0.2147  data: 0.0156  max mem: 2904\nEpoch: [0]  [59/60]  eta: 0:00:00  lr: 0.005000  loss: 0.3907 (0.7930)  loss_classifier: 0.0421 (0.1603)  loss_box_reg: 0.1287 (0.2143)  loss_mask: 0.1835 (0.4009)  loss_objectness: 0.0038 (0.0104)  loss_rpn_box_reg: 0.0084 (0.0070)  time: 0.2120  data: 0.0153  max mem: 2904\nEpoch: [0] Total time: 0:00:13 (0.2178 s / it)\ncreating index...\nindex created!\nTest:  [ 0/50]  eta: 0:00:04  model_time: 0.0717 (0.0717)  evaluator_time: 0.0057 (0.0057)  time: 0.0882  data: 0.0102  max mem: 2904\nTest:  [49/50]  eta: 0:00:00  model_time: 0.0414 (0.0440)  evaluator_time: 0.0036 (0.0062)  time: 0.0595  data: 0.0102  max mem: 2904\nTest: Total time: 0:00:03 (0.0610 s / it)\nAveraged stats: model_time: 0.0414 (0.0440)  evaluator_time: 0.0036 (0.0062)\nAccumulating evaluation results...\nDONE (t=0.01s).\nAccumulating evaluation results...\nDONE (t=0.01s).\nIoU metric: bbox\n Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.684\n Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.987\n Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.856\n Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.545\n Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.689\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.299\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.745\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.745\n Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.733\n Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.745\nIoU metric: segm\n Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.658\n Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.987\n Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.786\n Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.483\n Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.663\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.298\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.708\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.711\n Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.700\n Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.711\nEpoch: [1]  [ 0/60]  eta: 0:00:14  lr: 0.005000  loss: 0.5008 (0.5008)  loss_classifier: 0.0762 (0.0762)  loss_box_reg: 0.1832 (0.1832)  loss_mask: 0.2200 (0.2200)  loss_objectness: 0.0017 (0.0017)  loss_rpn_box_reg: 0.0196 (0.0196)  time: 0.2471  data: 0.0219  max mem: 2904\nEpoch: [1]  [10/60]  eta: 0:00:10  lr: 0.005000  loss: 0.3154 (0.3361)  loss_classifier: 0.0353 (0.0437)  loss_box_reg: 0.0923 (0.1130)  loss_mask: 0.1495 (0.1681)  loss_objectness: 0.0021 (0.0028)  loss_rpn_box_reg: 0.0060 (0.0084)  time: 0.2142  data: 0.0166  max mem: 2906\nEpoch: [1]  [20/60]  eta: 0:00:08  lr: 0.005000  loss: 0.2727 (0.3073)  loss_classifier: 0.0349 (0.0411)  loss_box_reg: 0.0806 (0.0961)  loss_mask: 0.1495 (0.1612)  loss_objectness: 0.0016 (0.0024)  loss_rpn_box_reg: 0.0046 (0.0064)  time: 0.2068  data: 0.0162  max mem: 2906\nEpoch: [1]  [30/60]  eta: 0:00:06  lr: 0.005000  loss: 0.2680 (0.2990)  loss_classifier: 0.0373 (0.0406)  loss_box_reg: 0.0806 (0.0964)  loss_mask: 0.1417 (0.1532)  loss_objectness: 0.0012 (0.0025)  loss_rpn_box_reg: 0.0034 (0.0063)  time: 0.2040  data: 0.0164  max mem: 2906\nEpoch: [1]  [40/60]  eta: 0:00:04  lr: 0.005000  loss: 0.2652 (0.2857)  loss_classifier: 0.0316 (0.0382)  loss_box_reg: 0.0852 (0.0892)  loss_mask: 0.1319 (0.1506)  loss_objectness: 0.0005 (0.0022)  loss_rpn_box_reg: 0.0044 (0.0056)  time: 0.2018  data: 0.0153  max mem: 2906\nEpoch: [1]  [50/60]  eta: 0:00:02  lr: 0.005000  loss: 0.2249 (0.2831)  loss_classifier: 0.0316 (0.0404)  loss_box_reg: 0.0703 (0.0880)  loss_mask: 0.1375 (0.1468)  loss_objectness: 0.0005 (0.0021)  loss_rpn_box_reg: 0.0037 (0.0056)  time: 0.2006  data: 0.0144  max mem: 2906\nEpoch: [1]  [59/60]  eta: 0:00:00  lr: 0.005000  loss: 0.2134 (0.2733)  loss_classifier: 0.0321 (0.0385)  loss_box_reg: 0.0631 (0.0842)  loss_mask: 0.1195 (0.1431)  loss_objectness: 0.0007 (0.0021)  loss_rpn_box_reg: 0.0033 (0.0054)  time: 0.2059  data: 0.0150  max mem: 2906\nEpoch: [1] Total time: 0:00:12 (0.2058 s / it)\ncreating index...\nindex created!\nTest:  [ 0/50]  eta: 0:00:02  model_time: 0.0383 (0.0383)  evaluator_time: 0.0032 (0.0032)  time: 0.0519  data: 0.0101  max mem: 2906\nTest:  [49/50]  eta: 0:00:00  model_time: 0.0395 (0.0406)  evaluator_time: 0.0028 (0.0048)  time: 0.0559  data: 0.0102  max mem: 2906\nTest: Total time: 0:00:02 (0.0560 s / it)\nAveraged stats: model_time: 0.0395 (0.0406)  evaluator_time: 0.0028 (0.0048)\nAccumulating evaluation results...\nDONE (t=0.01s).\nAccumulating evaluation results...\nDONE (t=0.01s).\nIoU metric: bbox\n Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.794\n Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.990\n Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.927\n Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.726\n Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.800\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.359\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.847\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.847\n Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.767\n Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.851\nIoU metric: segm\n Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.731\n Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.990\n Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.908\n Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.527\n Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.736\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.336\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.776\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.776\n Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.733\n Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.778\nThat's it!\nSo after one epoch of training, we obtain a COCO-style mAP > 50, and\na mask mAP of 65.\nBut what do the predictions look like? Let’s take one image in the\ndataset and verify\nimport\nmatplotlib.pyplot\nas\nplt\nfrom\ntorchvision.utils\nimport\ndraw_bounding_boxes\n,\ndraw_segmentation_masks\nimage\n=\nread_image\n(\n\"data/PennFudanPed/PNGImages/FudanPed00046.png\"\n)\neval_transform\n=\nget_transform\n(\ntrain\n=\nFalse\n)\nmodel\n.\neval\n()\nwith\ntorch\n.\nno_grad\n():\nx\n=\neval_transform\n(\nimage\n)\n# convert RGBA -> RGB and move to device\nx\n=\nx\n[:\n3\n,\n...\n]\n.\nto\n(\ndevice\n)\npredictions\n=\nmodel\n([\nx\n,\n])\npred\n=\npredictions\n[\n0\n]\nimage\n=\n(\n255.0\n*\n(\nimage\n-\nimage\n.\nmin\n())\n/\n(\nimage\n.\nmax\n()\n-\nimage\n.\nmin\n()))\n.\nto\n(\ntorch\n.\nuint8\n)\nimage\n=\nimage\n[:\n3\n,\n...\n]\npred_labels\n=\n[\nf\n\"pedestrian:\n{\nscore\n:\n.3f\n}\n\"\nfor\nlabel\n,\nscore\nin\nzip\n(\npred\n[\n\"labels\"\n],\npred\n[\n\"scores\"\n])]\npred_boxes\n=\npred\n[\n\"boxes\"\n]\n.\nlong\n()\noutput_image\n=\ndraw_bounding_boxes\n(\nimage\n,\npred_boxes\n,\npred_labels\n,\ncolors\n=\n\"red\"\n)\nmasks\n=\n(\npred\n[\n\"masks\"\n]\n>\n0.7\n)\n.\nsqueeze\n(\n1\n)\noutput_image\n=\ndraw_segmentation_masks\n(\noutput_image\n,\nmasks\n,\nalpha\n=\n0.5\n,\ncolors\n=\n\"blue\"\n)\nplt\n.\nfigure\n(\nfigsize\n=\n(\n12\n,\n12\n))\nplt\n.\nimshow\n(\noutput_image\n.\npermute\n(\n1\n,\n2\n,\n0\n))\n<matplotlib.image.AxesImage object at 0x7f66882e5180>\nThe results look good!\nWrapping up\n#\nIn this tutorial, you have learned how to create your own training\npipeline for object detection models on a custom dataset. For\nthat, you wrote a\ntorch.utils.data.Dataset\nclass that returns the\nimages and the ground truth boxes and segmentation masks. You also\nleveraged a Mask R-CNN model pre-trained on COCO train2017 in order to\nperform transfer learning on this new dataset.\nFor a more complete example, which includes multi-machine / multi-GPU\ntraining, check\nreferences/detection/train.py\n, which is present in\nthe torchvision repository.\nTotal running time of the script:\n(0 minutes 45.641 seconds)\nDownload\nJupyter\nnotebook:\ntorchvision_tutorial.ipynb\nDownload\nPython\nsource\ncode:\ntorchvision_tutorial.py\nDownload\nzipped:\ntorchvision_tutorial.zip",
  "metadata": {
    "title": "TorchVision Object Detection Finetuning Tutorial — PyTorch Tutorials 2.14.0+cu130 documentation",
    "description": null,
    "keywords": null,
    "author": null,
    "og:image": "https://docs.pytorch.org/docs/stable/_static/img/pytorch_seo.png",
    "article:modified_time": "2022-07-20T23:02:43+00:00"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/af06ea56361a/code/body-000.txt",
      "chars": 105,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-001.txt",
      "chars": 243,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-002.txt",
      "chars": 380,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-003.txt",
      "chars": 54,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-004.txt",
      "chars": 2211,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-005.txt",
      "chars": 580,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-006.txt",
      "chars": 480,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-007.txt",
      "chars": 1466,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-008.txt",
      "chars": 249,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-009.txt",
      "chars": 978,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-010.txt",
      "chars": 525,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-011.txt",
      "chars": 2,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-012.txt",
      "chars": 291,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-013.txt",
      "chars": 684,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-014.txt",
      "chars": 414,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-015.txt",
      "chars": 1885,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-016.txt",
      "chars": 9641,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-017.txt",
      "chars": 946,
      "language": "text"
    },
    {
      "file": "attachments/af06ea56361a/code/body-018.txt",
      "chars": 54,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_images/sphx_glr_torchvision_tutorial_001.png",
      "bytes": 453270,
      "reused": false,
      "local_path": "attachments/af06ea56361a/images/body-efb5f7669b851102390f.png",
      "src": "https://docs.pytorch.org/tutorials/_images/sphx_glr_torchvision_tutorial_001.png",
      "alt": "Image, Mask",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_static/img/tv_tutorial/tv_image03.png",
      "bytes": 315102,
      "reused": false,
      "local_path": "attachments/af06ea56361a/images/body-571a5489014524e8e93e.png",
      "src": "https://docs.pytorch.org/tutorials/_static/img/tv_tutorial/tv_image03.png",
      "alt": "../_static/img/tv_tutorial/tv_image03.png",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_static/img/tv_tutorial/tv_image04.png",
      "bytes": 702781,
      "reused": false,
      "local_path": "attachments/af06ea56361a/images/body-21faf0934b0d7ebcb8f1.png",
      "src": "https://docs.pytorch.org/tutorials/_static/img/tv_tutorial/tv_image04.png",
      "alt": "../_static/img/tv_tutorial/tv_image04.png",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_images/sphx_glr_torchvision_tutorial_002.png",
      "bytes": 888160,
      "reused": false,
      "local_path": "attachments/af06ea56361a/images/body-8a2b518b70e7ed9891af.png",
      "src": "https://docs.pytorch.org/tutorials/_images/sphx_glr_torchvision_tutorial_002.png",
      "alt": "torchvision tutorial",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://arxiv.org/abs/1703.06870",
      "label": "Mask\nR-CNN",
      "type": "a"
    },
    {
      "href": "https://www.cis.upenn.edu/~jshi/ped_html/",
      "label": "Penn-Fudan\nDatabase for Pedestrian Detection and\nSegmentation",
      "type": "a"
    },
    {
      "href": "https://github.com/pytorch/tutorials/blob/d686b662932a380a58b7683425faa00c06bcf502/intermediate_source/torchvision_tutorial.rst",
      "label": "this tutorial instead",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/data.html",
      "label": "torch.utils.data.Dataset",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.tv_tensors.Image.html",
      "label": "torchvision.tv_tensors.Image",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.tv_tensors.BoundingBoxes.html",
      "label": "torchvision.tv_tensors.BoundingBoxes",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/tensors.html",
      "label": "torch.Tensor",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.tv_tensors.Mask.html",
      "label": "torchvision.tv_tensors.Mask",
      "type": "a"
    },
    {
      "href": "https://github.com/gautamchitnis/cocoapi",
      "label": "gautamchitnis",
      "type": "a"
    },
    {
      "href": "https://www.cis.upenn.edu/~jshi/ped_html/PennFudanPed.zip",
      "label": "zip file",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.io.read_image.html",
      "label": "read_image",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.tv_tensors.TVTensor.html",
      "label": "torchvision.tv_tensors.TVTensor",
      "type": "a"
    },
    {
      "href": "https://pytorch.org/vision/stable/transforms.html",
      "label": "new Transforms API",
      "type": "a"
    },
    {
      "href": "https://pytorch.org/vision/main/auto_examples/transforms/plot_transforms_getting_started.html",
      "label": "this documentation",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.ops.masks_to_boxes.html",
      "label": "masks_to_boxes",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.unique.html",
      "label": "torch . unique",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/tensor_attributes.html",
      "label": "torch . uint8",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.ones.html",
      "label": "torch . ones",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.zeros.html",
      "label": "torch . zeros",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1506.01497",
      "label": "Faster R-CNN",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html",
      "label": "FastRCNNPredictor",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/models/generated/torchvision.models.detection.fasterrcnn_resnet50_fpn.html",
      "label": "torchvision . models . detection . fasterrcnn_resnet50_fpn",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.Sequential.html",
      "label": "backbone",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/models/generated/torchvision.models.mobilenet_v2.html",
      "label": "torchvision . models . mobilenet_v2",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.ops.MultiScaleRoIAlign.html",
      "label": "roi_pooler",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/models/generated/torchvision.models.detection.maskrcnn_resnet50_fpn.html",
      "label": "torchvision . models . detection . maskrcnn_resnet50_fpn",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.v2.RandomHorizontalFlip.html",
      "label": "T . RandomHorizontalFlip",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.v2.ToDtype.html",
      "label": "T . ToDtype",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.v2.ToPureTensor.html",
      "label": "T . ToPureTensor",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.v2.Compose.html",
      "label": "T . Compose",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.rand.html",
      "label": "torch . rand",
      "type": "a"
    },
    {
      "href": "https://pytorch.org/docs/stable/torch.html",
      "label": "accelerator",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.accelerator.current_accelerator.html",
      "label": "torch . accelerator . current_accelerator",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.accelerator.is_available.html",
      "label": "torch . accelerator . is_available",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.randperm.html",
      "label": "torch . randperm",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.optim.SGD.html",
      "label": "optimizer",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.StepLR.html",
      "label": "lr_scheduler",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.utils.draw_bounding_boxes.html",
      "label": "draw_bounding_boxes",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.utils.draw_segmentation_masks.html",
      "label": "draw_segmentation_masks",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.no_grad.html",
      "label": "torch . no_grad",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/tutorials/_downloads/4a542c9f39bedbfe7de5061767181d36/torchvision_tutorial.ipynb",
      "label": "Download Jupyter notebook: torchvision_tutorial.ipynb",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/tutorials/_downloads/7590258df9f28b5ae0994c3b5b035edf/torchvision_tutorial.py",
      "label": "Download Python source code: torchvision_tutorial.py",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/tutorials/_downloads/aa82b146a324295d4af880b71bfd78cd/torchvision_tutorial.zip",
      "label": "Download zipped: torchvision_tutorial.zip",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:53:55Z",
  "source_url": "https://pytorch.org/tutorials/intermediate/torchvision_tutorial.html",
  "papers": [
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1703.06870",
      "bytes": 7723886,
      "reused": true,
      "local_path": "papers/repair/664bbc784da30edacdb6.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1506.01497",
      "bytes": 6913803,
      "reused": true,
      "local_path": "papers/repair/713fc776568d336b3d68.pdf"
    }
  ],
  "actual_video_files": [],
  "body_chars": 29173,
  "expected_body_images": 4,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/af06ea56361a/pages/source.html",
  "local_html": "attachments/af06ea56361a/pages/article.html",
  "body_base_path": "attachments/af06ea56361a/pages/",
  "body_markdown_path": "attachments/af06ea56361a/pages/article.md"
}