Home [Week 02] 멘토링
Post
Cancel

[Week 02] 멘토링

Gather

  • 원하는 index의 값을 가져오기 위함이다.
  • matrix가 sparse한 경우에, training 내부에서 들어오는 data의 shpae를 맞춰주는 것이 병렬화에 편하기 때문에 사용한다.
  • 모델의 내부보다 후처리 할 때 더 많이 쓰는 것 같다.
    ⇒ 하지만 대체제가 존재한다. (ex. index masking 하면 비슷한 효과)


Q.backward(gradient=…) 어디에서 쓸까?

  • loss에 backward를 하면 모든 param 마다 gradient가 달린다.

  • 여기에서 gradient를 초기화하지 않고 backward 한 번 더 하면 학습의 방향이 잘못 될 수 있다.
    zero_grad() 안하면 대참사가 일어날 수 있다.

  • loss는 vector가 아니고 scalar 값이다.
    loss.backward() 함수는 scalar 값에 backward가 적용되므로 오류가 발생하지 않는다.

  • 하지만, Q.backward() vector/tensor에 backward를 적용하면 오류가 발생한다.
    • loss를 scalar 값이라고 정해놓았기 때문인 것 같다.
    • 따라서 scalar인 성분만 떼어서 Q[0].backward() 로 backward를 적용하면 오류가 발생하지 않는다.
  • vector/tensor인 경우, scalar 값이 아니기 때문에 최종 loss로 생각하지 않고, backprop 중간의 값이라고 생각한다. 따라서 chain rule에 의해 앞에서 값이 전달되어 온다는 것을 나타내기 위해 Q.backward(gradient=external_gradient)로 gradient를 지정해 주는 것 같다.

  • 모델이 커서 backprop 중 중간에서 멈춘 다음 다시 이어서 계산할 때나 쓰지 않을까 싶다.


backward 추가 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import torch

# 1번
a = torch.tensor([2., 3.], requires_grad=True)
b = torch.tensor([6., 4.], requires_grad=True)
Q = 3*a**3 - b**2
external_grad = torch.tensor([1., 1.])
Q.backward(gradient=external_grad)
print('a.grad',a.grad)
print('b.grad',b.grad)

# 2번
a.grad = None
b.grad = None
Q = 3*a**3 - b**2
loss = Q.sum()
loss.backward()
print('a.grad',a.grad)
print('b.grad',b.grad)

# 3번
a.grad = None
b.grad = None
Q = 3*a**3 - b**2
Q[0].backward(retain_graph=True)
Q[1].backward(retain_graph=True)
print('a.grad',a.grad)
print('b.grad',b.grad)
  • Q는 스칼라 값이 아닌 벡터이다.
    • Pytorch에서는 스칼라 값만 loss로 인정해서 backward가 가능하다.
    • 벡터에서 backward 함수를 이용하기 위해서는 loss에서 backpropagation해서 온 중간gradient 값이 존재해야 한다.
  • 1번 - 중간 gradient[1,1]로 지정해주고 backward 진행

  • 2번 - loss = Q[0]+Q[1]이라는 스칼라로 지정해주고 backward 진행
    • lossL이라고 했을 때 dL/dQ1 = 1, dL/dQ2 = 1이므로 1번과 동일한 결과를 얻는다.
  • 3번 - Q[0], Q[1] 각각에 backward 진행
    • loss.backward()Q[0].backward(), Q[1].backward()의 결과가 같기에 1번과 동일한 결과를 얻는다.


loss에 대해서

loss = loss1 + loss2일 때, 다음의 두 코드의 결과는?

  1. loss.backward()
  2. loss1.backward(), loss2.backward()

⇒ 같다.

epoch 내 과정

  1. grad 초기화
  2. param에 grad 쌓임
  3. optim
  4. param update
  • gradient clipping
    • gradient의 norm(크기)을 어느정도 이하로 제한해두기 위함이다.
    • loss backprop 시 gradient가 쌓여 매우 커질 수 있기 때문이다.
  • freeze
    • freeze 시키고 싶은 것에만 freeze 할 수 있다.
    • freeze 대신, freeze 시키고 싶은 것의 grad를 0으로 설정하면 update가 되지 않아 같은 동작을 하게 된다.

      1
      2
      3
      
        loss.backward()
        a.grad = 0.0
        optim.step()
      
    • 이는 $a = a-\text{lr}*\text{grad}$ 이기 때문이다.
    • 다음과 같이 코드를 작성하면 0.1 정도만 학습되게끔 지정이 가능하다.

      1
      
        a.grad *= 0.1
      

    ⇒ 이렇게 customizing 할 수 있다는 것이 PyTorch의 장점이다.


기타

  • prefetch - loader 성능이 매우 좋아짐
  • TensorBoard
  • TensorFlow는 배포 시에 good


앞으로의 방향

  • 절반은 질문, 나머지 절반은 논문스터디
    1. 논문 추천 & 읽어보기 (별 부담 없이) or 코드 리뷰
    2. 분야마다 동향 느낌으로 정보 하나씩 듣기
    3. 구현해보기 (ex. YOLO → 웹캠으로)
This post is licensed under CC BY 4.0 by the author.

[Week 02 / Day 007] 학습 기록

[Week 02 / Day 008] 학습 기록