Wie man mini-batches in pytorch in eine saubere und effiziente Art und Weise?
Ich versuche zu tun, eine einfache Sache, die war Zug ein lineares Modell mit Stochastic Gradient Descent (SGD) mit Fackel:
import numpy as np
import torch
from torch.autograd import Variable
import pdb
def get_batch2(X,Y,M,dtype):
X,Y = X.data.numpy(), Y.data.numpy()
N = len(Y)
valid_indices = np.array( range(N) )
batch_indices = np.random.choice(valid_indices,size=M,replace=False)
batch_xs = torch.FloatTensor(X[batch_indices,:]).type(dtype)
batch_ys = torch.FloatTensor(Y[batch_indices]).type(dtype)
return Variable(batch_xs, requires_grad=False), Variable(batch_ys, requires_grad=False)
def poly_kernel_matrix( x,D ):
N = len(x)
Kern = np.zeros( (N,D+1) )
for n in range(N):
for d in range(D+1):
Kern[n,d] = x[n]**d;
return Kern
## data params
N=5 # data set size
Degree=4 # number dimensions/features
D_sgd = Degree+1
##
x_true = np.linspace(0,1,N) # the real data points
y = np.sin(2*np.pi*x_true)
y.shape = (N,1)
## TORCH
dtype = torch.FloatTensor
# dtype = torch.cuda.FloatTensor # Uncomment this to run on GPU
X_mdl = poly_kernel_matrix( x_true,Degree )
X_mdl = Variable(torch.FloatTensor(X_mdl).type(dtype), requires_grad=False)
y = Variable(torch.FloatTensor(y).type(dtype), requires_grad=False)
## SGD mdl
w_init = torch.zeros(D_sgd,1).type(dtype)
W = Variable(w_init, requires_grad=True)
M = 5 # mini-batch size
eta = 0.1 # step size
for i in range(500):
batch_xs, batch_ys = get_batch2(X_mdl,y,M,dtype)
# Forward pass: compute predicted y using operations on Variables
y_pred = batch_xs.mm(W)
# Compute and print loss using operations on Variables. Now loss is a Variable of shape (1,) and loss.data is a Tensor of shape (1,); loss.data[0] is a scalar value holding the loss.
loss = (1/N)*(y_pred - batch_ys).pow(2).sum()
# Use autograd to compute the backward pass. Now w will have gradients
loss.backward()
# Update weights using gradient descent; w1.data are Tensors,
# w.grad are Variables and w.grad.data are Tensors.
W.data -= eta * W.grad.data
# Manually zero the gradients after updating weights
W.grad.data.zero_()
#
c_sgd = W.data.numpy()
X_mdl = X_mdl.data.numpy()
y = y.data.numpy()
#
Xc_pinv = np.dot(X_mdl,c_sgd)
print('J(c_sgd) = ', (1/N)*(np.linalg.norm(y-Xc_pinv)**2) )
print('loss = ',loss.data[0])
der code läuft einwandfrei und obwohl mein get_batch2
Methode scheint wirklich dum/naiv, seine wahrscheinlich, weil ich bin neu auf pytorch, aber ich habe nicht einen guten Platz gefunden, wo Sie diskutieren, wie Sie Daten abrufen, die Chargen. Ich ging durch Ihren tutorials (http://pytorch.org/tutorials/beginner/pytorch_with_examples.html) und durch die Daten festgelegt (http://pytorch.org/tutorials/beginner/data_loading_tutorial.html) mit kein Glück. Die tutorials scheinen alle davon ausgehen, dass man bereits die batch-und batch-Größe am Anfang und fährt dann mit dem Zug mit, dass Sie Daten, ohne es zu ändern (speziell schauen http://pytorch.org/tutorials/beginner/pytorch_with_examples.html#pytorch-variables-and-autograd).
Also meine Frage ist brauche ich wirklich, um meine Daten wieder in numpy, so dass ich abholen können einige zufällige Stichprobe, und dann schalten Sie es zurück zu pytorch mit Variablen in der Lage sein Zug in Speicher? Gibt es keine Möglichkeit, an mini-batches, die mit der Fackel?
Sah ich ein paar Funktionen Taschenlampe bietet aber mit kein Glück:
#pdb.set_trace()
#valid_indices = torch.arange(0,N).numpy()
#valid_indices = np.array( range(N) )
#batch_indices = np.random.choice(valid_indices,size=M,replace=False)
#indices = torch.LongTensor(batch_indices)
#batch_xs, batch_ys = torch.index_select(X_mdl, 0, indices), torch.index_select(y, 0, indices)
#batch_xs,batch_ys = torch.index_select(X_mdl, 0, indices), torch.index_select(y, 0, indices)
obwohl ich den code zur Verfügung gestellt, funktioniert einwandfrei ich bin besorgt, dass es sich nicht um eine effiziente Umsetzung UND, wenn ich die Verwendung von GPUs, dass es eine weitere erhebliche verlangsamen (weil ich Schätze, Sie setzen Dinge in Erinnerung und dann Holen Sie Sie zurück zu setzen GPU wie das ist albern).
Implementiert habe ich eine neue die auf der Antwort basiert, die vorgeschlagen, dass die Verwendung torch.index_select()
:
def get_batch2(X,Y,M):
'''
get batch for pytorch model
'''
# TODO fix and make it nicer, there is pytorch forum question
#X,Y = X.data.numpy(), Y.data.numpy()
X,Y = X, Y
N = X.size()[0]
batch_indices = torch.LongTensor( np.random.randint(0,N+1,size=M) )
pdb.set_trace()
batch_xs = torch.index_select(X,0,batch_indices)
batch_ys = torch.index_select(Y,0,batch_indices)
return Variable(batch_xs, requires_grad=False), Variable(batch_ys, requires_grad=False)
jedoch, diese Fragen zu haben scheint, weil es nicht funktioniert, wenn X,Y
sind KEINE Variablen...das ist wirklich seltsam. Ich habe dies nur Hinzugefügt, um die pytorch forum: https://discuss.pytorch.org/t/how-to-get-mini-batches-in-pytorch-in-a-clean-and-efficient-way/10322
Jetzt, was ich bin kämpfen, ist mit dieser Arbeit für die gpu. Meine aktuelle version:
def get_batch2(X,Y,M,dtype):
'''
get batch for pytorch model
'''
# TODO fix and make it nicer, there is pytorch forum question
#X,Y = X.data.numpy(), Y.data.numpy()
X,Y = X, Y
N = X.size()[0]
if dtype == torch.cuda.FloatTensor:
batch_indices = torch.cuda.LongTensor( np.random.randint(0,N,size=M) )# without replacement
else:
batch_indices = torch.LongTensor( np.random.randint(0,N,size=M) ).type(dtype) # without replacement
pdb.set_trace()
batch_xs = torch.index_select(X,0,batch_indices)
batch_ys = torch.index_select(Y,0,batch_indices)
return Variable(batch_xs, requires_grad=False), Variable(batch_ys, requires_grad=False)
den Fehler:
RuntimeError: tried to construct a tensor from a int sequence, but found an item of type numpy.int64 at index (0)
Ich verstehe es nicht, muss ich wirklich zu tun haben:
ints = [ random.randint(0,N) for i i range(M)]
bekommen die ganzen zahlen?
Wäre es auch ideal, wenn die Daten für eine variable. Es scheint, dass es torch.index_select
funktioniert nicht für Variable
Typ data.
diese Liste von Integer-zahlen, was immer noch nicht funktioniert:
TypeError: torch.addmm received an invalid combination of arguments - got (int, torch.cuda.FloatTensor, int, torch.cuda.FloatTensor, torch.FloatTensor, out=torch.cuda.FloatTensor), but expected one of:
* (torch.cuda.FloatTensor source, torch.cuda.FloatTensor mat1, torch.cuda.FloatTensor mat2, *, torch.cuda.FloatTensor out)
* (torch.cuda.FloatTensor source, torch.cuda.sparse.FloatTensor mat1, torch.cuda.FloatTensor mat2, *, torch.cuda.FloatTensor out)
* (float beta, torch.cuda.FloatTensor source, torch.cuda.FloatTensor mat1, torch.cuda.FloatTensor mat2, *, torch.cuda.FloatTensor out)
* (torch.cuda.FloatTensor source, float alpha, torch.cuda.FloatTensor mat1, torch.cuda.FloatTensor mat2, *, torch.cuda.FloatTensor out)
* (float beta, torch.cuda.FloatTensor source, torch.cuda.sparse.FloatTensor mat1, torch.cuda.FloatTensor mat2, *, torch.cuda.FloatTensor out)
* (torch.cuda.FloatTensor source, float alpha, torch.cuda.sparse.FloatTensor mat1, torch.cuda.FloatTensor mat2, *, torch.cuda.FloatTensor out)
* (float beta, torch.cuda.FloatTensor source, float alpha, torch.cuda.FloatTensor mat1, torch.cuda.FloatTensor mat2, *, torch.cuda.FloatTensor out)
didn't match because some of the arguments have invalid types: (int, torch.cuda.FloatTensor, int, torch.cuda.FloatTensor, torch.FloatTensor, out=torch.cuda.FloatTensor)
* (float beta, torch.cuda.FloatTensor source, float alpha, torch.cuda.sparse.FloatTensor mat1, torch.cuda.FloatTensor mat2, *, torch.cuda.FloatTensor out)
didn't match because some of the arguments have invalid types: (int, torch.cuda.FloatTensor, int, torch.cuda.FloatTensor, torch.FloatTensor, out=torch.cuda.FloatTensor)
- auf der pytorch forum: discuss.pytorch.org/t/...
- nützlich Kommentar vielleicht: Stellen Sie sicher, rufen Sie
index_select
mit der gleichen Art von Argumenten, d.h. zwei Tensoren oder zwei Variablen. Wickeln Sie Ihrebatch_indices
in eine Variable oder nutzen Sie einfachX[batch_indices, :]
. - auch im Zusammenhang: discuss.pytorch.org/t/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verwenden Sie data loader.
Datensatz
Zuerst definieren Sie einen Datensatz. Mit Paketen können Sie Datensätze in
torchvision.datasets
oder verwenden SieImageFolder
dataset-Klasse, die entsprechend der Struktur des Imagenet.Verwandelt
Transformationen sind sehr nützlich für die Vorverarbeitung der geladenen Daten on-the-fly. Wenn Sie Bilder, die Sie verwenden müssen, die
ToTensor()
Transformation zum konvertieren von geladenen Bilder ausPIL
zutorch.tensor
. Mehr verwandelt werden können, verpackt in ein composit-Transformation wie folgt.Data Loader
Dann definieren Sie eine Daten-loader bereitet die nächste charge während der Ausbildung. Sie können die Anzahl der threads, die für das laden von Daten.
Für die Ausbildung, die Sie nur aufzählen, auf die Daten loader.
NumPy Zeug
Ja. Sie haben zu konvertieren
torch.tensor
zunumpy
mit.numpy()
Methode zu arbeiten. Wenn Sie mit der CUDA-Sie haben zum download der Daten von der GPU auf die CPU zuerst mit der.cpu()
- Methode vor dem Aufruf.numpy()
. Persönlich, kommen aus der MATLAB-hintergrund, ziehe ich es vor, die meiste Arbeit mit Fackel-tensor, dann Konvertierung der Daten in numpy nur für die Visualisierung. Auch Bedenken, dass die Fackel speichert Daten in einem Kanal-ersten-Modus, während numpy und PIL arbeiten mit channel-letzten. Dies bedeutet, dass Sie verwenden müssennp.rollaxis
bewegen Sie den Kanal-Achse auf die Letzte. Ein Beispiel-code ist unten.Protokollierung
Die beste Methode, die ich gefunden, um die Visualisierung der feature-Karten ist mit tensor-board. Ein code ist verfügbar unter yunjey/pytorch-tutorial.
np.transpose()
konvertieren von Kanal Erster Kanal letzter Darstellung.Wenn ich verstehen Sie Ihren code richtig, Ihre
get_batch2
- Funktion erscheint unter zufälligen mini-Chargen aus Ihrem Datenbestand ohne tracking die Indizes, die Sie verwendet haben, bereits in einer Epoche. Das Problem mit dieser Implementierung ist, dass es wahrscheinlich nicht machen, verwenden Sie alle Ihre Daten.Die Art, wie ich normalerweise tun, Batchverarbeitung, ist das erstellen einer zufälligen permutation aller möglichen Ecken mit
torch.randperm(N)
Schleife durch Sie in den Reihen. Zum Beispiel:Wenn Sie möchten, kopieren und einfügen, stellen Sie sicher, dass Sie definieren Ihre Optimierer -, Modell-und lossfunction irgendwo vor dem Beginn der Epoche Schleife.
In Bezug auf Ihre Fehler, versuchen Sie es mit
torch.from_numpy(np.random.randint(0,N,size=M)).long()
statttorch.LongTensor(np.random.randint(0,N,size=M))
. Ich bin mir nicht sicher, ob dies zu lösen, wird die Fehlermeldung, die Sie bekommen, aber es löst eine Zukunft Fehler.torch.randperm(N)
helfen?get_batch2()
.np.random.permutation()
so es einfach ist zu tun, wenn Sie tensorflow.batch_size
. Also, wenn Sie 10 Beispiele, und legen Sie die batch-Größe 3, Sie nicht zu nutzen, die letzten 1 Beispiel. Nur etwas bewusst zu seinNicht sicher, was Sie zu tun versuchten. W. r.t. die Dosierung, die Sie nicht haben, um zu konvertieren, um numpy. Sie konnte einfach index_select() , z.B.:
Den rest des Codes müsste geändert werden, sowie though.
Meine Vermutung, Sie würde gern ein get_batch-Funktion verbindet Ihren X-Tensoren und Y-Tensoren. So etwas wie:
Dann während des Trainings Sie wählen, z.B. max_batch_size = 32, Beispiele durch schneiden.
index_select()
benötigt die Daten, um nicht eine variable sein...warum?requires_grad=False
...wie spielt das eine Rolle?index_select()
vs-nur die Indizierung direktX[k1:k2,:]
? Wie, als würden wir einer gegen den anderen?Erstellen Sie eine Klasse, die eine Unterklasse von
torch.utils.data.Dataset
und übergeben es an einemtorch.utils.data.Dataloader
. Unten ist ein Beispiel für mein Projekt.Können Sie
torch.utils.data
vorausgesetzt, Sie haben geladen, die Daten aus dem Verzeichnis, in Zug-und test-numpy-arrays können Erben von
torch.utils.data.Dataset
Klasse zu erstellen, die das dataset-ObjektErstellen Sie dann das dataset-Objekt
Schließlich verwenden
DataLoader
zu erstellen Sie Ihre mini-batches