Почему градиенты pytorch являются массивом, а не вектором?

#python #pytorch

#python #pytorch

Вопрос:

Я пытаюсь вычислить точку градиентов одного и того же слоя двух разных эпох, но когда я использую print(model.layer1[0].weight.grad) его, он возвращается

 tensor([[[[-1.1855e-03, -3.7884e-03, -2.8973e-03, -2.8847e-03, -9.6510e-04],
          [-2.0213e-03, -4.4927e-03, -5.4852e-03, -6.6060e-03, -3.5726e-03],
          [ 7.4499e-04, -1.8440e-03, -5.0472e-03, -5.6322e-03, -1.9532e-03],
          [-4.5696e-04,  9.6445e-04, -1.4923e-03, -2.9467e-03, -1.4610e-03],
          [ 2.4987e-04,  2.2086e-03, -7.6576e-04, -2.7009e-03, -2.8571e-03]]],


        [[[ 2.1447e-03,  3.1090e-03,  6.8175e-03,  6.4778e-03,  3.0501e-03],
          [ 2.0214e-03,  3.9936e-03,  7.9528e-03,  6.0224e-03,  1.7545e-03],
          [ 3.8781e-03,  5.6659e-03,  6.6901e-03,  5.4041e-03,  7.8014e-04],
          [ 4.4273e-03,  3.4548e-03,  5.7185e-03,  4.1650e-03,  9.9067e-04],
          [ 4.6075e-03,  4.1176e-03,  6.8392e-03,  3.4005e-03,  1.0009e-03]]],


        [[[-3.8654e-04, -2.9567e-03, -6.1341e-03, -8.3991e-03, -8.2343e-03],
          [-2.9113e-03, -5.4605e-03, -6.3008e-03, -8.2075e-03, -9.6702e-03],
          [-1.5218e-03, -4.4105e-03, -5.5651e-03, -6.8926e-03, -6.6076e-03],
          [-6.0357e-04, -3.1118e-03, -4.4441e-03, -4.0519e-03, -3.9733e-03],
          [-2.8683e-04, -1.6281e-03, -4.2213e-03, -5.5304e-03, -5.0142e-03]]],


        [[[-3.7607e-04, -1.7234e-04, -1.4569e-03, -3.5825e-04,  1.4530e-03],
          [ 2.6226e-04,  8.5076e-04,  1.2195e-03,  2.7885e-03,  2.5953e-03],
          [-7.7404e-04,  1.0984e-03,  7.8208e-04,  5.1286e-03,  4.6842e-03],
          [-1.8183e-03,  8.9730e-04,  1.0955e-03,  4.9259e-03,  6.4677e-03],
          [ 1.1674e-03,  4.0651e-03,  4.5886e-03,  8.3678e-03,  8.9893e-03]]],
  

Это и есть градиенты? Если да, то почему они не являются векторными? Ниже приведена моя нейронная сеть

 class ConvNet(nn.Module):
    def __init__(self):
        super(ConvNet, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=5, stride=1, padding=2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=5, stride=1, padding=2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.drop_out = nn.Dropout()
        self.fc1 = nn.Linear(7 * 7 * 64, 1000)
        self.fc2 = nn.Linear(1000, 10)

    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = out.reshape(out.size(0), -1)
        out = self.drop_out(out)
        out = self.fc1(out)
        out = self.fc2(out)
        return out
  

Ниже приведен код того, как я обучаю и вычисляю градиенты

 model = ConvNet()
klisi=[]
# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

# Train the model
total_step = len(train_loader)
loss_list = []
acc_list = []
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # Run the forward pass
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss_list.append(loss.item())

        # Backprop and perform Adam optimisation
        optimizer.zero_grad()
        loss.backward()
        
        optimizer.step()

        # Track the accuracy
        total = labels.size(0)
        _, predicted = torch.max(outputs.data, 1)
        correct = (predicted == labels).sum().item()
        acc_list.append(correct / total)

        if (i   1) % 100 == 0:
            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}, Accuracy: {:.2f}%'
                  .format(epoch   1, num_epochs, i   1, total_step, loss.item(),
                          (correct / total) * 100))
    print(model.layer1[0].weight.grad)
    klisi.append(model.layer1[0].weight.grad)
    print(optimizer.param_groups[0]['lr'])
    optimizer.param_groups[0]['lr'] *= 0.9999
  

Комментарии:

1. Пожалуйста, не включайте изображения в свой вопрос — можете ли вы скопировать и вставить текст и включить его в свой вопрос?

2. хорошо, я отредактирую его

3. Покажите код, который вы используете для вычисления градиентов. torch обычно накапливает градиент, поэтому, если вы вычисляете градиент относительно двух выходных данных (две разные эпохи), значения в .grad будут суммой двух градиентов.

4. Я использую ‘model. layer1[0].weight.grad’ для возврата градиентов

5. Почему вы удивлены? Рассматриваемый слой — Conv2D, веса которого равны 3D — так что градиент также является 3D-тензором.