PyTorch의 clone(), detach() 및 확장 상세 정보

clone () 과 detach () 비교
Torch는 속도를 높이기 위해 벡터나 행렬의 값이 같은 메모리를 가리키는데 이것은 Matlab와 다르다.오래된 tensor를 저장하려면 인용이 아닌 새로운 저장 주소를 열어야 합니다. clone () 으로 깊이 복사할 수 있습니다.
우선 clone () 작업 후의 데이터 형식 정의 변화를 출력합니다.
(1). 단순 인쇄 유형

import torch

a = torch.tensor(1.0, requires_grad=True)
b = a.clone()
c = a.detach()
a.data *= 3
b += 1

print(a) # tensor(3., requires_grad=True)
print(b)
print(c)

'''
 :
tensor(3., requires_grad=True)
tensor(2., grad_fn=<AddBackward0>)
tensor(3.) # detach() a 
'''
grad_fn=, clone 후의 반환 값은 중간 변수이기 때문에 사다리의 소거를 지원합니다.clone 조작은 어느 정도에identity-mapping 함수로 볼 수 있다.
detach () 작업 후의tensor는 원시tensor와 데이터 메모리를 공유합니다. 원시tensor가 계산도에서 수치가 역방향으로 전파되는 등 업데이트가 발생하면detach () 의tensor 값도 변경됩니다.
주의:pytorch에서 우리는 id가 같은지 아닌지를 직접 사용해서 텐서가 메모리를 공유하는지 판단하지 마십시오. 이것은 충분한 조건입니다. 왜냐하면 밑바닥에서 데이터 메모리를 공유할 수도 있지만 여전히 새로운 텐서, 예를 들어 detach () 입니다. 만약에 우리가 직접 id를 인쇄하면 다음과 같은 상황이 발생할 수 있습니다.

import torch as t
a = t.tensor([1.0,2.0], requires_grad=True)
b = a.detach()
#c[:] = a.detach()
print(id(a))
print(id(b))
#140568935450520
140570337203616
분명히 직접 출력된 id는 같지 않다. 우리는 간단한 값을 부여한 후에 데이터의 변화를 관찰하여 판단할 수 있다.
(2). clone () 의 사다리 회전
detach () 함수는 완전히 같은tensor를 되돌려줍니다. 낡은 tensor와 메모리를 공유하고 계산도에서 벗어나 사다리 계산에 연루되지 않습니다.
반면에 clone은 중간 변수를 충당하면 사다리를 원량에 전달하여 중첩되지만 그 자체는grad를 저장하지 않습니다. 즉, 값은 None입니다.

