webentwicklung-frage-antwort-db.com.de

Datenerweiterung in PyTorch

Ich bin etwas verwirrt über die in PyTorch durchgeführte Datenerweiterung. Soweit ich weiß, behalten wir jetzt, wenn wir eine Datenerweiterung durchführen, unseren ursprünglichen Datensatz bei und fügen dann andere Versionen hinzu (Spiegeln, Beschneiden ... usw.). Dies scheint jedoch nicht in PyTorch zu geschehen. Soweit ich aus den Referenzen verstanden habe, verwenden wir data.transforms in PyTorch, dann werden sie einzeln angewendet. Also zum Beispiel:

data_transforms = {
    'train': transforms.Compose([
        transforms.RandomResizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
}

Für das Training beschneiden wir das Bild zunächst nach dem Zufallsprinzip und passen es in der Größe an (224,224). Dann nehmen wir diese (224,224) Bilder und spiegeln sie horizontal. Daher enthält unser Datensatz jetzt NUR die horizontal gespiegelten Bilder, sodass unsere Originalbilder in diesem Fall verloren gehen.

Habe ich recht? Ist dieses Verständnis richtig? Wenn nicht, wo können wir PyTorch in diesem obigen Code (aus der offiziellen Dokumentation entnommen) anweisen, die Originalbilder beizubehalten und die Größe auf die erwartete Form zu ändern (224,224)?

Vielen Dank

24
H.S

Die Vorgänge transforms werden bei jeder Stapelgenerierung auf Ihre Originalbilder angewendet. Damit Ihr Datensatz unverändert bleibt, werden bei jeder Iteration nur die Stapelbilder kopiert und transformiert.

Die Verwirrung kann von der Tatsache herrühren, dass transforms häufig, wie in Ihrem Beispiel, sowohl für die Datenaufbereitung (Größenänderung/Zuschneiden auf erwartete Abmessungen, Normalisierung von Werten usw.) als auch für die Datenerweiterung (Randomisierung der Größenänderung/Zuschneiden, zufälliges Spiegeln der Bilder usw.).


Was Ihr data_transforms['train'] Tut, ist:

  • Verändern Sie die Größe des bereitgestellten Bildes nach dem Zufallsprinzip und schneiden Sie es nach dem Zufallsprinzip zu, um einen Patch (224, 224) Zu erhalten
  • Wende einen zufälligen horizontalen Flip mit einer Chance von 50/50 auf diesen Patch an oder nicht
  • Konvertiere es in ein Tensor
  • Normalisieren Sie das resultierende Tensor unter Berücksichtigung der von Ihnen angegebenen Mittel- und Abweichungswerte

Was Ihr data_transforms['val'] Tut, ist:

  • Ändere die Größe deines Bildes auf (256, 256)
  • Schneiden Sie das verkleinerte Bild in der Mitte zu, um einen Patch (224, 224) Zu erhalten
  • Konvertiere es in ein Tensor
  • Normalisieren Sie das resultierende Tensor unter Berücksichtigung der von Ihnen angegebenen Mittel- und Abweichungswerte

(d. h. die zufällige Größenänderung/Zuschneidung für die Trainingsdaten wird durch eine feste Operation für die Validierungsoperation ersetzt, um zuverlässige Validierungsergebnisse zu erhalten)


Wenn Sie nicht möchten, dass Ihre Trainingsbilder mit einer Chance von 50/50 horizontal gespiegelt werden, entfernen Sie einfach die Zeile transforms.RandomHorizontalFlip().

Wenn Sie möchten, dass Ihre Bilder immer in der Mitte beschnitten werden, ersetzen Sie transforms.RandomResizedCrop Durch transforms.Resize Und transforms.CenterCrop, Wie für data_transforms['val'].

15
benjaminplanche

Ich gehe davon aus, dass Sie fragen, ob diese Datenerweiterungstransformationen (z. B. RandomHorizontalFlip) tatsächlich Vergrößerung des Datensatzes oder werden sie nacheinander auf jedes Element im Datensatz angewendet und nicht) Hinzufügen zur Größe des Datensatzes.

Beim Ausführen des folgenden einfachen Code-Snippets konnten wir beobachten, dass letzteres ist wahr, dh wenn Sie einen Datensatz mit 8 Bildern haben, und ein PyTorch-Datensatzobjekt für diesen Datensatz erstellen, wenn Sie den Datensatz und die Transformationen durchlaufen werden für jeden Datenpunkt aufgerufen und der transformierte Datenpunkt wird zurückgegeben. Wenn Sie beispielsweise zufälliges Spiegeln haben, werden einige der Datenpunkte als Original zurückgegeben, andere als gespiegelt (z. B. 4 gespiegelt und 4 Original). Mit anderen Worten, durch eine Iteration durch die Datensatzelemente erhalten Sie 8 Datenpunkte (einige umgedreht und andere nicht). [Dies steht im Widerspruch zum herkömmlichen Verständnis der Erweiterung des Datensatzes (z. B. in diesem Fall mit 16 Datenpunkten im erweiterten Datensatz)]

class experimental_dataset(Dataset):

    def __init__(self, data, transform):
        self.data = data
        self.transform = transform

    def __len__(self):
        return len(self.data.shape[0])

    def __getitem__(self, idx):
        item = self.data[idx]
        item = self.transform(item)
        return item

    transform = transforms.Compose([
        transforms.ToPILImage(),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor()
    ])

x = torch.Rand(8, 1, 2, 2)
print(x)

dataset = experimental_dataset(x,transform)

for item in dataset:
    print(item)

Ergebnisse: (Die kleinen Unterschiede bei den Fließkommawerten werden durch die Transformation in pil-Bild und zurück verursacht.)

Ursprünglicher Dummy-Datensatz:

tensor([[[[0.1872, 0.5518],
          [0.5733, 0.6593]]],


    [[[0.6570, 0.6487],
      [0.4415, 0.5883]]],


    [[[0.5682, 0.3294],
      [0.9346, 0.1243]]],


    [[[0.1829, 0.5607],
      [0.3661, 0.6277]]],


    [[[0.1201, 0.1574],
      [0.4224, 0.6146]]],


    [[[0.9301, 0.3369],
      [0.9210, 0.9616]]],


    [[[0.8567, 0.2297],
      [0.1789, 0.8954]]],


    [[[0.0068, 0.8932],
      [0.9971, 0.3548]]]])

transformierter Datensatz:

tensor([[[0.1843, 0.5490],
     [0.5725, 0.6588]]])
tensor([[[0.6549, 0.6471],
     [0.4392, 0.5882]]])
tensor([[[0.5647, 0.3255],
         [0.9333, 0.1216]]])
tensor([[[0.5569, 0.1804],
         [0.6275, 0.3647]]])
tensor([[[0.1569, 0.1176],
         [0.6118, 0.4196]]])
tensor([[[0.9294, 0.3333],
         [0.9176, 0.9608]]])
tensor([[[0.8549, 0.2275],
         [0.1765, 0.8941]]])
tensor([[[0.8902, 0.0039],
         [0.3529, 0.9961]]])
27
Ashkan372