Pytorch: Holen Sie sich einen einzelnen Batch von DataLoader ohne Iteration

Erstellt am 26. Juni 2017  ·  18Kommentare  ·  Quelle: pytorch/pytorch

Ist es möglich, einen einzelnen Stapel von einem DataLoader zu erhalten? Derzeit richte ich eine for-Schleife ein und gebe einen Stapel manuell zurück.
Wenn es derzeit keine Möglichkeit gibt, dies mit dem DataLoader zu tun, würde ich gerne daran arbeiten, die Funktionalität hinzuzufügen.

Hilfreichster Kommentar

next(iter(data_loader)) ?

Alle 18 Kommentare

next(iter(data_loader)) ?

Cool, das ist viel besser als das, was ich benutzt hatte.
Danke!

Diese Antwort provoziert ein Speicherleck in meinem Training mit linearer Vergrößerung des RAM-Speichers, während die ständige Beschäftigung mit einer regulären for-Schleife (und genau dem gleichen Code in der Schleife) :/

:+1: an @hyperfraise. Dadurch entsteht ein Speicherleck.

Dasselbe Problem des Speicherlecks mit dem folgenden (etwas anderen) Code:

dataloader_iterator = iter(dataloader)
for i in range(iterations):     
    try:
        X, Y = next(dataloader_iterator)
    except:
        dataloader_iterator = iter(train_loader)
        X, Y = next(dataloader_iterator)
    do_backprop(X, Y)

Während der for-Schleife steigt die Speicherbelegung kontinuierlich an. Ich könnte ein neues Thema mit mehr Informationen eröffnen (falls noch nicht geschehen)

Dies ist möglicherweise kein Speicherleck, sondern einfach die Tatsache, dass Ihre Schleife extrem damit beschäftigt ist, Prozesse schneller zu starten, als wir sie überhaupt beenden können. DataLoader-Iteratoren sind nicht als sehr kurzlebige Objekte gedacht

Mein vorheriger Kommentar war falsch. Ich habe entdeckt, dass das Leck an einer anderen Stelle im Code war (ich habe mich an vars festgehalten, ohne mich für diejenigen zu lösen, die neugierig sind).

bekomme "BrokenPipeError: [Errno 32] Broken pipe" beim nächsten Versuch (iter(dataloader))

Ich habe diese Methode verwendet, um Stapel für das Training in einer Schleife abzurufen:

    for i in range(n):
       batch = next(iter(data_loader))

Mir ist aufgefallen, dass ich immer denselben Batch erhalte, so wie der zugrunde liegende __getitem__ des Datensatzes immer denselben item -Index erhält.
Ist das normal?

@shaibagon
Es ist nicht sehr gut dokumentiert, aber wenn Sie iter(dataloader) ausführen, erstellen Sie ein Objekt der Klasse _DataLoaderIter und in der Schleife erstellen Sie dasselbe Objekt n mal und rufen nur den ersten Stapel ab.
Eine Problemumgehung besteht darin, einen _DataLoaderIter außerhalb der Schleife zu erstellen und darüber zu iterieren. Das Problem besteht darin, dass _DataLoaderIter nach dem Abrufen aller Stapel einen StopIteration-Fehler auslöst .

Um Probleme zu vermeiden, mache ich derzeit folgendes:

    dataloader_iterator = iter(dataloader)
    for i in range(iterations):
        try:
            data, target = next(dataloader_iterator)
        except StopIteration:
            dataloader_iterator = iter(dataloader)
            data, target = next(dataloader_iterator)
        do_something()

Es ist sehr hässlich, aber es funktioniert gut.

ein ähnliches Problem kann hier gefunden werden . Ich hoffe, Lösungsvorschläge in diesem Thread können den Leuten dort auch helfen.

@ srossi93 schöne Lösung. Manchmal erhalte ich eine ignorierte Ausnahme, wenn der Iterationszyklus endet: ConnectionResetError: [Errno 104] Connection reset by peer .

Scheint durch Multiprocessing verursacht zu sein. Wenn Sie num_workers auf dem Dataloader auf 0 setzen, verschwindet der Fehler. Irgendwelche anderen Lösungen?

danke @srossi93

Vielleicht ist dieser Code etwas besser?

def inf_train_gen():
    while True:
        for images, targets in enumerate(dataloader):
            yield images, targets
gen = inf_train_gen
for it in range(num_iters):
    images, targets = gen.next()    

Wird der Datensatz gemischt, wenn ich den oben angegebenen Code verwende?
dataloader_iterator = iter(dataloader) for i in range(iterations): try: X, Y = next(dataloader_iterator) except: dataloader_iterator = iter(train_loader) X, Y = next(dataloader_iterator) do_backprop(X, Y)

warum ist das nicht schon ein Generator/Iterator?

@ Yamin05114 Ich habe ein kleines Beispiel ausgeführt, um zu sehen, ob das Ergebnis von iter (dataloader) bei jedem Zurücksetzen gemischt wird. Wenn Sie dieses kleine Skript unten ausführen, können Sie sich den kleinen Satz von Druckanweisungen ansehen, um sich selbst zu vergewissern, dass die Reihenfolge tatsächlich gemischt ist. Dies ist im Allgemeinen kein Beweis, aber es ist ein überzeugender Beweis dafür, dass die Daten jedes Mal gemischt werden, wenn wir iter(train_loader) aufrufen.

import torch
from torch.utils.data import Dataset, DataLoader

dataset = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7])
dataloader = DataLoader(dataset, batch_size=2, shuffle=True, num_workers=3)
iterloader = iter(dataloader)

for i in range(0, 12):

    try:
        batch = next(iterloader)
    except StopIteration:
        iterloader = iter(dataloader)
        batch = next(iterloader)

    print("iteration" + str(i))
    print(batch)

Außerdem konnte ich den Fehler von @shaibagon nicht reproduzieren ... der folgende Code scheint unterschiedliche Stapel zu erzeugen (unter Verwendung der gleichen Variablen wie oben definiert), also nicht sicher, was dort passiert ist.

for i in range(0, 12):
    batch = next(iter(dataloader))
    print("iteration: " + str(i))
    print(batch)

Wenn Sie ein dataset -Objekt haben, das data.Dataset von Pytorch erbt, muss es die Methode __getitem__ überschreiben, die idx als Argument verwendet. Daher können Sie direkt darauf zugreifen:

**some dataset instance called _data_
data=Dataset(**kwargs)
for i in range(10):
     data[i]

oder

for i in range(10):
     data_batch.__getitem__(i)
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen