Beim Maschinentraining ist es üblich, einen Datensatz in Trainingsdaten und Validierungsdaten aufzuteilen. Insbesondere bei Klassifizierungsproblemen ist es möglich, ohne Berücksichtigung der Klassenbezeichnung zufällig zu teilen, es ist jedoch wünschenswert, so zu teilen, dass die Verteilung der Klassenbezeichnung der geteilten Daten dieselbe ist wie die Originaldaten. Das Teilen unter Beibehaltung des Verhältnisses jeder Klasse auf diese Weise wird als geschichtete Extraktion oder geschichtete Aufteilung bezeichnet.
In scikit-learn können Sie eine geschichtete Aufteilung durchführen, indem Sie die Option stratify an die Funktion sklearn.model_selection.train_test_split
übergeben.
Andererseits verfügt PyTorch nicht über einen solchen Mechanismus. Sie können eine Funktion wie "torch.utils.data.random_split" verwenden, um einen Datensatz zufällig aufzuteilen, aber Sie können keine direkte geschichtete Aufteilung durchführen. Daher wird Stratified Split durch Kombination mit train_test_split von scicit-learn realisiert.
Sie können beispielsweise einen geschichteten Split mit folgendem Code durchführen:
import torch
import torchvision.transforms as transforms
from sklearn.model_selection import train_test_split
transformer = transforms.Compose([
transforms.ToTensor(),
])
#Bild laden
dataset = torchvision.datasets.ImageFolder(root='directory_name', transform=transformer)
#Teilen Sie den Datensatz in Zug und Validierung auf
train_indices, val_indices = train_test_split(list(range(len(dataset.targets))), test_size=0.2, stratify=dataset.targets)
train_dataset = torch.utils.data.Subset(dataset, train_indices)
val_dataset = torch.utils.data.Subset(dataset, val_indices)
#Erstellen Sie einen DataLoader
train_data_loader = torch.utils.data.DataLoader(train_dataset, batch_size=4, shuffle=True, num_workers=4)
val_data_loader = torch.utils.data.DataLoader(val_dataset, batch_size=4, shuffle=True, num_workers=4)
Ich werde in der Reihenfolge erklären.
transformer = transforms.Compose([
transforms.ToTensor(),
])
#Bild laden
dataset = torchvision.datasets.ImageFolder(root='directory_name', transform=transformer)
Das ist schön, nicht wahr? Der Bildordner wird verwendet, um das Bild zu laden und einen Datensatz zu erstellen.
#Teilen Sie den Datensatz in Zug und Validierung auf
train_indices, val_indices = train_test_split(list(range(len(dataset.targets))), test_size=0.2, stratify=dataset.targets)
Dieser Teil ist der Hauptteil. Übergeben Sie das Array, das Sie teilen möchten, an das erste Argument von train_test_split, aber Sie können Dataset nicht direkt übergeben, sodass list (range (len (dataset.targets))
das Indexarray von Dataset (
[0,1,1) ist. 2,3, ... Anzahl der Daten] `) wird generiert und an seiner Stelle übergeben. Durch Übergeben der Klassenbezeichnung "dataset.targets" für dieses Indexarray als Schichtungsoption kann das Indexarray für Training und Validierung aufgeteilt werden, während das Verhältnis der Klassenbezeichnungen zu den Originaldaten beibehalten wird.
train_dataset = torch.utils.data.Subset(dataset, train_indices)
val_dataset = torch.utils.data.Subset(dataset, val_indices)
Da das Indexarray geteilt wird, wird der Datensatz basierend auf dem Index geteilt. Wie der Name schon sagt, ist Subset eine Klasse zum Erstellen einer Teilmenge von Daten. Durch Übergeben des ursprünglichen Datensatzes und des Indexarrays können Sie den Datensatz generieren, der dem Index entspricht.
#Erstellen Sie einen DataLoader
train_data_loader = torch.utils.data.DataLoader(train_dataset, batch_size=4, shuffle=True, num_workers=4)
val_data_loader = torch.utils.data.DataLoader(val_dataset, batch_size=4, shuffle=True, num_workers=4)
Sie müssen den Datensatz lediglich wie gewohnt an den DataLoader übergeben.
https://discuss.pytorch.org/t/how-to-do-a-stratified-split/62290
Recommended Posts