pytorch_detach 네트워크 반전 차단 방식

detach


공식 문서에서 이 방법에 대해 이렇게 소개했다.

    detach = _add_docstr(_C._TensorBase.detach, r"""
    Returns a new Tensor, detached from the current graph.
    The result will never require gradient.
    .. note::
      Returned Tensor uses the same data tensor as the original one.
      In-place modifications on either of them will be seen, and may trigger
      errors in correctness checks.
    """)
현재 그림에서 분리된 새 Variable을 되돌려줍니다.
되돌아오는 Variable은 사다리가 필요하지 않습니다.
만약 detach의 Variable volatile=True에 의해 detach에서 나온 volatile도 True이다
또 하나의 주의사항, 즉 되돌아오는 Variable과 detach의 Variable가 같은 tensor를 가리키는 것

import torch
from torch.nn import init
t1 = torch.tensor([1., 2.],requires_grad=True)
t2 = torch.tensor([2., 3.],requires_grad=True)
v3 = t1 + t2
v3_detached = v3.detach()
v3_detached.data.add_(t1) #   v3_detached Variable  tensor  
print(v3, v3_detached)    # v3  tensor  
print(v3.requires_grad,v3_detached.requires_grad)
'''
tensor([4., 7.], grad_fn=<AddBackward0>) tensor([4., 7.])
True False
'''
pytorch에서 복사를 통해 위치를 차단하기 전에tensor를 통해 이 기능을 실현합니다.tensor에서 복사된 함수는 두 개입니다. 하나는 clone (), 다른 하나는copy_(),clone () 은 이전의tensor를 완전히 복제한 것과 같고 그의 사다리도 복제할 수 있으며 반대로 전파할 때 복제된 샘플과 결과는 등가이다. 간단하게 clone은 같은tensor와 다른 대명사,'='와 등가를 주었다는 것을 이해할 수 있다.그래서 새로운 분리된tensor를 생성하려면copy_().
그러나 이러한 조작에 대해pytorch에는 전문적인 함수인 detach()가 있다.
사용자가 직접 만든 노드는 leaf_node(그림의 abc 세 노드), 다른 변수에 의존하지 않고leaf_node는 in_를 진행할 수 없습니다.place 작업.루트 노드는 계산도의 최종 목표(예를 들어 그림 y)로 체인식 법칙을 통해 모든 노드가 루트 노드에 비해 사다리꼴 값을 계산할 수 있다.이 과정은 루트를 호출합니다.backward () 가 가능합니다.
따라서 detach가 하는 일은 변수를 다시 성명하고 원래 변수의 저장 위치를 가리키지만requires_grad는 false입니다.좀 더 깊은 이해는 계산도가 detach가 지나간 변수에서 끊어지고 leaf_가 되었다는 것이다node.나중에 다시 리퀴어_node는true로 설정되어도 사다리가 없습니다.

pytorch 사다리


(0.4 이후),tensor와variable가 합쳐져,tensor는grad,grad_fn 등 속성;
기본적으로 생성된 tensor,grad는 기본적으로 False입니다. 현재 tensor_grad가 None이면 앞으로 전파되지 않습니다. 만약에 다른 브랜치가grad를 가지고 있다면 다른 브랜치의grad만 전파됩니다

#  requires_grad = False Tensor
x = torch.ones(1)   # create a tensor with requires_grad=False (default)
print(x.requires_grad)
 # out: False
 
 #  Tensor, requires_grad = False
y = torch.ones(1)  # another tensor with requires_grad=False
 # both inputs have requires_grad=False. so does the output
z = x + y
 #  Tensor x,y,requires_grad=False. ,
 #  (operation)z=x+y z ,requires_grad=False
print(z.requires_grad)
 # out: False
 
 # then autograd won't track this computation. let's verify!
 #  autograd, 
# z.backward()
 # out: :RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
    
# now create a tensor with requires_grad=True
w = torch.ones(1, requires_grad=True)
print(w.requires_grad)
 # out: True
 
 # add to the previous result that has require_grad=False
 #  total Tensor w requires_grad=True, 。
total = w + z
# the total sum now requires grad!
total.requires_grad
# out: True
# autograd can compute the gradients as well
total.backward()
print(w.grad)
#out: tensor([ 1.])
# and no computation is wasted to compute gradients for x, y and z, which don't require grad
#  z,x,y requires_grad=False, 
z.grad == x.grad == y.grad == None
# True

nn.Paramter


import torch.nn.functional as F
# With square kernels and equal stride
filters = torch.randn(8,4,3,3)
weiths = torch.nn.Parameter(torch.randn(8,4,3,3))
inputs = torch.randn(1,4,5,5)
out = F.conv2d(inputs, weiths, stride=2,padding=1)
print(out.shape)
con2d = torch.nn.Conv2d(4,8,3,stride=2,padding=1)
out_2 = con2d(inputs)
print(out_2.shape)
추가: Pytorch-detach() 사용 방법

목적:


신경 네트워크의 훈련은 때때로 일부분의 네트워크 파라미터가 변하지 않고 그 중의 일부분의 파라미터만 조정하기를 희망할 수 있다.
또는 일부 지점 네트워크를 훈련시켜 그 사다리가 메인 네트워크의 사다리에 영향을 주지 않도록 한다.이때 우리는 detach () 함수를 사용하여 일부 지점의 역방향 전파를 차단해야 한다.

1 tensor.detach()


현재 계산도에서 분리된 새로운tensor를 되돌려줍니다.그러나 여전히 원 변수의 저장 위치를 가리키며, 다른 점은 리퀴스_grad는 false입니다.얻은 이tensir는 영원히 계산기의 사다리를 필요로 하지 않고grad를 가지고 있지 않다.
나중에 다시 리퀴어_grad는true로 설정되어 있으며, 사다리꼴grad도 가지고 있지 않습니다.이렇게 하면 우리는 이 새로운tensor를 계속 사용하여 계산을 할 것이다. 다음에 우리가 역방향 전파를 할 때, 이 호출된 detach () 의tensor는 멈추고 더 이상 앞으로 전파할 수 없다.
참고:
detach를 사용하여 되돌아오는 tensor는 원시적인 tensor와 같은 메모리입니다. 즉, 수정된 메모리도 따라서 바뀝니다.
예를 들어 정상적인 예는 다음과 같다.

import torch 
a = torch.tensor([1, 2, 3.], requires_grad=True)
print(a)
print(a.grad)
out = a.sigmoid()
 
out.sum().backward()
print(a.grad)
출력
tensor([1., 2., 3.], requires_grad=True)
None
tensor([0.1966, 0.1050, 0.0452])
1.1 detach () 를 사용하여 tensor를 분리하지만 이 tensor를 변경하지 않았을 때 backward () 에 영향을 주지 않습니다.

import torch 
a = torch.tensor([1, 2, 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
 
# detach(),c requires_grad False
c = out.detach()
print(c)
 
# c , backward()
out.sum().backward()
print(a.grad)
 
''' :
None
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward>)
tensor([0.7311, 0.8808, 0.9526])
tensor([0.1966, 0.1050, 0.0452])
'''
이상의 개인적인 경험으로 여러분께 참고가 되었으면 좋겠습니다. 또한 많은 응원 부탁드립니다.만약 잘못이 있거나 완전한 부분을 고려하지 않으신다면 아낌없이 가르침을 주시기 바랍니다.

좋은 웹페이지 즐겨찾기