import torch
a = torch.tensor(1.0, requires_grad=True)
a_ = a.clone()
y = a**2
z = a ** 2+a_ * 3
y.backward()
print(a.grad) # 2
z.backward()
print(a_.grad)   # None.  variable, grad
print(a.grad) 
'''
 :
tensor(2.) 
None
tensor(7.) # 2*2+3=7
'''
torch를 사용합니다.clone () 에서 얻은 새로운tensor와 원래의 데이터는 더 이상 메모리를 공유하지 않지만 계산도에 남아 있습니다. clone 작업은 데이터 메모리를 공유하지 않는 동시에 사다리 전달과 중첩을 지원하기 때문에 신경 네트워크의 어떤 단원이 중복적으로 사용해야 하는 장면에 자주 사용됩니다.
보통 원tensor의requires_grad=True:
  • clone () 조작 후 tensor requires_grad=True
  • detach() 작업 후tensorrequires_grad=False.
  • 
    import torch
    torch.manual_seed(0)
    
    x= torch.tensor([1., 2.], requires_grad=True)
    clone_x = x.clone() 
    detach_x = x.detach()
    clone_detach_x = x.clone().detach() 
    
    f = torch.nn.Linear(2, 1)
    y = f(x)
    y.backward()
    
    print(x.grad)
    print(clone_x.requires_grad)
    print(clone_x.grad)
    print(detach_x.requires_grad)
    print(clone_detach_x.requires_grad)
    '''
     :
    tensor([-0.0053, 0.3793])
    True
    None
    False
    False
    '''
    
    또 다른 특이한 것은 원본 장량의 require_grad=False, clone 후 장량 require_grad=True, 이때 장량 회전 현상이 존재하지 않으며,clone 후의 장량 구도를 얻을 수 있습니다.
    다음과 같습니다.
    
    import torch
    a = torch.tensor(1.0)
    a_ = a.clone()
    a_.requires_grad_() #require_grad=True
    y = a_ ** 2
    y.backward()
    print(a.grad) # None
    print(a_.grad) 
    '''
     :
    None
    tensor(2.)
    '''
    
    양자의 차이를 이해한 후에 우리는 항상 다른 함수와 조합하여 사용하여 데이터 복사 후의 기타 수요를 실현한다.
    예를 들어 우리는view () 함수를 자주 사용하여tensor에 대해reshape 작업을 한다.되돌아오는 새 Tensor와 원본 Tensor는 서로 다른size가 있을 수 있지만 데이터를 공유하는 것입니다. 즉, 그 중 하나가 바뀌고 다른 것도 따라서 바뀝니다.
    주의해야 할 것은view가 되돌아오는 Tensor와 원본 Tensor는 데이터를 공유하지만 여전히 새로운 Tensor입니다. (Tensor는 데이터를 포함하는 것 외에 다른 속성이 있기 때문입니다.) 양자 id(메모리 주소)는 일치하지 않습니다.
    
    x = torch.rand(2, 2)
    y = x.view(4)
    x += 1
    print(x)
    print(y) #  1
    
    view () 는 단지 이 장량에 대한 관찰 각도를 바꾸었을 뿐 내부 데이터는 변하지 않았다.이때 진정한 새로운 복사본(즉 데이터 메모리를 공유하지 않음)으로 돌아가려면 어떻게 해야 합니까?Pytorch는 reshape () 를 제공하여 모양을 바꿀 수 있지만, 이 함수는 복사본으로 되돌아오는 것을 보장할 수 없기 때문에 사용을 추천하지 않습니다.먼저 clone으로 사본을 만들고 view를 사용하는 것을 추천합니다.여기 참조
    
    x = torch.rand(2, 2)
    x_cp = x.clone().view(4)
    x += 1
    print(id(x))
    print(id(x_cp))
    print(x)
    print(x_cp)
    '''
    140568935036464
    140568935035816
    tensor([[0.4963, 0.7682],
     [0.1320, 0.3074]])
    tensor([[1.4963, 1.7682, 1.1320, 1.3074]]) 
    '''
    
    또한 clone () 을 사용하면 계산도에 기록됩니다. 즉, 사다리가 복사본으로 전송될 때도 원본 Tensor로 전송됩니다전편에서 총결이 있다 .
    요약:
  • torch.detach () - 새로운tensor는 계산도에서 벗어나 사다리 계산에 연루되지 않습니다
  • torch.clone () - 새로운tensor는 중간 변수를 충당하여 계산도에 보존하고 사다리 계산(회전 중첩)에 참여하지만 일반적으로 자신의 사다리를 보존하지 않습니다.
    제자리 작업(in-place, such as resize_/resize_as_/set_/transpose_)위에서 두 가지를 실행하면 오류나 경고를 일으킬 수 있습니다.
  • 공유 데이터 메모리는 베이스 디자인으로 텐서의 id 주소를 직접 인쇄하여 판단할 수 없으며, 값을 부여하거나 연산 조작을 한 후 비교 데이터의 변화를 인쇄하여 판단해야 한다
  • 복제 작업은 실제 수요에 따라 결합하여 사용할 수 있다.
  • 공식 문서를 인용하면: 만약 당신이 in-placeoperation을 사용하고 오류를 보고하지 않았다면, 당신의 사다리 계산이 정확하다는 것을 확정할 수 있습니다.또한 가능한 한 in-place의 사용을 피해야 한다.
    y = x + y 같은 연산은 메모리를 새로 열고 y를 새 메모리로 가리킨다.우리는 Python이 가지고 있는 id 함수를 사용하여 검증할 수 있습니다. 만약 두 개의 실례의 ID가 같다면, 그것들이 대응하는 메모리 주소가 같습니다.
    PyTorch의 clone (), detach () 및 확장에 대한 자세한 내용은 여기 소개되어 있습니다. 더 많은 PyTorch의 clone (), detach () 및 확장에 관한 내용은 이전의 글을 검색하거나 아래의 관련 글을 계속 훑어보시기 바랍니다. 앞으로 많은 응원 부탁드립니다!

    좋은 웹페이지 즐겨찾기