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
값이 존재해야 한다.
- Pytorch에서는 스칼라 값만
1번 -
중간 gradient
를[1,1]
로 지정해주고backward
진행- 2번 -
loss = Q[0]+Q[1]
이라는 스칼라로 지정해주고backward
진행loss
를L
이라고 했을 때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
일 때, 다음의 두 코드의 결과는?
loss.backward()
loss1.backward()
,loss2.backward()
⇒ 같다.
epoch 내 과정
- grad 초기화
- param에 grad 쌓임
- optim
- 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
앞으로의 방향
- 절반은 질문, 나머지 절반은 논문스터디
- 논문 추천 & 읽어보기 (별 부담 없이) or 코드 리뷰
- 분야마다 동향 느낌으로 정보 하나씩 듣기
- 구현해보기 (ex. YOLO → 웹캠으로)