[PYTHON] Grundlegendes zu PyTorchs DataSet und DataLoader (2)

Bis zum letzten Mal

Bis zu Letztes Mal habe ich das Verhalten von PyTorchs DataLoader und DataSet verstanden. Dieses Mal wenden wir es an und erstellen Ihren eigenen Datensatz. Vielleicht habe ich auf die Quelle von [hier] verwiesen (https://github.com/adambielski/siamese-triplet).

Lassen Sie uns unseren eigenen Datensatz erstellen

Ich habe das Gefühl, dass ich mit dem Inhalt bis zum letzten Mal etwas Aufwändiges machen kann. Machen wir es möglich, Daten gut zurückzugeben, indem wir einen Datensatz erstellen.

Erstellen Sie ein Beispiel, das paarweise MNIST-Daten zurückgibt

Im jüngsten Trend des metrischen Lernens ist es erforderlich, ein Paar Bilder zu erstellen. Es wurden verschiedene Methoden vorgeschlagen, aber ich bin der Meinung, dass es vorerst nicht viel guten Code gibt, den man ausprobieren kann. Lassen Sie uns diesmal die Handhabung von Paaren vereinfachen, indem Sie als Beispiel selbst einen Datensatz erstellen.

Erstellen Sie eine PairMnistDataset-Klasse

Erstellen Sie zunächst eine Klasse. Erben Sie das DataSet von Torch. Darüber hinaus sollte der Konstruktor den MNIST-Datensatz erhalten. Das positive und das negative Paar von Metric Learning haben die folgende Beziehung.

Name Inhalt
Positive Pair Gleiches Etikett
Negative Pair Nicht identisches Etikett

Da ich die Trainingsdaten mischen möchte, muss ich nur die Positionsbeziehung der Beschriftungen im Konstruktor erstellen, und für die Testdaten muss ich nur zuerst das Paarmuster erstellen, damit ich eine Liste von Indizes erstellen kann.

from torch.utils.data import Dataset

class PairMnistDataset(Dataset):
    def __init__(self, mnist_dataset, train=True):
        self.train = train
        self.dataset = mnist_dataset
        self.transform = mnist_dataset.transform

        if self.train:
            self.train_data = self.dataset.train_data
            self.train_labels = self.dataset.train_labels
            self.train_label_set = set(self.train_labels.numpy())
            self.label_to_indices = {label: np.where(self.train_labels.numpy() == label)[0]
                                     for label in self.train_label_set}
        else:
            self.test_data = self.dataset.test_data
            self.test_labels = self.dataset.test_labels
            self.test_label_set = set(self.test_labels.numpy())
            self.label_to_indices = {label: np.where(self.test_labels.numpy() == label)[0]
                                     for label in self.test_label_set}

            #Ich werde nicht mischen, also entscheide zuerst das Paar
            positive_pairs = [[i,
                               np.random.choice(self.label_to_indices[self.test_labels[i].item()]),
                               1]
                              for i in range(0, len(self.test_data), 2)]

            negative_pairs = [[i,
                               np.random.choice(self.label_to_indices[np.random.choice(list(self.test_label_set - set([self.test_labels[i].item()])))]),
                               0]
                              for i in range(1, len(self.test_data), 2)]

            self.test_pairs = positive_pairs + negative_pairs

Machen Sie __getitem__

Lassen Sie uns das getitem machen, das wir im vorherigen Artikel studiert haben. Sie müssen lediglich beschreiben, welche Daten zurückgegeben werden sollen, wenn der Index übergeben wird.

    def __getitem__(self, index):
        if self.train:
            target = np.random.randint(0, 2)

            # img1,label1 wird zuerst entschieden
            img1, label1 = self.train_data[index], self.train_labels[index].item()
            if target == 1:
                # positive pair
                #Verarbeitung zur Auswahl von Indizes mit derselben Bezeichnung
                siamese_index = index
                while siamese_index == index:
                    siamese_index = np.random.choice(self.label_to_indices[label1])
            else:
                # negative pair
                #Verarbeitung zur Auswahl von Indizes mit unterschiedlichen Beschriftungen
                siamese_label = np.random.choice(list(self.train_label_set - set([label1])))
                siamese_index = np.random.choice(self.label_to_indices[siamese_label])

            img2 = self.train_data[siamese_index]
        else:
            img1 = self.test_data[self.test_pairs[index][0]]
            img2 = self.test_data[self.test_pairs[index][1]]
            target = self.test_pairs[index][2]

        img1 = Image.fromarray(img1.numpy(), mode='L')
        img2 = Image.fromarray(img2.numpy(), mode='L')
        if self.transform:
            img1 = self.transform(img1)
            img2 = self.transform(img2)
            
        return (img1, img2), target  #Ob die Bezeichnungen des metrischen Lernens gleich sind

    def __len__(self):
        return len(self.dataset)

Versuchen Sie, Dataset und Datenlader in main aufzurufen

Alles was Sie tun müssen, ist anzurufen, was Sie bisher gemacht haben. Der Code ist bisher lang und kompliziert, aber ich denke, wenn Sie ihn gut verwenden, können Sie die Daten reibungslos laden.

def main():
    #Das übliche zuerst
    train_dataset = datasets.MNIST(
        '~/dataset/MNIST',  #Gegebenenfalls ändern
        train=True,
        download=True,
        transform=transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.1307,), (0.3081,))
        ]))

    test_dataset = datasets.MNIST(
        '~/dataset/MNIST',  #Gegebenenfalls ändern
        train=False,
        download=True,
        transform=transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.1307,), (0.3081,))
        ]))

    #Selbst erstellter Datensatz und Datenlader
    pair_train_dataset = PairMnistDataset(train_dataset, train=True)
    pair_train_loader = torch.utils.data.DataLoader(
        pair_train_dataset,
        batch_size=16
    )

    pair_test_dataset = PairMnistDataset(test_dataset, train=False)
    pair_test_loader = torch.utils.data.DataLoader(
        pair_test_dataset,
        batch_size=16
    )

    #Zum Beispiel können Sie es so nennen
    for (data1, data2), label in pair_train_loader:
        print(data1.shape)
        print(data2.shape)
        print(label)

Klicken Sie hier für die Ergebnisanzeige. Es wird ordnungsgemäß als Paar zurückgegeben, und das Flag, ob sie dieselbe Bezeichnung haben oder nicht, wird ebenfalls zurückgegeben. Wenn Sie diese Daten verwenden, können Sie problemlos metrisches Lernen durchführen.

    torch.Size([16, 1, 28, 28])
    torch.Size([16, 1, 28, 28])
    tensor([1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1])

Zusammenfassung

Das letzte Mal war es ziemlich lang, aber es war ein Artikel über das Verständnis von DataLoader und DataSet von PyTorch. Wie wäre es, wenn Sie die Daten für das kürzlich beliebte Metric Learning so lesen?

Recommended Posts

Grundlegendes zu PyTorchs DataSet und DataLoader (2)
Grundlegendes zu PyTorchs DataSet und DataLoader (1)
Verstehen Sie t-SNE und verbessern Sie die Visualisierung
Lernen Sie Python-Pakete und -Module kennen
[Pytorch] Memo über Dataset / DataLoader
[Python / matplotlib] FuncAnimation verstehen und verwenden
Verstehen Sie Zahnräder und Erweiterungen in discord.py
Verstehe die Regeln und konvexen Funktionen von Armijo