• gradient freeze 시키고 작업할 때
      with torch.no_grad(): 
    
  • device setting
    device = "cuda" if torch.cuda.is_available() else "cpu"
    
  • tensor.norm (torch tensor instance 에 대해)
    text_features /= text_features.norm(dim=-1, keepdim=True)
    # dim = -1 ; 마지막 차원에 대해서 연산하는 것을 norm 연산을 하는 것을 의미함. 
      # i.e 3x3 matrix 라면, -> 각 행마다 하나의 값을 가지도록 연산 됨 
      # default 면, 모든 값에 대해 norm 연산을 해서 scalar 값을 얻게 됨
    # keepdim=True ; norm 연산 차원을 유지하게 됨 
      # 값은 norm 연산으로 하나가 돼되, dimension을 여전히 wrapping 할지말지를 결정함 
      # if keepdim=True , 3x3 -> [3,1]
      # if keepdim=False , 3x3 -> [3]
    
  • cpu().detach().numpy().astype(“float32”)
      query = text_features.detach().cpu().numpy().astype("float32") #preferred
      #OR 
      query = text_features.cpu().detach().numpy().astype("float32")
    
    • .cpu()
      • GPU 메모리에 올라가 있는 tensor를 CPU 메모리로 copy 하는 method
      • If this object is already in CPU memory and on the correct device, then no copy is performed and the original object is returned.
    • .detach()
      • “Returns a new Tensor, detached from the current graph. The result will never require gradient” (feat. Pytorch docs )
      • graph 에서 분리한 새로운 tensor를 return 해준다. pytorch는 tensor에서 이루어진 모든 연산을 추적하여 기록한다(graph). 이 연산 기록으로부터 도함수가 계산되고 역전파가 이루어진다.
      • detach()는 이 연산 기록으로부터 분리한 tensor를 반환해준다.
    • .numpy()
      • Returns self tensor as a Numpy ndarray.
        This tensor and the returned ndarray share the same underlying storage.
        Changes to self tensor will be reflected in the ndarray and vice verse

        tenfor를 numpy 로 변환하여 return한다.
        이 때, 기존 tensor variable과 새로운 ndarray variable은 동일한 저장공간을 공유하기 때문에 한 쪽에서 값을 변경하면 모두 반영된다.
      • cpu 에 올려져 있는 tensor만 .numpy() 를 사용할 수 있다.
    • .astype(“float32”)
      • 내 생각엔 tensor 에서 double 형이었든 그런 것을 “float32”로 명시적으로 바꿔주는 것임
      • 추가 (float32 vs float64)
        • A 32-bit float can exactly represent about 7 decimal digits of mantissa. Your number requires more, and therefore cannot be represented exactly.
          The mechanics of what happens are as follows:
          A 32-bit float has a 24-bit mantissa. Your number requires 27 bits to be represented exactly, so the last three bits are getting truncated (set to zero).
          The three lowest bits of your number are 0112; these are getting set to 0002. Observe that 0112 is 310.
        • A float32 only has 24 bits of significand precision, which is roughly seven digits (log10(2**24) = 7.22). You’re expecting it to store an 8-digit number exactly, which in general is impossible.
    • 순서가 중요하다! detach().cpu().numpy() 권장!
      .cpu().detach().numpy() 의 경우,
      cpu를 만드는 edge가 생성되지만, detach로 이 edge는 곧 없어진다.
      반면,
      .detach().cpu().numpy() 의 경우,
      detach() 로 먼저 requires_grad=False를 보장하기 때문에 사라질 edge 조차 생성하지 않는다.
      하지만 이는 되게 빠른 작업으로 virtually same 하다고 한다.
      출처

추가로 볼 것

  • https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html
  • https://towardsdatascience.com/pytorch-autograd-understanding-the-heart-of-pytorchs-magic-2686cd94ec95
  • https://www.youtube.com/watch?v=MswxJw-8PvE&feature=emb_title

Reference

  • https://byeongjo-kim.tistory.com/32