一、 函數解釋
clone()- 返回一個新的tensor,這個tensor與原始tensor的數據不共享一個內存(也就是說, 兩者不是同一個數據,修改一個另一個不會變)。
- requires_grad屬性與原始tensor相同,若requires_grad=True,計算梯度,但不會保留梯度,梯度會與原始tensor的梯度相加。
detach()- 返回一個新的tensor,這個tensor與原始tensor的數據共享一個內存(也就是說,兩者是同一個數據,修改原始tensor,new tensor也會變; 修改new tensor,原始tensor也會變)。
- require_grad設置為False(也就是網上說的從計算圖中剝除,不計算梯度)。
- 在下圖的detach()中 \(X \ne False\) 畫的也不是很准確,應該是不完全等於。其中\(X\)的取值有兩種可能(\(False\) or \(True\)),但new Tensor 只有一種可能,也就是False.

有一張表解釋的很清楚:

二、 實驗
# 對應clone的觀點1
a = torch.tensor([1.], dtype=torch.float32, requires_grad=True)
b = a.clone()
a.data *= 3
print("Tensor:", a)
print("New Tensor:", b)
Tensor: tensor([3.], requires_grad=True)
New Tensor: tensor([1.], grad_fn=<CloneBackward>)
# 對應clone的觀點二
a = torch.tensor([1.], dtype=torch.float32, requires_grad=True)
b = a.clone()
z = a**2 + b*2
z.backward()
print("Tensor requires_grad:", a.requires_grad)
print("Tensor requires_grad:", a.grad)
print("NewTensor requires_grad:", b.requires_grad)
print("NewTensor requires_grad:", b.grad)
輸出:
Tensor requires_grad: True
Tensor requires_grad: tensor([4.])
NewTensor requires_grad: True
NewTensor requires_grad: None
# 對應detach的觀點1
a = torch.tensor([1.], dtype=torch.float32, requires_grad=True)
b = a.detach()
a.data *= 3
print("Tensor", a)
print("New Tensor", b)
輸出:
Tensor: tensor([3.], requires_grad=True)
New Tensor: tensor([3.])
# 對應detach觀點2
a = torch.tensor([1.], dtype=torch.float32, requires_grad=True)
b = a.detach()
z = a**2 + b*2
z.backward()
print("Tensor requires_grad:", a.requires_grad)
print("Tensor requires_grad:", a.grad)
print("NewTensor requires_grad:", b.requires_grad)
print("NewTensor requires_grad:", b.grad)
輸出:
Tensor requires_grad: True
Tensor requires_grad: tensor([2.])
NewTensor requires_grad: False
NewTensor requires_grad: None
參考鏈接:
