it-swarm.com.de

Wie funktioniert die "Ansicht" -Methode in PyTorch?

Ich bin verwirrt über die Methode view() im folgenden Codeausschnitt.

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool  = nn.MaxPool2d(2,2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1   = nn.Linear(16*5*5, 120)
        self.fc2   = nn.Linear(120, 84)
        self.fc3   = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16*5*5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

net = Net()

Meine Verwirrung betrifft die folgende Zeile.

x = x.view(-1, 16*5*5)

Was macht die Funktion tensor.view()? Ich habe seine Verwendung an vielen Orten gesehen, aber ich kann nicht verstehen, wie es seine Parameter interpretiert.

Was passiert, wenn ich der Funktion view() negative Werte als Parameter gebe? Was passiert zum Beispiel, wenn ich tensor_variable.view(1, 1, -1) aufrufe?

Kann jemand das Hauptprinzip der Funktion view() anhand einiger Beispiele erläutern?

130
Wasi Ahmad

Die Ansichtsfunktion soll den Tensor umformen.

Angenommen, Sie haben einen Tensor

import torch
a = torch.range(1, 16)

a ist ein Tensor mit 16 Elementen von 1 bis 16 (enthalten). Wenn Sie diesen Tensor in einen 4 x 4 -Tensor umformen möchten, können Sie ihn verwenden

a = a.view(4, 4)

Nun wird a ein 4 x 4 Tensor sein. Beachten Sie, dass nach der Umformung die Gesamtzahl der Elemente gleich bleiben muss. Den Tensor a in einen 3 x 5 Tensor umzuformen, wäre nicht angebracht.

Was bedeutet der Parameter -1?

Wenn Sie in einer Situation nicht wissen, wie viele Zeilen Sie möchten, sich aber der Anzahl der Spalten sicher sind, können Sie dies mit -1 angeben. ( Beachten Sie, dass Sie dies auf Tensoren mit mehr Dimensionen ausweiten können. Nur einer der Achsenwerte kann -1 sein.) Auf diese Weise können Sie der Bibliothek mitteilen: "Geben Sie mir einen Tensor mit diesen vielen Spalten und Sie berechnen die entsprechende Anzahl von Zeilen, die erforderlich sind, um dies zu erreichen".

Dies ist im oben angegebenen neuronalen Netzwerkcode zu sehen. Nach der Zeile x = self.pool(F.relu(self.conv2(x))) in der Vorwärtsfunktion haben Sie eine 16-Tiefen-Feature-Map. Sie müssen diese reduzieren, um die vollständig verbundene Ebene zu erhalten. Sie weisen pytorch an, den erhaltenen Tensor in eine bestimmte Anzahl von Spalten umzuformen und die Anzahl der Zeilen selbst zu bestimmen.

view zeichnet eine Ähnlichkeit zwischen numpy und pytorch und ähnelt der Funktion numpy's reshape .

183
Kashyap

Lassen Sie uns einige Beispiele machen, von einfacher bis schwieriger.

  1. Die view -Methode gibt einen Tensor mit denselben Daten zurück wie der self -Tensor (was bedeutet, dass der zurückgegebene Tensor dieselbe Anzahl von Elementen hat), aber mit einer anderen Form. Zum Beispiel:

    a = torch.arange(1, 17)  # a's shape is (16,)
    
    a.view(4, 4) # output below
      1   2   3   4
      5   6   7   8
      9  10  11  12
     13  14  15  16
    [torch.FloatTensor of size 4x4]
    
    a.view(2, 2, 4) # output below
    (0 ,.,.) = 
    1   2   3   4
    5   6   7   8
    
    (1 ,.,.) = 
     9  10  11  12
    13  14  15  16
    [torch.FloatTensor of size 2x2x4]
    
  2. Angenommen, -1 ist nicht einer der Parameter, wenn Sie sie miteinander multiplizieren, muss das Ergebnis gleich der Anzahl der Elemente im Tensor sein. Wenn Sie: a.view(3, 3) ausführen, wird RuntimeError ausgelöst, da die Form (3 x 3) für die Eingabe mit 16 Elementen ungültig ist. Mit anderen Worten: 3 x 3 entspricht nicht 16, sondern 9.

  3. Sie können -1 als einen der Parameter verwenden, die Sie an die Funktion übergeben, jedoch nur einmal. Alles, was passiert, ist, dass die Methode die Berechnung für Sie durchführt, wie diese Dimension gefüllt werden soll. Zum Beispiel entspricht a.view(2, -1, 4)a.view(2, 2, 4). [16/(2 x 4) = 2]

  4. Beachten Sie, dass der zurückgegebene Tensor dieselben Daten hat. Wenn Sie in der "Ansicht" eine Änderung vornehmen, ändern Sie die Daten des ursprünglichen Tensors:

    b = a.view(4, 4)
    b[0, 2] = 2
    a[2] == 3.0
    False
    
  5. Nun zu einem komplexeren Anwendungsfall. Die Dokumentation besagt, dass jede neue Ansichtsdimension entweder ein Unterraum einer ursprünglichen Dimension sein muss oder nur span d, d + 1, ..., d + k die die folgende zusammenhängende Bedingung erfüllen, die für alle i = 0, ..., k - 1, [i] = Schritt [i + 1] x Größe [i + 1] . Andernfalls muss contiguous() aufgerufen werden, bevor der Tensor angezeigt werden kann. Zum Beispiel:

    a = torch.Rand(5, 4, 3, 2) # size (5, 4, 3, 2)
    a_t = a.permute(0, 2, 3, 1) # size (5, 3, 2, 4)
    
    # The commented line below will raise a RuntimeError, because one dimension
    # spans across two contiguous subspaces
    # a_t.view(-1, 4)
    
    # instead do:
    a_t.contiguous().view(-1, 4)
    
    # To see why the first one does not work and the second does,
    # compare a.stride() and a_t.stride()
    a.stride() # (24, 6, 2, 1)
    a_t.stride() # (24, 2, 1, 6)
    

    Beachten Sie, dass für a_t Schritt [0]! = Schritt [1] x Größe [1] seit 24! = 2 x 3

25
Jadiel de Armas

Was bedeutet der Parameter -1?

Sie können -1 als dynamische Anzahl von Parametern oder "irgendetwas" lesen. Aus diesem Grund kann es in view() nur einen Parameter -1 geben.

Wenn Sie x.view(-1,1) fragen, wird die Tensorform [anything, 1] abhängig von der Anzahl der Elemente in x ausgegeben. Zum Beispiel:

import torch
x = torch.tensor([1, 2, 3, 4])
print(x,x.shape)
print("...")
print(x.view(-1,1), x.view(-1,1).shape)
print(x.view(1,-1), x.view(1,-1).shape)

Wird ausgeben:

tensor([1, 2, 3, 4]) torch.Size([4])
...
tensor([[1],
        [2],
        [3],
        [4]]) torch.Size([4, 1])
tensor([[1, 2, 3, 4]]) torch.Size([1, 4])
1
prosti

Ich habe herausgefunden, dass x.view(-1, 16 * 5 * 5) äquivalent zu x.flatten(1) ist, wobei der Parameter 1 angibt, dass der Abflachungsprozess ab der 1. Dimension beginnt (nicht abflachen der Bemusterungsdimension) semantisch klarer und einfacher zu bedienen, daher bevorzuge ich flatten().

1
FENGSHI ZHENG

weights.reshape(a, b) gibt einen neuen Tensor mit den gleichen Daten wie die Gewichte mit der Größe (a, b) zurück, während die Daten in einen anderen Teil des Speichers kopiert werden.

weights.resize_(a, b) gibt den gleichen Tensor mit einer anderen Form zurück. Wenn die neue Form jedoch weniger Elemente als der ursprüngliche Tensor enthält, werden einige Elemente aus dem Tensor entfernt (jedoch nicht aus dem Speicher). Wenn die neue Form mehr Elemente als der ursprüngliche Tensor enthält, werden neue Elemente im Speicher nicht initialisiert.

weights.view(a, b) gibt einen neuen Tensor mit denselben Daten wie die Gewichte mit der Größe (a, b) zurück

0
Jibin Mathew