게이트를 꺼내 보니 망각 게이트가 안 움직였다
1편에서 글자 하나를 바꿔 보니 은닉 상태의 차이가 네 자 만에 절반으로 줄었다. 게이트가 있는 LSTM 도 GRU 도 게이트 없는 RNN 과 거의 같은 속도였다. 게이트가 붙어 있는데 왜 같은지 보려면 게이트를 직접 꺼내야 한다.
LSTM 한 걸음
RNN 은 상태를 통째로 갈아 치운다. LSTM 은 상태를 두 개로 나눠서, 셀 상태
c 는 조금씩만 고치고 은닉 상태 h 는 거기서 필요한 만큼 꺼내 쓴다.
고치는 양을 정하는 것이 게이트다.
z = W_ih @ x + b_ih + W_hh @ h + b_hh # 한 번에 네 덩어리
i = sigmoid(z[0:H]) # 입력 게이트 - 새 것을 얼마나 넣나
f = sigmoid(z[H:2H]) # 망각 게이트 - 옛 것을 얼마나 남기나
g = tanh(z[2H:3H]) # 후보 - 넣을 내용 자체
o = sigmoid(z[3H:4H]) # 출력 게이트 - 셀에서 얼마나 꺼내 보이나
c = f * c + i * g
h = o * tanh(c)
i, f, o 는 sigmoid 라 0 과 1 사이다. 0 이면 잠그고 1 이면 연다.
c = f * c + i * g 한 줄이 핵심이다. 기울기가 뒤로 갈 때 걸음마다 f 가
곱해지므로, 얼마나 뒤까지 기억하느냐는 f 가 정한다 - 적어도 이론상은.
nn.LSTM 은 h 만 돌려주고 게이트는 안 준다. 그래서 학습된 가중치로 위 줄을
손으로 돌렸고, 파이토치가 낸 h 와 최대 6.85e-07 차이로 같다. 아래 숫자는
전부 그렇게 꺼낸 것이다.
게이트 값을 꺼내면
1편에서 쓴 것과 같은 800걸음 LSTM 에, 검증 데이터 32줄 x 128자를 넣고 유닛
325개의 게이트 값을 다 모으면 1,331,200 개가 나온다.
평균 5% 25% 50% 75% 95%
입력 i 0.661 0.294 0.515 0.684 0.828 0.946
망각 f 0.495 0.081 0.258 0.491 0.730 0.922
출력 o 0.587 0.178 0.392 0.597 0.798 0.947
망각 게이트 평균이 0.495 다. 파이토치는 바이어스를 0 에서 시작하므로
학습 전 망각 게이트는 sigmoid(0) = 0.5 다. 800걸음을 돌고 나서도 그 자리에서
거의 안 움직였다.
긴 기억을 맡은 유닛이 없다
평균이 0.5 라도 어떤 유닛은 0.95 로 오래 붙들고 어떤 유닛은 0.1 로 바로 버리는 식이면, 서로 다른 시간 규모를 나눠 맡은 셈이 된다. 흔히 그렇게 설명한다. 유닛별로 나눠 보면
유닛 325개의 평균 망각 게이트
최소 0.307 5% 0.377 중앙 0.494 95% 0.622 최대 0.793
그 값이 뜻하는 반감기 (자)
최소 0.59 중앙 0.98 최대 2.99
325개 전부가 0.31 에서 0.79 사이에 들어간다. 반감기로 옮기면 제일 오래
붙드는 유닛도 3 자이고, 절반이 넘는 172 개는 초기값 0.5 아래다. 열 자
이상 붙드는 유닛은 하나도 없다.
시간 규모를 나눠 맡은 게 아니라, 다 같이 짧게 잊는다.
망각 게이트가 전부는 아니다
그런데 1편에서 잰 상태 차이의 반감기는 네 자였다. 유닛별 반감기 중앙값
0.98 자와 네 배가 어긋난다.
c = f * c + i * g 를 다시 보면 이유가 보인다. 교란이 f 로만 줄어드는 게
아니다. h 가 달라지면 다음 걸음의 i 와 g 도 달라지고, 그 차이가 셀에 다시
들어온다. 그러니까 잊는 경로 말고 되돌아오는 경로가 있다.
갈라 본다. 교란 직후의 셀 차이를 그 뒤로 f 만 곱해 굴린 것과, 실제로 두 글을
끝까지 돌려 잰 것을 나란히 놓으면
뒤로 실제 차이 망각 게이트로만
1 0.711 0.574
4 0.337 0.124
8 0.144 0.022
16 0.041 0.003
32 0.0069 6.48e-04
반감기가 실제 4 자, 망각 게이트로만 굴리면 3 자다. 32자 뒤에는 실제가
11배 남아 있다.
망각 게이트는 잊는 속도의 일부만 정한다. 나머지는 매 걸음 입력 쪽으로 되돌아 들어오는 몫이고, 이게 기억을 게이트가 말하는 것보다 오래 끌고 간다.
게이트가 글자에 반응한다
게이트 값은 고정된 숫자가 아니라 x 와 h 로 매 걸음 계산된다. 그러니 글자에
따라 달라져야 한다. 자리 4,096 개를 글자로 갈라 망각 게이트 평균을 내면
띄어쓰기 0.4623 (자리 865개)
개행 0.4597 (자리 105개)
나머지 0.5057 (자리 3,126개)
띄어쓰기와 개행에서 0.05 쯤 더 닫는다. 단어가 끝나는 자리에서 조금 더
버린다는 뜻이다. 큰 차이는 아니지만 방향은 뚜렷하다 - 경계에서 비운다.
남는 것
여기 숫자는 800걸음 학습한 모형이다. 7편에서 보듯 그 지점이 검증 손실의 바닥 인데, 더 오래 돌리면 게이트가 어디로 가는지는 안 봤다.
GRU 도 안 열었다. 게이트가 둘뿐이고 셀 상태가 따로 없는데 1편에서 잊는 속도가 LSTM 과 거의 같았다. 다음 편이 그것이다.
그리고 “긴 기억을 맡은 유닛이 없다” 는 이 코퍼스와 이 과제에 붙은 말이다. 8편에서 망각 바이어스를 열면 도달이 문맥 전체로 가지만 손실은 나빠졌다. 긴 기억이 필요한 과제였다면 학습이 게이트를 다른 데로 데려갔을 것이다.
그래서
- LSTM 한 걸음은
c = f·c + i·g와h = o·tanh(c)두 줄이고,i·f·o는 전부 0 과 1 사이의 문이다 nn.LSTM은 게이트를 안 주므로 가중치로 손으로 돌렸다. 파이토치와 최대6.85e-07차이다- 망각 게이트 평균이
0.495로 초기값sigmoid(0) = 0.5에서 거의 안 움직였다 - 유닛 325개의 평균 망각 게이트가 전부
0.307~0.793안이다. 반감기로는 최대3자이고 열 자 넘는 유닛은 없다. 시간 규모를 나눠 맡지 않았다 - 그런데 실제 상태는 반감기
4자로 더 오래 간다. 32자 뒤에 망각 게이트만 굴린 것의11배다 - 차이가 입력 쪽으로 되돌아 들어온다 - 게이트는 글자에 반응한다. 띄어쓰기
0.4623, 개행0.4597, 나머지0.5057로 경계에서 조금 더 버린다
Comments