ImageFolder zum Laden von Datensätzen
ImageFolder
Als allgemeiner Datenlader sind die Daten im Datensatz folgendermaßen organisiert
Die Funktion ist wie folgt
ImageFolder(root, transform``=``None``, target_transform``=``None``, loader``=``default_loader)
Parametererklärung
-
Root gibt den Pfad zum Laden des Bildes an
-
transform: Transformationsoperation, die für das PIL-Image ausgeführt wird. Die Eingabe der Transformation ist das zurückgegebene Objekt der Verwendung des Loaders zum Lesen des Bildes
-
target_transform: Transformation des Labels
-
Loader: Standardmäßig wird das PIL-Image-Objekt im RGB-Format gelesen, um das Bild nach einem bestimmten Pfad zu lesen
Die Beschriftung wird nach dem Sortieren in der Reihenfolge des Ordnernamens in einem Wörterbuch gespeichert, dh {Klassenname: Klassennummer (ab 0)}. Im Allgemeinen ist es am besten, den Ordner direkt mit einer Nummer ab 0 zu benennen wird mit dem konsequenten ImageFolder
tatsächlichen label
, wenn es nicht für diese Namenskonvention ist, wird es an den zu sehen empfohlenen self.class_to_idx
Attributen die Abbildungsbeziehung zwischen Etikett und Ordnernamen zu verstehen
Es ist ersichtlich, dass es in zwei Kategorien unterteilt ist: Katze und Hund
import torchvision.datasets as dset
dataset = dset.ImageFolder('./data/dogcat_2') #没有transform,先看看取得的原始图像数据
print(dataset.classes) #根据分的文件夹的名字来确定的类别
print(dataset.class_to_idx) #按顺序为这些类别定义索引为0,1...
print(dataset.imgs) #返回从所有文件夹中得到的图片的路径以及其类别
Rückkehr
['cat', 'dog']
{
'cat': 0, 'dog': 1}
[('./data/dogcat_2/cat/cat.12484.jpg', 0), ('./data/dogcat_2/cat/cat.12485.jpg', 0), ('./data/dogcat_2/cat/cat.12486.jpg', 0), ('./data/dogcat_2/cat/cat.12487.jpg', 0), ('./data/dogcat_2/dog/dog.12496.jpg', 1), ('./data/dogcat_2/dog/dog.12497.jpg', 1), ('./data/dogcat_2/dog/dog.12498.jpg', 1), ('./data/dogcat_2/dog/dog.12499.jpg', 1)]
Zeigen Sie die erhaltenen Bilddaten an:
#从返回结果可见得到的数据仍是PIL Image对象
print(dataset[0])
print(dataset[0][0])
print(dataset[0][1]) #得到的是类别0,即cat
Rückkehr:
(<PIL.Image.Image image mode=RGB size=497x500 at 0x11D99A9B0>, 0)
<PIL.Image.Image image mode=RGB size=497x500 at 0x11DD24278>
0
Und dann transform
Tensor werden
data_transform = {
"train": transforms.Compose([transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor()
]),
"val": transforms.Compose([transforms.Resize((224, 224)), # cannot 224, must (224, 224)
transforms.ToTensor()
])}
train_dataset = datasets.ImageFolder(root=os.path.join(data_root, "train"),
transform=data_transform["train"])
print(train_dataset[0])
print(train_dataset[0][0])
print(train_dataset[0][1]) #得到的是类别0,即cat
erhalten
(tensor([[[0.3765, 0.3765, 0.3765, ..., 0.3765, 0.3765, 0.3765],
[0.3765, 0.3765, 0.3765, ..., 0.3765, 0.3765, 0.3765],
[0.3804, 0.3804, 0.3804, ..., 0.3765, 0.3765, 0.3765],
...,
[0.4941, 0.4941, 0.4902, ..., 0.3804, 0.3765, 0.3765],
[0.5098, 0.5098, 0.5059, ..., 0.3804, 0.3765, 0.3765],
[0.5098, 0.5098, 0.5059, ..., 0.3804, 0.3765, 0.3765]],
[[0.5686, 0.5686, 0.5686, ..., 0.5843, 0.5804, 0.5804],
[0.5686, 0.5686, 0.5686, ..., 0.5843, 0.5804, 0.5804],
[0.5725, 0.5725, 0.5725, ..., 0.5843, 0.5804, 0.5804],
...,
[0.5686, 0.5686, 0.5686, ..., 0.5961, 0.5922, 0.5922],
[0.5686, 0.5686, 0.5686, ..., 0.5961, 0.5922, 0.5922],
[0.5686, 0.5686, 0.5686, ..., 0.5961, 0.5922, 0.5922]],
[[0.4824, 0.4824, 0.4824, ..., 0.4902, 0.4902, 0.4902],
[0.4824, 0.4824, 0.4824, ..., 0.4902, 0.4902, 0.4902],
[0.4863, 0.4863, 0.4863, ..., 0.4902, 0.4902, 0.4902],
...,
[0.3647, 0.3686, 0.3804, ..., 0.4824, 0.4784, 0.4784],
[0.3451, 0.3490, 0.3608, ..., 0.4824, 0.4784, 0.4784],
[0.3451, 0.3490, 0.3608, ..., 0.4824, 0.4784, 0.4784]]]), 0)
省略
图像Tensor [........]
标签Tensor [0]
Sie können wissen, train_dataset[0]
dass einer tuple
ein Tensor und der andere ein Skalar ist
print(train_dataset[0][0].shape)
print(train_dataset[0][1])
Rückkehr
torch.Size([3, 224, 224])
0
DataLoader generiert Batch-Trainingsdaten
for epoch in range(epoch_num):
for image, label in train_loader:
print("label: ", labels, labels.dtype)
print("imges: ", images, images.dtype)
Rückkehr
label: tensor([0]) torch.int64
imges: tensor([[[[0.2275, 0.2275, 0.2235, ..., 0.2196, 0.2196, 0.2196],
[0.2275, 0.2275, 0.2235, ..., 0.2196, 0.2196, 0.2196],
[0.2235, 0.2235, 0.2235, ..., 0.2157, 0.2157, 0.2157],
...,
[0.2392, 0.2392, 0.2392, ..., 0.2235, 0.2235, 0.2235],
[0.2353, 0.2353, 0.2353, ..., 0.2235, 0.2275, 0.2275],
[0.2353, 0.2353, 0.2353, ..., 0.2235, 0.2275, 0.2275]],
[[0.2392, 0.2392, 0.2353, ..., 0.2275, 0.2275, 0.2275],
[0.2392, 0.2392, 0.2353, ..., 0.2275, 0.2275, 0.2275],
[0.2353, 0.2353, 0.2353, ..., 0.2235, 0.2235, 0.2235],
...,
[0.2275, 0.2275, 0.2314, ..., 0.2196, 0.2196, 0.2196],
[0.2235, 0.2235, 0.2275, ..., 0.2196, 0.2196, 0.2196],
[0.2235, 0.2235, 0.2275, ..., 0.2196, 0.2196, 0.2196]],
[[0.1961, 0.1961, 0.1961, ..., 0.1765, 0.1765, 0.1765],
[0.1961, 0.1961, 0.1961, ..., 0.1765, 0.1765, 0.1765],
[0.1922, 0.1922, 0.1922, ..., 0.1725, 0.1725, 0.1725],
...,
[0.1529, 0.1529, 0.1529, ..., 0.1686, 0.1686, 0.1686],
[0.1490, 0.1490, 0.1490, ..., 0.1686, 0.1686, 0.1686],
[0.1490, 0.1490, 0.1490, ..., 0.1686, 0.1686, 0.1686]]]]) torch.float32
Laden auflisten
Die Funktion enumerate () wird verwendet, um ein durchlaufbares Datenobjekt (z. B. eine Liste) zu konvertieren.TupelOder Zeichenfolge) wird zu einer Indexsequenz kombiniert, in der Daten und Datenindizes gleichzeitig aufgelistet sind, die im Allgemeinen in einer for-Schleife verwendet wird.
Sie können diese Schleife verwenden, um batchsize
jede der folgenden 元组
zu laden , um zu erhaltenEntsprechende Bilder und Etiketten
Zuordnung mehrerer Elemente
Wenn Python erkennt, dass sich links neben dem Gleichheitszeichen und der Liste oder dem Tupel rechts mehrere Variablen befinden, dekomprimiert es automatisch die Liste und das Tupel und weist sie nacheinander den entsprechenden Elementen zu:
l = [1, 2]
a, b = l
Also kannst du
for step, data in enumerate(train_bar):
images, labels = data
Schließlich berechnet nn.CrossEntropyLoss () die Verlustregression
nn.CrossEntropyLoss()
Es ist nn.logSoftmax()
und nn.NLLLoss()
Integration, es kann direkt verwendet werden, um sowohl den Netzwerkbetrieb zu ersetzen. Werfen wir einen Blick auf den Berechnungsprozess.
Dabei ist x der Ausgabevektor des Netzwerks und Klasse die reale Bezeichnung
Beispielsweise ist die Ausgabe eines Netzwerks mit drei Klassifizierungen für eine Eingabestichprobe [-0,7715, -0,6205, -0,2562], die wahre Bezeichnung der Stichprobe ist 0 und der nn.CrossEntropyLoss()
berechnete Verlust ist