Leaf Tensor, Non-Leaf Tensor

JunD·2025년 12월 8일
post-thumbnail
  • 딥러닝 모델링 과정에서 가중치를 직접 초기화하고 학습할 때 ValueError: can't optimize a non-leaf Tensor를 겪고,

  • 리프 텐서와 논리프 텐서에 대해 알아보고 에러 없이 가중치 초기화, 학습 파라미터에 추가하는 방법에 대해!



리프 텐서? 논리프 텐서?

리프 텐서(Leaf Tensor)

  • leaf란, 잎을 의미

  • 본래 의미와 비슷하게 리프 텐서는 가장 바깥쪽에 위치한. 즉, 최초의 입력값이다.

  • 유저가 직접 생성한 텐서거나,
    • ex) torch.rand or torch.empty
    • 단, requires_grad = False
  • nn.Parameter()로 선언한 가중치이다.
  • 특징

    • 다른 텐서로부터 연산된 값이 아닌 원본 가중치

    • 파이토치 연산그래프(DAG)의 Root에 위치한 노드

    • 최종 기울기 정보를 내부에 저장

      • 옵티마이저가 업데이트를 수행할 수 있도록!
    • 리프 텐서에 in-place를 수행하면 기존 데이터가 사라지는 문제(= history 파괴) 발생하여 기울기 계산 불가해짐

      • 기존 텐서가 requires_grad=True인 경우

  • 예시
    • 아래 두 코드는 모두 에러 발생

  • code_1
query=nn.Parameter(torch.empty(768,768)).to(device)
nn.init.xavier_uniform_(query)

Error_1

  • nn.Parameter 선언하여 리프 텐서 생성 이후 gpu에 올리기 위해 .to(device)를 사용하는경우, 복사본이 GPU에 올라가고 이 복사본 또한 연산의 결과물이므로non-leaf tensor가 되어 오휴 발생
  • code_2
query=torch.empty(768,768, requires_grad = True)
nn.init.xavier_uniform_(query)

Error_2

  • 기울기 옵션을 True로 설정하고 query 생성 시, in-place 과정에서 오류 발생
    • requires_grad = True를 사용하는 순간, 미분 엔진은 연산 과정의 모든 데이터를 기억하는데, in-place 연산은 원본을 덮어씌우기 때문에 원본이 사라지는 문제 발생하기 때문!

  • 적절한 가중치 초기화 방법
query=torch.empty(768,768, device=device)
nn.init.xavier_uniform_(query)
query = nn.Parameter(query)


논리프 텐서(Non-leaf Tensor)

  • 리프 텐서가 아닌 텐서

  • 특징

    • 다른 텐서로부터 연산을 통해 생성

      • 텐서 객체 내부에 grad_fn 속성을 갖고 있음
      • 해당 텐서를 만들어낸 연산의 종류가 grad_fn에 저장
        • 연산기록 이름
          +AddBackward
          *MulBackward
          matmul()MmBackward
          copyToCopyBackward
    • 기울기 전달의 통로

      • 역전파 과정에서 기울기를 전달하는 다리 역할
    • 업데이트 불가

      • 필자가 경험한 ValueError: can't optimize a non-leaf Tensor의 직접적인 이유로,
      • 옵티마이저는 오직 리프 텐서의 가중치만 업데이트하기 때문에 중간 연산 결과인 논리프 텐서는 업데이트 불가

profile
Data Scientist & Data Analyst

0개의 댓글