Ceci est le 8ème volet de PyTorch Tutoriel officiel après Dernière fois. Cette fois, nous allons procéder avec TorchVision Object Detection Finetuning Tutorial.
TorchVision Object Detection Finetuning Tutorial
Dans ce tutoriel, nous utiliserons le [Mask R-CNN] pré-entraîné (https://arxiv.org/abs/1703.06870) pour voir les réglages fins et le transfert d'apprentissage. Les données utilisées pour la formation sont les données de Penn-Fudan pour la détection et la segmentation des piétons. Pour ces données, 170 images avec 345 piétons (instances) sont préparées.
Tout d'abord, vous devez installer la bibliothèque pycocotools. Cette bibliothèque est utilisée pour calculer une note appelée "Intersection over Union". "Intersection over Union" est l'une des méthodes pour évaluer la condition de correspondance des zones dans la détection d'objets.
%%shell
pip install cython
#Installez pycocotools. La version par défaut de Colab est https://github.com/cocodataset/cocoapi/pull/Il y a un bug corrigé dans 354.
pip install -U 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'
Définissez le jeu de données. L'ensemble de données nécessite certains attributs pour tirer parti du modèle entraîné par Mask R-CNN. Données requises à l'aide du script torchvision (détection d'objets, segmentation d'instance, bibliothèque de détection de points clés de personne) Vous pouvez créer un ensemble.
L'ensemble de données nécessite les attributs suivants:
(Une description approximative de l'ensemble de données est que les boîtes définissent un quadrangle contenant des objets et que les masques définissent s'il s'agit ou non d'un objet en pixels.) Si le modèle renvoie la méthode ci-dessus, le modèle fonctionne à la fois pour la formation et l'évaluation, et le script d'évaluation pycocotools est utilisé.
Sortons l'ensemble de données de l'ensemble de données Penn-Fudan. Première, https://www.cis.upenn.edu/~jshi/ped_html/PennFudanPed.zip Téléchargez et décompressez le fichier zip.
%%shell
# download the Penn-Fudan dataset
wget https://www.cis.upenn.edu/~jshi/ped_html/PennFudanPed.zip .
# extract it in the current folder
unzip PennFudanPed.zip
Les données ont la structure suivante.
PennFudanPed/
PedMasks/
FudanPed00001_mask.png
FudanPed00002_mask.png
FudanPed00003_mask.png
FudanPed00004_mask.png
...
PNGImages/
FudanPed00001.png
FudanPed00002.png
FudanPed00003.png
FudanPed00004.png
Montrons la première image.
from PIL import Image
Image.open('PennFudanPed/PNGImages/FudanPed00001.png')
(Comme décrit dans le fichier readme.txt décompressé, l'image de masque est une image avec un arrière-plan de "0" et une étiquette de 1 ou plus pour chaque piéton.)
mask = Image.open('PennFudanPed/PedMasks/FudanPed00001_mask.png')
#Chaque occurrence de masque a une couleur différente de zéro à N.
#Où N est le nombre d'instances (piétons). Pour faciliter la visualisation
#Ajoutons une palette de couleurs au masque.
mask.putpalette([
0, 0, 0, # black background
255, 0, 0, # index 1 is red
255, 255, 0, # index 2 is yellow
255, 153, 0, # index 3 is orange
])
mask
Dans ces données, il y a un masque qui identifie chaque image et chaque piéton, et chaque couleur du masque correspond à chaque piéton. Créons la classe torch.utils.data.Dataset pour cet ensemble de données.
import os
import numpy as np
import torch
import torch.utils.data
from PIL import Image
class PennFudanDataset(torch.utils.data.Dataset):
def __init__(self, root, transforms=None):
self.root = root
self.transforms = transforms
#Charger et trier tous les fichiers image
self.imgs = list(sorted(os.listdir(os.path.join(root, "PNGImages"))))
self.masks = list(sorted(os.listdir(os.path.join(root, "PedMasks"))))
def __getitem__(self, idx):
#Charger des images et des masques
img_path = os.path.join(self.root, "PNGImages", self.imgs[idx])
mask_path = os.path.join(self.root, "PedMasks", self.masks[idx])
img = Image.open(img_path).convert("RGB")
#Parce que chaque couleur correspond à une instance différente et 0 est l'arrière-plan
#Notez que nous n'avons pas converti le masque en RVB
mask = Image.open(mask_path)
mask = np.array(mask)
#Les instances sont codées sous différentes couleurs
obj_ids = np.unique(mask)
#Le premier identifiant est l'arrière-plan, supprimez-le
obj_ids = obj_ids[1:]
# split the color-encoded mask into a set
# of binary masks
#Divisez le masque de couleur en un ensemble de masques binaires
masks = mask == obj_ids[:, None, None]
# get bounding box coordinates for each mask
#Obtenez les coordonnées de la boîte englobante pour chaque masque
num_objs = len(obj_ids)
boxes = []
for i in range(num_objs):
pos = np.where(masks[i])
xmin = np.min(pos[1])
xmax = np.max(pos[1])
ymin = np.min(pos[0])
ymax = np.max(pos[0])
boxes.append([xmin, ymin, xmax, ymax])
boxes = torch.as_tensor(boxes, dtype=torch.float32)
# there is only one class
#Il n'y a qu'une seule classe
labels = torch.ones((num_objs,), dtype=torch.int64)
masks = torch.as_tensor(masks, dtype=torch.uint8)
image_id = torch.tensor([idx])
area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])
# suppose all instances are not crowd
#Supposons que toutes les instances ne soient pas encombrées
iscrowd = torch.zeros((num_objs,), dtype=torch.int64)
target = {}
target["boxes"] = boxes
target["labels"] = labels
target["masks"] = masks
target["image_id"] = image_id
target["area"] = area
target["iscrowd"] = iscrowd
if self.transforms is not None:
img, target = self.transforms(img, target)
return img, target
def __len__(self):
return len(self.imgs)
C'est tout pour l'ensemble de données. Voyons comment la sortie de cet ensemble de données est organisée
dataset = PennFudanDataset('PennFudanPed/')
dataset[0]
out
(<PIL.Image.Image image mode=RGB size=559x536 at 0x7FC7AC4B62E8>,
{'area': tensor([35358., 36225.]), 'boxes': tensor([[159., 181., 301., 430.],
[419., 170., 534., 485.]]), 'image_id': tensor([0]), 'iscrowd': tensor([0, 0]), 'labels': tensor([1, 1]), 'masks': tensor([[[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
...,
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0]],
[[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
...,
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0]]], dtype=torch.uint8)})
Vous pouvez voir que l'ensemble de données renvoie PIL.Image et un dictionnaire contenant certains champs tels que boxes
, labels
, masks
.
Bien qu'il ne soit pas dans le didacticiel, le code suivant peut illustrer des boîtes et des masques. les cases sont des carrés contenant des instances (personnes) et les masques sont les instances elles-mêmes.
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
target = dataset[0][1]
#Masques de première instance
masks_0 = target['masks'][0,:,:]
#Boîtes de première instance
boxes_0 = target['boxes'][0]
#Masque de sortie
ax.imshow(masks_0)
#Boîtes de sortie
ax.add_patch(
patches.Rectangle(
(boxes_0[0], boxes_0[1]),boxes_0[2] - boxes_0[0], boxes_0[3] - boxes_0[1],
edgecolor = 'blue',
facecolor = 'red',
fill=True,
alpha=0.5
) )
plt.show()
Defining your model
Ce didacticiel utilise MaskR-CNN, basé sur FasterR-CNN. Faster R-CNN est un algorithme de détection d'objet qui prédit à la fois le cadre de sélection et le score de classe des objets potentiels dans une image (le carré contenant l'objet et ce qu'est l'objet). (L'image ci-dessous est une image traitée de Faster R-CNN)
Mask R-CNN est une version améliorée de Faster R-CNN qui évalue non seulement la détection d'objets par carré (boîte), mais aussi par unité de pixel (masque). (L'image ci-dessous est une image traitée du masque R-CNN)
Il y a deux raisons principales pour personnaliser un modèle avec Torchvision. La première consiste à tirer parti d'un modèle pré-entraîné et à modifier la dernière couche. L'autre est lorsque vous souhaitez remplacer le backbone de votre modèle par un autre backbone. (Par exemple, pour une prédiction plus rapide) Prenons un exemple concret.
Voici comment utiliser un modèle pré-entraîné pour ajuster la classe que vous souhaitez identifier.
import torchvision
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
#Charger des modèles pré-entraînés chez COCO
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
#Classificateur, nombre défini par l'utilisateur_Remplacer par un nouveau classificateur avec des classes
num_classes = 2 # 1 class (person) + background :1 cours (personne)+Contexte
#Obtient le nombre de fonctionnalités d'entrée du classificateur
in_features = model.roi_heads.box_predictor.cls_score.in_features
#Remplacez la tête pré-entraînée par une nouvelle
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
L'autre cas est celui où vous souhaitez remplacer le backbone du modèle par un autre backbone. Par exemple, la dorsale par défaut actuelle (ResNet-50) peut être trop grande dans certaines situations et vous souhaiterez peut-être tirer parti d'un modèle plus petit. Ce qui suit décrit comment utiliser la vision de la torche pour changer la dorsale.
import torchvision
from torchvision.models.detection import FasterRCNN
from torchvision.models.detection.rpn import AnchorGenerator
#Charge un modèle pré-entraîné pour la classification et renvoie uniquement les fonctionnalités
backbone = torchvision.models.mobilenet_v2(pretrained=True).features
#FasterRCNN a besoin de connaître le nombre de canaux de sortie dans le backbone.
# mobilenet_Pour la v2, c'est 1280, vous devez donc l'ajouter ici
backbone.out_channels = 1280
#En RPN, avec 5 tailles différentes et 3 formats d'image différents
#Générons 5 x 3 ancres pour chaque position spatiale.
#Parce que la taille et le rapport hauteur / largeur de chaque carte de caractéristiques peuvent être différents
# Tuple [Tuple [int]]il y a.
anchor_generator = AnchorGenerator(sizes=((32, 64, 128, 256, 512),),
aspect_ratios=((0.5, 1.0, 2.0),))
#Avec la carte des caractéristiques utilisée pour effectuer le découpage de la zone d'intérêt,
#Définissons la taille de la garniture après la remise à l'échelle.
#Si le backbone renvoie Tensor, featmap_les noms sont[0]Devrait être.
#Plus généralement, l'épine dorsale est OrderedDict[Tensor]Doit être retourné,
# featmap_Vous pouvez sélectionner la carte des caractéristiques à utiliser avec les noms.
roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[0],
output_size=7,
sampling_ratio=2)
#Assemblez les pièces dans un modèle RCNN plus rapide
model = FasterRCNN(backbone,
num_classes=2,
rpn_anchor_generator=anchor_generator,
box_roi_pool=roi_pooler)
Dans ce cas, le jeu de données est très petit, nous allons donc peaufiner le modèle pré-entraîné. Par conséquent, suivez l'approche numéro 1. Nous utiliserons ici le masque R-CNN pour calculer également le masque de segmentation de l'instance (pour déterminer la zone de la personne en pixels).
maskrcnn_resnet50_fpn
est décrit dans la documentation officielle (https://pytorch.org/docs/stable/torchvision/models.html#torchvision.models.detection.maskrcnn_resnet50_fpn) C'est un modèle personnalisé.
maskrcnn_resnet50_fpn est pré-entraîné avec l'ensemble de données à COCO train2017.import torchvision
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
from torchvision.models.detection.mask_rcnn import MaskRCNNPredictor
def get_instance_segmentation_model(num_classes):
#Charger un modèle de segmentation d'instance COCO pré-entraîné
model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True)
#Obtient le nombre de fonctionnalités d'entrée du classificateur
in_features = model.roi_heads.box_predictor.cls_score.in_features
#Remplacez la tête pré-entraînée par une nouvelle
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
#mask Obtient le nombre de fonctionnalités d'entrée du classificateur
in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels
hidden_layer = 256
# and replace the mask predictor with a new one
#Remplacez le prédicteur de masque par un nouveau
model.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask,
hidden_layer,
num_classes)
return model
Vous êtes maintenant prêt à entraîner et à évaluer votre modèle avec cet ensemble de données.
(En comparant ce modèle avec torchvision.models.detection.maskrcnn_resnet50_fpn, vous pouvez voir que les dimensions des pièces suivantes ont changé.)
(roi_heads): RoIHeads(
・ ・ ・
(box_predictor): FastRCNNPredictor(
(cls_score): Linear(in_features=1024, out_features=2, bias=True)
(bbox_pred): Linear(in_features=1024, out_features=8, bias=True)
)
・ ・ ・
(mask_predictor): MaskRCNNPredictor(
・ ・ ・
(mask_fcn_logits): Conv2d(256, 2, kernel_size=(1, 1), stride=(1, 1))
)
)
La vision de la torche «vision / références / détection /» a un certain nombre de fonctions d'assistance pour simplifier la formation et l'évaluation des modèles de détection d'objets. Ici, nous utilisons references / detection / engine.py
, references / detection / utils.py
, references / detection / transforms.py
.
Copiez ces fichiers (et leurs fichiers associés) pour utilisation.
%%shell
# Download TorchVision repo to use some files from
# references/detection
git clone https://github.com/pytorch/vision.git
cd vision
git checkout v0.3.0
cp references/detection/utils.py ../
cp references/detection/transforms.py ../
cp references/detection/coco_eval.py ../
cp references/detection/engine.py ../
cp references/detection/coco_utils.py ../
Utilisons les refereces / detection
copiées pour créer des fonctions d'aide pour développer / transformer les données.
from engine import train_one_epoch, evaluate
import utils
import transforms as T
def get_transform(train):
transforms = []
#Convertir l'image en Tensor
transforms.append(T.ToTensor())
if train:
#Pour la formation, l'image et les données de l'enseignant sont inversées horizontalement de manière aléatoire. (Image reflétée dans le miroir)
transforms.append(T.RandomHorizontalFlip(0.5))
return T.Compose(transforms)
Le code ci-dessus est la préparation des données. Convertit l'image en Tensor et l'inverse de manière aléatoire pour les données d'entraînement. Aucune normalisation des données ou redimensionnement de l'image n'est requise. Le modèle Mask R-CNN le fait en interne.
L'ensemble de données, le modèle et la préparation des données sont maintenant prêts. Instancions-les.
#Utilise un jeu de données et des transformations définies
dataset = PennFudanDataset('PennFudanPed', get_transform(train=True))
dataset_test = PennFudanDataset('PennFudanPed', get_transform(train=False))
#Divisez l'ensemble de données en données d'entraînement et données de test
torch.manual_seed(1)
indices = torch.randperm(len(dataset)).tolist()
dataset = torch.utils.data.Subset(dataset, indices[:-50])
dataset_test = torch.utils.data.Subset(dataset_test, indices[-50:])
#Définir un chargeur de données d'entraînement et de validation
data_loader = torch.utils.data.DataLoader(
dataset, batch_size=2, shuffle=True, num_workers=4,
collate_fn=utils.collate_fn)
data_loader_test = torch.utils.data.DataLoader(
dataset_test, batch_size=1, shuffle=False, num_workers=4,
collate_fn=utils.collate_fn)
Instanciez le modèle.
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
#Les données des enseignants ne concernent que deux classes, le parcours et la personne
num_classes = 2
#Obtenez le modèle à l'aide de la fonction d'assistance
model = get_instance_segmentation_model(num_classes)
#Déplacez le modèle vers l'appareil approprié
model.to(device)
#Construisez l'optimiseur
params = [p for p in model.parameters() if p.requires_grad]
optimizer = torch.optim.SGD(params, lr=0.005,
momentum=0.9, weight_decay=0.0005)
#Planificateur de taux d'apprentissage qui réduit le taux d'apprentissage à 1/10 toutes les 3 époques
lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer,
step_size=3,
gamma=0.1)
Entraînez-vous avec 10 époques. Évaluer avec la fonction d'évaluation à chaque époque. (Il faut environ 8 minutes pour apprendre dans l'environnement GPU Colaboratory. Une erreur d'exécution se produit dans le GPU None.)
#Formation avec 10 époques
num_epochs = 10
for epoch in range(num_epochs):
print(epoch)
#Formation 1 Epoch
train_one_epoch(model, optimizer, data_loader, device, epoch, print_freq=10)
#Mettre à jour le taux d'apprentissage
lr_scheduler.step()
#Évaluer avec un jeu de données de test
evaluate(model, data_loader_test, device=device)
out
...
Averaged stats: model_time: 0.1179 (0.1174) evaluator_time: 0.0033 (0.0051)
Accumulating evaluation results...
DONE (t=0.01s).
Accumulating evaluation results...
DONE (t=0.01s).
IoU metric: bbox
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.831
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.990
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.955
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.543
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.841
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.386
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.881
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.881
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.787
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.887
IoU metric: segm
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.760
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.990
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.921
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.492
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.771
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.345
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.808
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.808
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.725
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.814
Maintenant que la formation est terminée, voyons à quoi ressemblera l'ensemble de données de test.
#Sélectionnez une image de l'ensemble de test
img, _ = dataset_test[4]
#Mettre le modèle en mode évaluation
model.eval()
with torch.no_grad():
prediction = model([img.to(device)])
Lorsque vous sortez la prédiction, il s'agit d'une liste de dictionnaires. Puisque nous avons spécifié une donnée de test, l'exemple ci-dessous a un élément dans la liste. Le dictionnaire contient des prédictions d'image. Dans ce cas, vous pouvez voir qu'il contient des boîtes, des étiquettes, des masques et des scores.
prediction
out
[{'boxes': tensor([[173.1167, 27.6446, 240.8375, 313.0114],
[325.5737, 64.3967, 453.1539, 352.3020],
[222.4494, 24.5255, 306.5306, 291.5595],
[296.8205, 21.3736, 379.0592, 263.7513],
[137.4137, 38.1588, 216.4886, 276.1431],
[167.8121, 19.9211, 332.5648, 314.0146]], device='cuda:0'),
'labels': tensor([1, 1, 1, 1, 1, 1], device='cuda:0'),
'masks': tensor([[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]],
[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]],
[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]],
[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]],
[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]],
[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]]], device='cuda:0'),
'scores': tensor([0.9965, 0.9964, 0.9942, 0.9696, 0.3053, 0.1552], device='cuda:0')}]
Vérifiez l'image et le résultat de la prédiction. L'image (img) est un Tenseur de [couleur, vertical, horizontal]. La couleur étant de 0 à 1, mettez-la à l'échelle de 0 à 255 et remplacez-la par [Vertical, Horizontal, Couleur].
Image.fromarray(img.mul(255).permute(1, 2, 0).byte().numpy())
Ensuite, visualisez le masque prédit. les masques sont attendus comme «[N, 1, H, W]». Où «N» est le nombre prévu d'instances (personnes). Chaque valeur de masque stocke la probabilité de déterminer «personne» en pixels comme 0-1.
Image.fromarray(prediction[0]['masks'][0, 0].mul(255).byte().cpu().numpy())
(D'autres instances prédites (personnes) peuvent également être visualisées en modifiant la valeur de N comme indiqué ci-dessous.)
Image.fromarray(prediction[0]['masks'][1, 0].mul(255).byte().cpu().numpy())
Image.fromarray(prediction[0]['masks'][2, 0].mul(255).byte().cpu().numpy())
Image.fromarray(prediction[0]['masks'][3, 0].mul(255).byte().cpu().numpy())
Je peux bien le prédire.
Dans ce didacticiel, vous avez appris à entraîner un modèle de détection d'objets à l'aide d'un jeu de données que vous avez défini vous-même.
Pour l'ensemble de données, nous avons créé la classe torch.utils.data.Dataset
qui contient la boîte et le masque pour définir l'ensemble de données spécifique à la détection d'objets.
Nous avons également exploité le modèle MaskR-CNN pré-formé à COCOtrain 2017 pour effectuer l'apprentissage par transfert sur ce nouvel ensemble de données.
Pour des exemples plus détaillés de formation multi-machine / multi-GPU, voir references / detection / train sur torchvision GitHub repo Vérifiez le .py.
Dans ce didacticiel, vous avez appris «l'apprentissage par transfert» et «l'ajustement fin» à l'aide d'un modèle pré-entraîné. (Cette fois, il s'agit apparemment de réglage fin, et la différence entre l'apprentissage par transfert et le réglage fin sera expliquée la prochaine fois.) Dans le didacticiel, j'ai essayé avec 120 données d'entraînement et 50 données de vérification, mais même avec environ 40 données d'entraînement, j'ai pu prédire assez correctement. L'apprentissage par transfert est incroyable de pouvoir apprendre avec une si petite quantité de données de test. La prochaine fois, j'aimerais continuer avec "Tutoriel de transfert d'apprentissage pour la vision par ordinateur".
2020/11/15 Première édition publiée
Recommended Posts