Dies ist die 8. Ausgabe von PyTorch Official Tutorial nach Last time. Dieses Mal fahren wir mit dem [TorchVision Object Detection Finetuning Tutorial] fort (https://pytorch.org/tutorials/intermediate/torchvision_tutorial.html).
TorchVision Object Detection Finetuning Tutorial
In diesem Tutorial verwenden wir die vorgefertigte Maske R-CNN, um die Feinabstimmung und das Transferlernen zu sehen. Die für das Training verwendeten Daten sind Penn-Fudan-Daten zur Erkennung und Segmentierung von Fußgängern. Für diese Daten werden 170 Bilder mit 345 Fußgängern (Instanzen) erstellt.
Zunächst müssen Sie die pycocotools-Bibliothek installieren. Diese Bibliothek wird verwendet, um eine Bewertung mit dem Namen "Intersection over Union" zu berechnen. "Kreuzung über Union" ist eine der Methoden zur Bewertung des Übereinstimmungszustands von Bereichen bei der Objekterkennung.
%%shell
pip install cython
#Installieren Sie pycocotools. Die Standardversion von Colab ist https://github.com/cocodataset/cocoapi/pull/In 354 wurde ein Fehler behoben.
pip install -U 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'
Definieren Sie den Datensatz.
Erforderliche Daten mithilfe von Torchvision-Skript (Objekterkennung, Instanzsegmentierung, Personenschlüsselpunkterkennungsbibliothek) Sie können einen Satz erstellen.
Der Datensatz erfordert die folgenden Attribute:
Bild: PIL-Bild der Größe (H, B)
Ziel: Ein Diktat mit den folgenden Feldern
Felder (FloatTensor [N, 4]): Koordinaten von N Begrenzungsrahmen in der Form [x0, y0, x1, y1]. Der Bereich liegt zwischen 0 und W und zwischen 0 und H.
Beschriftungen (Int64Tensor [N]): Beschriftungen für jedes Rahmenfeld
area (Tensor [N]): Der Bereich des Begrenzungsrahmens. Es wird verwendet, um die Metrikwerte während der Auswertung mit der COCO-Metrik zwischen den kleinen, mittleren und großen Feldern zu trennen. * iscrowd (UInt8Tensor [N]): Instanzen mit iscrowd = True werden bei der Auswertung ignoriert. * Masken (optional) (UInt8Tensor [N, H, W]): Segmentierungsmaske für jedes Objekt (repräsentiert den Bereich des zu erkennenden Objekts) * Schlüsselpunkte (optional) (FloatTensor [N, K, 3]): N. Für jedes der Objekte enthält es K Schlüsselpunkte der Form [x, y, Sichtbarkeit], die das Objekt definieren. Sichtbarkeit = 0 bedeutet, dass die wichtigsten Punkte nicht angezeigt werden. Beachten Sie, dass für die Datenerweiterung das Konzept des Spiegelns von Schlüsselpunkten von der Datendarstellung abhängt. (Grob gesagt definiert der Datensatz ein Rechteck, das Objekte in Feldern enthält, und Masken definieren, ob es sich um ein Objekt in Pixel handelt oder nicht.) Wenn das Modell die obige Methode zurückgibt, wird das Modell sowohl trainiert als auch ausgewertet. Es funktioniert und das Evaluierungsskript von pycocotools wird verwendet.
Lassen Sie uns den Datensatz des Penn-Fudan-Datensatzes ausgeben. Zuerst, https://www.cis.upenn.edu/~jshi/ped_html/PennFudanPed.zip Laden Sie die Zip-Datei herunter und entpacken Sie sie.
%%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
Die Daten haben die folgende Struktur.
PennFudanPed/
PedMasks/
FudanPed00001_mask.png
FudanPed00002_mask.png
FudanPed00003_mask.png
FudanPed00004_mask.png
...
PNGImages/
FudanPed00001.png
FudanPed00002.png
FudanPed00003.png
FudanPed00004.png
Lassen Sie uns das erste Bild anzeigen.
from PIL import Image
Image.open('PennFudanPed/PNGImages/FudanPed00001.png')
(Wie in der entpackten readme.txt beschrieben, ist das Maskenbild ein Bild mit einem Hintergrund von "0" und einer Bezeichnung von 1 oder mehr für jeden Fußgänger.)
mask = Image.open('PennFudanPed/PedMasks/FudanPed00001_mask.png')
#Jede Maskeninstanz hat eine andere Farbe von Null bis N.
#Wobei N die Anzahl der Instanzen (Fußgänger) ist. Zur Erleichterung der Visualisierung
#Fügen wir der Maske eine Farbpalette hinzu.
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
Diese Daten haben eine Maske, die jedes Bild und jeden Fußgänger identifiziert, und jede Farbe der Maske entspricht einem einzelnen Fußgänger. Erstellen wir die Klasse torch.utils.data.Dataset für dieses Dataset.
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
#Laden und sortieren Sie alle Bilddateien
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):
#Laden Sie Bilder und Masken
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")
#Weil jede Farbe einer anderen Instanz entspricht und 0 der Hintergrund ist
#Beachten Sie, dass wir die Maske nicht in RGB konvertiert haben
mask = Image.open(mask_path)
mask = np.array(mask)
#Instanzen werden in verschiedenen Farben codiert
obj_ids = np.unique(mask)
#Die erste ID ist der Hintergrund. Löschen Sie sie daher
obj_ids = obj_ids[1:]
# split the color-encoded mask into a set
# of binary masks
#Teilen Sie die farbcodierte Maske in eine Reihe von Binärmasken
masks = mask == obj_ids[:, None, None]
# get bounding box coordinates for each mask
#Holen Sie sich die Begrenzungsrahmenkoordinaten für jede Maske
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
#Es gibt nur eine Klasse
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
#Angenommen, nicht alle Instanzen sind überlastet
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)
Das war's für den Datensatz. Mal sehen, wie die Ausgabe dieses Datasets organisiert ist
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)})
Sie können sehen, dass das Dataset PIL.Image und ein Wörterbuch zurückgibt, das einige Felder wie "Boxen", "Beschriftungen", "Masken" enthält.
Obwohl nicht im Lernprogramm enthalten, kann der folgende Code Felder und Masken veranschaulichen. Kästchen sind Quadrate, die Instanzen (Personen) enthalten, und Masken sind die Instanzen selbst.
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
target = dataset[0][1]
#Erstinstanzmasken
masks_0 = target['masks'][0,:,:]
#Boxen der ersten Instanz
boxes_0 = target['boxes'][0]
#Ausgabemaske
ax.imshow(masks_0)
#Ausgabeboxen
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
Dieses Tutorial verwendet MaskR-CNN, das auf FasterR-CNN basiert. Schnelleres R-CNN ist einer der Objekterkennungsalgorithmen. Hierbei handelt es sich um ein Modell, das sowohl die Grenzbox als auch die Klassenbewertung (das Quadrat, das das Objekt enthält und was das Objekt ist) der potenziellen Objekte im Bild vorhersagt. (Das Bild unten ist ein verarbeitetes Bild von Faster R-CNN.)
Die Maske R-CNN ist eine verbesserte Version von Faster R-CNN, die die Objekterkennung nicht nur nach Quadrat (Kästchen), sondern auch nach Pixeleinheit (Maske) beurteilt. (Das Bild unten ist ein verarbeitetes Bild der Maske R-CNN.)
Es gibt zwei Hauptgründe für die Anpassung eines Modells mit Fackelvision. Die erste besteht darin, ein vorab trainiertes Modell zu nutzen und die letzte Ebene zu optimieren. Das andere ist, wenn Sie das Backbone Ihres Modells durch ein anderes Backbone ersetzen möchten. (Zum Beispiel für eine schnellere Vorhersage) Nehmen wir ein konkretes Beispiel.
Hier erfahren Sie, wie Sie das vorab trainierte Modell nutzen und es auf die Klasse abstimmen können, die Sie identifizieren möchten.
import torchvision
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
#Laden Sie vorgefertigte Modelle bei COCO
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
#Klassifikator, benutzerdefinierte Nummer_Durch einen neuen Klassifikator durch Klassen ersetzen
num_classes = 2 # 1 class (person) + background :1 Klasse (Person)+Hintergrund
#Ruft die Anzahl der Eingabefunktionen des Klassifikators ab
in_features = model.roi_heads.box_predictor.cls_score.in_features
#Ersetzen Sie den vorgefertigten KOPF durch einen neuen
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
Der andere Fall ist, wenn Sie das Modell-Backbone durch ein anderes Backbone ersetzen möchten. Beispielsweise kann das aktuelle Standard-Backbone (ResNet-50) in einigen Situationen zu groß sein, und Sie möchten möglicherweise ein kleineres Modell nutzen. Im Folgenden wird beschrieben, wie Sie mit Torchvision das Backbone ändern.
import torchvision
from torchvision.models.detection import FasterRCNN
from torchvision.models.detection.rpn import AnchorGenerator
#Lädt ein vorab trainiertes Modell zur Klassifizierung und gibt nur Features zurück
backbone = torchvision.models.mobilenet_v2(pretrained=True).features
#FasterRCNN muss die Anzahl der Ausgangskanäle im Backbone kennen.
# mobilenet_Für v2 ist es 1280, also müssen Sie es hier hinzufügen
backbone.out_channels = 1280
#In RPN mit 5 verschiedenen Größen und 3 verschiedenen Seitenverhältnissen
#Lassen Sie uns 5 x 3 Anker für jede räumliche Position generieren.
#Weil die Größe und das Seitenverhältnis jeder Feature-Map unterschiedlich sein können
# Tuple [Tuple [int]]es gibt.
anchor_generator = AnchorGenerator(sizes=((32, 64, 128, 256, 512),),
aspect_ratios=((0.5, 1.0, 2.0),))
#Mit der Feature-Map, die zum Trimmen des interessierenden Bereichs verwendet wird,
#Definieren wir die Größe der Trimmung nach der Neuskalierung.
#Wenn das Backbone Tensor zurückgibt, featmap_Namen ist[0]Wird voraussichtlich sein.
#Im Allgemeinen ist das Backbone OrderedDict[Tensor]Muss zurückgegeben werden,
# featmap_Sie können die Feature-Map auswählen, die mit Namen verwendet werden soll.
roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[0],
output_size=7,
sampling_ratio=2)
#Fügen Sie die Teile zu einem schnelleren RCNN-Modell zusammen
model = FasterRCNN(backbone,
num_classes=2,
rpn_anchor_generator=anchor_generator,
box_roi_pool=roi_pooler)
In diesem Fall ist der Datensatz sehr klein, daher werden wir das vorab trainierte Modell optimieren. Folgen Sie daher Ansatz Nummer 1. Wir werden hier die Maske R-CNN verwenden, um auch die Segmentierungsmaske für die Instanz zu berechnen (um den Bereich der Person in Pixel zu bestimmen).
maskrcnn_resnet50_fpn
ist in der offiziellen Dokumentation (https://pytorch.org/docs/stable/torchvision/models.html#torchvision.models.detection.maskrcnn_resnet50_fpn) beschrieben, aber ResNet-50-FPN Es ist ein kundenspezifisches Modell.
maskrcnn_resnet50_fpn ist mit dem Datensatz unter COCO train2017 vorab trainiert.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):
#Laden Sie ein vorab trainiertes COCO-Instanzsegmentierungsmodell
model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True)
#Ruft die Anzahl der Eingabefunktionen des Klassifikators ab
in_features = model.roi_heads.box_predictor.cls_score.in_features
#Ersetzen Sie den vorgefertigten KOPF durch einen neuen
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
#mask Ruft die Anzahl der Eingabefunktionen des Klassifikators ab
in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels
hidden_layer = 256
# and replace the mask predictor with a new one
#Ersetzen Sie den Maskenprädiktor durch einen neuen
model.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask,
hidden_layer,
num_classes)
return model
Jetzt können Sie Ihr Modell mit diesem Datensatz trainieren und bewerten.
(Wenn Sie dieses Modell mit torchvision.models.detection.maskrcnn_resnet50_fpn vergleichen, können Sie feststellen, dass sich die Abmessungen der folgenden Teile geändert haben.)
(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))
)
)
Die Fackelvision "Vision / Referenzen / Erkennung /" verfügt über eine Reihe von Hilfsfunktionen, um das Training und die Bewertung von Objekterkennungsmodellen zu vereinfachen. Hier verwenden wir "Referenzen / Erkennung / engine.py", "Referenzen / Erkennung / utils.py", "Referenzen / Erkennung / transforms.py".
Kopieren Sie diese Dateien (und die zugehörigen Dateien) zur Verwendung.
%%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 ../
Verwenden wir die kopierten "Referenzen / Erkennung", um einige Hilfsfunktionen zum Erweitern / Transformieren von Daten zu erstellen.
from engine import train_one_epoch, evaluate
import utils
import transforms as T
def get_transform(train):
transforms = []
#Bild in Tensor konvertieren
transforms.append(T.ToTensor())
if train:
#Für das Training werden die Bild- und Lehrerdaten zufällig horizontal gespiegelt. (Bild im Spiegel reflektiert)
transforms.append(T.RandomHorizontalFlip(0.5))
return T.Compose(transforms)
Der obige Code ist die Aufbereitung der Daten. Konvertiert das Bild in Tensor und invertiert es zufällig für Trainingsdaten. Es ist keine Datenstandardisierung oder Bildskalierung erforderlich. Das Mask R-CNN-Modell erledigt dies intern.
Der Datensatz, das Modell und die Datenaufbereitung sind jetzt fertig. Lassen Sie uns sie instanziieren.
#Verwendet einen Datensatz und definierte Transformationen
dataset = PennFudanDataset('PennFudanPed', get_transform(train=True))
dataset_test = PennFudanDataset('PennFudanPed', get_transform(train=False))
#Teilen Sie den Datensatz in Trainingsdaten und Testdaten
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:])
#Definieren Sie einen Trainings- und Validierungsdatenlader
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)
Instanziieren Sie das Modell.
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
#Lehrerdaten sind nur zwei Klassen, Hintergrund und Person
num_classes = 2
#Holen Sie sich das Modell mit der Hilfsfunktion
model = get_instance_segmentation_model(num_classes)
#Bewegen Sie das Modell auf das entsprechende Gerät
model.to(device)
#Erstellen Sie den Optimierer
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)
#Lernratenplaner, der die Lernrate alle 3 Epochen auf 1/10 reduziert
lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer,
step_size=3,
gamma=0.1)
Trainiere mit 10 Epochen. Evaluieren Sie mit der Evaluierungsfunktion in jeder Epoche. (Das Erlernen der Colaboratory GPU-Umgebung dauert ca. 8 Minuten. In der None GPU tritt ein Laufzeitfehler auf.)
#Training mit 10 Epochen
num_epochs = 10
for epoch in range(num_epochs):
print(epoch)
#1 Epochentraining
train_one_epoch(model, optimizer, data_loader, device, epoch, print_freq=10)
#Lernrate aktualisieren
lr_scheduler.step()
#Mit Testdatensatz auswerten
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
Nachdem das Training beendet ist, wollen wir sehen, wie der Testdatensatz aussehen wird.
#Wählen Sie ein Bild aus dem Testsatz aus
img, _ = dataset_test[4]
#Versetzen Sie das Modell in den Bewertungsmodus
model.eval()
with torch.no_grad():
prediction = model([img.to(device)])
Wenn Sie die Vorhersage ausgeben, handelt es sich um eine Liste von Wörterbüchern. Da wir eine Testdaten angegeben haben, enthält das folgende Beispiel ein Element in der Liste. Das Wörterbuch enthält Bildvorhersagen. In diesem Fall sehen Sie, dass es Felder, Beschriftungen, Masken und Partituren enthält.
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')}]
Überprüfen Sie das Bild und das Vorhersageergebnis. Das Bild (img) ist ein Tensor von [Farbe, vertikal, horizontal]. Da die Farbe 0-1 ist, skalieren Sie sie auf 0-255 und ersetzen Sie sie durch [Vertikal, Horizontal, Farbe].
Image.fromarray(img.mul(255).permute(1, 2, 0).byte().numpy())
Visualisieren Sie als Nächstes die vorhergesagte Maske. Masken werden als "[N, 1, H, W]" erwartet. Wobei "N" die vorhergesagte Anzahl von Instanzen (Personen) ist. Jeder Wert der Maske speichert die Wahrscheinlichkeit, "Person" in Pixeln zu bestimmen, als 0-1.
Image.fromarray(prediction[0]['masks'][0, 0].mul(255).byte().cpu().numpy())
(Andere vorhergesagte Instanzen (Personen) können auch durch Ändern des Werts von N wie unten gezeigt visualisiert werden.)
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())
Ich kann es gut vorhersagen.
In diesem Lernprogramm haben Sie gelernt, wie Sie ein Objekterkennungsmodell anhand eines von Ihnen selbst definierten Datensatzes trainieren. Für das Dataset haben wir die Klasse "torch.utils.data.Dataset" erstellt, die das Feld und die Maske enthält, um das für die Objekterkennung spezifische Dataset zu definieren. Wir haben auch das auf COCOtrain 2017 vorab trainierte MaskR-CNN-Modell genutzt, um Transferlernen für diesen neuen Datensatz durchzuführen.
Ausführlichere Beispiele für das Training mit mehreren Maschinen / GPUs finden Sie unter Referenzen / Erkennung / Zug unter torchvision GitHub repo. Überprüfen Sie die .py.
In diesem Tutorial haben Sie anhand eines vorab trainierten Modells "Transferlernen" und "Feinabstimmung" gelernt. (Dieses Mal wird es anscheinend als Feinabstimmung bezeichnet, und der Unterschied zwischen Transferlernen und Feinabstimmung wird beim nächsten Mal erklärt.) Im Tutorial habe ich es mit 120 Trainingsdaten und 50 Verifizierungsdaten versucht, aber selbst mit ungefähr 40 Trainingsdaten konnte ich ziemlich richtig vorhersagen. Transferlernen ist erstaunlich, um mit so wenig Testdaten lernen zu können. Das nächste Mal möchte ich mit "Lernprogramm für Computer Vision übertragen" fortfahren.
2020/11/15 Erste Ausgabe veröffentlicht
Recommended Posts