Tôi không tìm thấy mã gốc trên trang web PyTorch nữa.
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)
Vấn đề với đoạn mã trên không có chức năng nào dựa trên những gì để tính toán độ dốc. Điều này có nghĩa là chúng ta không biết có bao nhiêu tham số (đối số mà hàm nhận) và thứ nguyên của tham số.
Để hiểu đầy đủ điều này, tôi đã tạo một ví dụ gần với bản gốc:
Ví dụ 1:
a = torch.tensor([1.0, 2.0, 3.0], requires_grad = True)
b = torch.tensor([3.0, 4.0, 5.0], requires_grad = True)
c = torch.tensor([6.0, 7.0, 8.0], requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients,retain_graph=True)
print(a.grad) # tensor([3.0000e-01, 3.0000e+00, 3.0000e-04])
print(b.grad) # tensor([1.2000e+00, 1.6000e+01, 2.0000e-03])
print(c.grad) # tensor([1.6667e-02, 1.4286e-01, 1.2500e-05])
Tôi giả sử hàm của chúng ta là y=3*a + 2*b*b + torch.log(c)
và các tham số là tensors với ba phần tử bên trong.
Bạn có thể nghĩ gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
như thế này là bộ tích lũy.
Như bạn có thể nghe thấy hệ thống tính toán tự động của PyTorch tương đương với sản phẩm Jacobian.
Trong trường hợp bạn có một chức năng, như chúng tôi đã làm:
y=3*a + 2*b*b + torch.log(c)
Jacobian sẽ là [3, 4*b, 1/c]
. Tuy nhiên, Jacobian này không phải là cách PyTorch đang thực hiện để tính toán độ dốc tại một số điểm nhất định.
PyTorch sử dụng chế độ phân biệt tự động chuyển tiếp và lùi (AD) song song với nhau.
Không có toán học biểu tượng liên quan và không có phân biệt số.
Sự khác biệt về số sẽ là để tính toán δy/δb
, cho b=1
và b=1+ε
ở đâu ε là nhỏ.
Nếu bạn không sử dụng gradient trong y.backward()
:
Ví dụ 2
a = torch.tensor(0.1, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(0.1, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
y.backward()
print(a.grad) # tensor(3.)
print(b.grad) # tensor(4.)
print(c.grad) # tensor(10.)
Bạn sẽ đơn giản nhận được kết quả tại một điểm, dựa vào cách bạn thiết của bạn a
, b
, c
tensors ban đầu.
Hãy cẩn thận như thế nào bạn khởi tạo của bạn a
, b
, c
:
Ví dụ 3:
a = torch.empty(1, requires_grad = True, pin_memory=True)
b = torch.empty(1, requires_grad = True, pin_memory=True)
c = torch.empty(1, requires_grad = True, pin_memory=True)
y=3*a + 2*b*b + torch.log(c)
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(a.grad) # tensor([3.3003])
print(b.grad) # tensor([0.])
print(c.grad) # tensor([inf])
Nếu bạn sử dụng torch.empty()
và không sử dụng, pin_memory=True
bạn có thể có kết quả khác nhau mỗi lần.
Ngoài ra, lưu ý gradient giống như bộ tích lũy, do đó, không chúng khi cần thiết.
Ví dụ 4:
a = torch.tensor(1.0, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(1.0, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
y.backward(retain_graph=True)
y.backward()
print(a.grad) # tensor(6.)
print(b.grad) # tensor(8.)
print(c.grad) # tensor(2.)
Một số mẹo cuối cùng về các thuật ngữ PyTorch sử dụng:
PyTorch tạo một đồ thị tính toán động khi tính toán độ dốc trong chuyển tiếp. Nó trông giống như một cái cây.
Vì vậy, bạn sẽ thường nghe nói lá của cây này là tensor đầu vào và gốc là tensor đầu ra .
Gradients được tính bằng cách truy tìm biểu đồ từ gốc đến lá và nhân mọi gradient theo cách sử dụng quy tắc chuỗi . Phép nhân này xảy ra trong quá trình chuyền ngược.