ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [cs231n] 6강 신경망 훈련하기 (3/4, 배치 정규화와 학습 과정 베이비시팅 (batch normalization & learning process babysitting))
    AI 2021. 3. 11. 10:48

    이제 이것과 연관된 아이디어에 대해서 얘기해 보죠. 이 아이디어는 활성을 우리가 원하는 가우시안 범위로 유지하고 싶다는 겁니다.

    우리가 배치 정규화라고 부르는 것 뒤에 있는 이 아이디어는, 오케이, 우리는 단위 가우시안 활성을 원한다는 것입니다. 그러게 되도록 만들어보죠. 어떻게 그럴 수 있죠? 어떤 계층의 활성 배치를 생각해 보죠. 이제 모든 활성이 나오죠. 만약 우리가 이걸 단위 가우시안으로 만들고 싶으면, 사실 경험적으로 이것을 할 수 있습니다. 우리는 현재 배치의 평균과 분산을 취해서 이것으로 정규화할 수 있습니다. 가중치 초기화 대신, 우리는 이것을 훈련시작할 때 설정할 수 있죠. 그걸 좋은 위치에 놓기 위해서요. 그럼 우리는 단위 가우시안을 계층마다 가질 수 있죠. 바라건데, 훈련중에도 이것이 계속 유지될 것입니다. 이제 우리는 명시적으로 망 전체의 모든 순방향 전달에 대해서도 이렇게 되도록 할 겁니다. 우리는 이것이 기능적으로 발생하도록 할텐데, 각각의 뉴런의 평균과 분산을 정규화해서 하는거죠. 우리는 그것으로 들어오는 모든 입력을 보고 그 배치의 평균과 분산을 계산하고 그것으로 정규화하는 것이죠. 이건 그냥 미분할 수 있는 함수입니다. 우리의 평균과 분산을 상수로 가지면, 이건 그냥 우리가 미분하고 이것을 통해 역전파할 수 있는 일련의 컴퓨터 연산이죠.

    앞서서 얘기한 것 처럼, 우리의 입력 데이타를 보면... 이것을 이렇게 생각할 수 있죠. 현재 배치에 N개의 훈련 예제가 있고, 각각의 배치는 차원 D가 있고, 각각의 차원에 대해 우리는 경험적 평균과 분산을 독립적으로 계산할 겁니다. 각각은 사실 피쳐 (feature) 원소들이죠. 이것을 우리의 배치, 즉 우리가 가진 현재 미니 배치에 대해서 계산하고 이것으로 정규화합니다.

    이건 보통 완전 연결 계층이나 합성곱 계층 뒤에 들어갑니다. 이 계층에서 w를 곱할거고 이걸 반복하게 되는데, 각각에 대한 이 안좋은 스케일링 (scaling) 영향이 생기죠. 그래서 이건 사실 이 영향을 되돌리는 (undo) 겁니다. 우리는 각 뉴런, 각 활성에 연결된 입력으로 곱하는 거라서, 우리는 이것을 같은 방식으로 완전 연결과 합성곱 계층들에 적용할 수 있고, 유일한 차이점은 합성곱 계층에서는 모든 훈련 예제에 대해서, 각각의 피쳐 (feature) 차원에 대해서 독립적으로 정규화하고 싶지 않다는 것이죠. 우리는 모든 피쳐 차원과 활성 지도에 있는 모든 공간 위치에 대해서, 뿐만 아니라 모든 훈련 예제에 걸쳐서 정규화를 하고 싶은 겁니다. 이렇게 하는 이유는 합성곱 속성을 따르고 (obey) 싶기 때문이죠. 그리고 가까이에 있는 위치도 같은 방식으로 정규화하고 싶기 때문입니다. 합성곱 계층에 대해서는, 우리가 가진 활성 지도마다 하나의 평균과 하나의 표준 편차가 있고, 배치에 있는 모든 예제에 대해서 이것으로 정규화할 겁니다. 이 세부 사항은 2015년에 나온 이 논문에 자세히 설명되어 있습니다. 실제에서 많이 사용하고 싶은 아주 유용한 기법입니다. 이 배치 정규화 계층을 가지고 싶을 겁니다. 이 논문을 읽고 모든 유도 (derivation)를 거쳐 보고, 주어진 정규화 연산으로 어떻게 경사를 계산하는지에 대한 유도도 쭉 보시길 바랍니다.

    한가지 지적하고 싶은 것은 명확하지 않은 것이 있다는 겁니다. 모든 완전 연결 계층 뒤에 이 배치 정규화를 하는데, 우리가 반드시 이 탠에이치 비선형성에 단위 가우시안 입력을 가지고 있어야 하는지 명확하지 않죠. 왜냐면, 이것이 여러분을 이 비선형성의 선형 영역으로 제한합니다. 그리고 여러분들은 이런 포화를 갖지 말자고 할겁니다. 아마도 이것도 좀 좋은 점이 있죠. 여러분들은 얼마나 많은 포화를 가질 지를 제어하고 싶을 겁니다.

    우리가 배치 정규화를 할 때 이걸 해결할 수 있는 방법은 우리가 정규화 연산을 가지고 있지만, 그 이후에 추가적으로 이런 밀어 붙이는 (squashing) 연산과 배율 (scaling) 연산이 있다는 겁니다. 우리의 정규화를 하는 거죠. 그다음 우리는 감마 (gamma) 상수 배율을 적용할 거고, 베타 (beta) 인수로 이동시킬 (shift) 겁니다. 이것은 여러분이 원한다면 항등 (identity) 함수를 복원하게 할 것입니다. 그래서 망이 원한다면 배율 인수인 감마가 분산이 되도록 학습할 수 있을 것입니다. 베타는 평균이 되도록 학습할 수 있죠. 이 경우 마치 배치 정규화가 없는 것처럼 항등 사상 (identity mapping)을 복원할 수 있습니다. 이제 여러분은 자유롭게 여러분의 망이 탠에이치를 더 포화되게 하거나 덜 포화되게 학습하도록 할 수 있고, 좋은 훈련을 하기 위해서 얼마나 그렇게 해야 하는 지도 학습하게 할 수 있습니다.

    배치 정규화 아이디어를 요약해보죠. 입력이 주어졌을 때, 우리는 미니배치 평균을 계산할 겁니다. 들어오는 모든 미니배치에 대해서 이렇게 할 거구요. 분산도 계산합니다. 평균과 분산으로 정규화하고 이러한 추가적인 척도 인자 (scaling factor)와 이동 인수 (shifting factor)를 가집니다. 이것이 망을 통과하는 경사 흐름을 개선합니다. 결과적으로 더 견고하죠. 더 넓은 범위의 학습률, 여러 초기화에서 동작해서, 사람들은 배치 정규화를 하면 훈련시키기 쉽다는 것을 알았죠. 그것이 이것을 해야 하는 이유죠. 지적하고 싶은 한가지는 이것을 정규화 (regularization)하는 한 방법으로 생각할 수 있다는 겁니다. 각 계층의 출력에서 각각의 활성화, 각각의 출력은 입력 x의 출력이자 배치 속의 다른 예제들의 출력이죠. 같이 샘플된 예제들이요. 왜냐면 각각의 입력 데이타를 그 배치에 대한 경험적 평균으로 정규화할 거니까요. 그 이유로, 주어진 훈련 예제에 대해서 더 이상 결정값 (deterministic value)을 생성하지 않습니다. 그리고 이 모든 입력을 배치에서 함께 묶습니다. 그래서 이건 사실, 더 이상 결정적이지 않기 때문에, x의 표현을 약간 움직이는 (jitter) 거죠. 어떤 의미에서는 정규화 (regularization) 효과를 내기도 합니다. 

    마지막으로 이것에 대해서 얘기하고 싶은 것은, 테스트시에는, 배치 정규화 계층에서, 우리는 경험적 평균을 취하고 훈련 데이타에서 분산을 취하죠. 그래서 우리는 이것을 테스트시에는 다시 계산하지 않습니다. 우리는 그냥 훈련시에 추정하죠. 예를 들면, 이동 평균 (running average)을 사용해서요. 그리고 이것을 테스트시에 사용합니다. 그래서 그것으로 배율을 조정하죠.

    이제 학습 프로세스 베이비시팅하기 (babysitting)로 넘어가겠습니다. 이제 우리는 우리의 망 아키텍처를 정의했고, 훈련을 어떻게 모니터링할 지에 대해서 이야기 하겠습니다. 그리고 진행하면서 어떻게 하이퍼파라미터를 조정하여 좋은 학습 결과를 얻을 수 있는지에 대해서 얘기해 보겠습니다.

    항상 그렇듯이, 우리가 하고 싶은 첫번째 단계는 데이타 전처리입니다. 우리는 0 평균 데이타를 얻고 싶죠. 앞에서 이야기 했듯이요.

    그다음 우리는 아키텍처 (architecture)를 선택합니다. 여기서 우리는 , 예를 들어, 50개의 뉴런으로된 하나의 숨겨진 (hidden) 계층으로 시작할 겁니다. 그러나 사실 우리는 어떤 아키텍처든 선택할 수 있습니다.

    우리가 하고 싶은 첫번째 것은 우리의 망을 초기화하는 겁니다. 우리는 그것을 통과해서 순전파할 (forward pass)거고 우리의 손실이 합리적으로 나오도록 해야 합니다. 몇 강의 앞에서, 거기서 예를 들면서, 여기 있는 소프트맥스 (softmax) 분류기가 있다고 하면, 우리는 우리의 손실이 얼마여야 하는지 알고, 우리의 가중치가 언제 작은지 알죠. 그리고 우리는 일반적으로 확산적 (diffuse) 분포가 있습니다. 그리고 나면 우리는 소프트맥스 분류기 손실이 음의 로그 우도 (likelyhood)가 되길 바라죠. 10개의 클래스가 있다면, 그건 - 로그 1/10 정도가 될 겁니다. 여기보며 그건, 2.3 정도죠. 그래서 우리의 손실이 반드시 우리가 기대하는 값이 되도록 하고 싶습니다.

    그래서 이건 항상 하고 싶은 좋은 정밀 테스트 (sanity check)죠. 일단 우리의 초기 손실이 좋다는 것을 알게 되면...

    먼저 우리는 이것이 0 정규화 (regularization)를 갖길 원합니다. 우리가 정규화를 끄면, 이제 우리의 유일한 손실 항은 이 데이타 손실이고, 여기서 2.3이 될 겁니다.

    여기서 이제 정규화 (regularization)를 하고 싶습니다. 그걸 할 때, 우리의 손실이 올라가는 것을 보고 싶습니다. 왜냐면, 이 추가적인 정규화항을 추가했기 때문이죠. 이건 정밀 테스트를 위한 좋은 다음 단계죠.

    이제 우리는 훈련을 시작합니다. 이제 우리는 훈련을 하려고 하는데, 이걸 하는 좋은 방법은 매우 작은 양의 데이타로 시작하는 겁니다. 왜냐면, 매우 작은 훈련 셋을 가지고 있다면, 이것에 과적합되기 (overfitting) 매우 쉽고, 여기서 매우 좋은 훈련 손실을 얻을 겁니다. 이 경우 우리는 우리의 정규화를 다시 끄고 (turn off), 손실이 0으로 가게 할 수 있는지 한번 보고 싶네요.

    이 모든 에포크 (epoch)가 나오면서 손실이 변하는 것을 볼 수 있죠. 각 에포크마다 손실을 계산할 수 있고, 이것이 0까지 쭉 내려가는 것을 보고 싶습니다. 그리고 우리의 훈련 정확도가 1까지 올라가는 것을 볼 수 있고, 이건 말이 되죠. 만약 적은 수의 데이타가 있다면, 이것에 완벽하게 과적합될 수 있습니다.

    그걸 하고 나면, 이것들은 모두 정밀 테스트 (sanity check)입니다. 이제 여러분은 정말 훈련하는 것을 시작할 수 있습니다. 전체 훈련 데이타를 취해서 작은 양의 정규화 (regularization)로 시작합니다. 먼저 좋은 학습률이 뭔지 알아보죠. 학습률은 가장 중요한 하이퍼파라미터중의 하나이고, 먼저 조정하고 싶은 것입니다. 그래서 여러분은 어떤 학습률 값을 시도해 보고 싶을 겁니다.

    여기 저는 1의 -6제곱을 했는데요. 손실이 거의 바뀌지 않는 것을 알 수 있습니다.

    거의 변하지 않는 것은 학습률이 너무 작아서 그렇습니다. 너무 작으면, 경사 업데이트가 충분히 크지 않고, 비용은 거의 같죠.

    여기서 지적하고 싶은 것은 우리 손실이 거의 변하지 않는다는 것을 알았지만, 훈련과 검증 정확도는 20%까지 빠르게 올라왔습니다. 왜 그런지 아는 사람 있나요? 소프트맥스 함수가 있다는 것을 기억해 보세요. 손실은 거의 바뀌지 않았지만, 정확도는 많이 개선되었죠. 이렇게 되는 이유는 여기서 확률이 여전히 꽤 퍼져 (diffuse)있죠. 우리의 손실 항은 여전히 꽤 비슷합니다. 그러나 우리가 이 모든 확률을 약간 올바른 방향으로 움직일 때, 왜냐면 우리는 학습하는 중이니까요. 가중치가 올바른 방향으로 변하는 거죠. 이제 정확도는 갑자기 뛰어오를 수 있습니다. 왜냐면 우리는 최대로 정확한 값을 취하고 있으니까요. 그래서 우리는 정확도에서 큰 점프를 얻는거죠. 비록 우리의 손실은 여전히 비교적 퍼져있지만요. 

    이제 또 다른 학습률을 시도한다면, 다른 극단으로 뛰어들어 보죠. 매우 큰 학습률인 1e6를 취해 보죠.

    그랬더니 우리의 비용은 NaN이 되네요. NaN이 나왔다는 것은 비용이 폭발했다는 것을 의미합니다. 그렇게 되는 이유는 보통 학습률이 너무 높아서 그렇습니다.

    그럼 여러분은 학습률을 낮게 조정할 수 있겠죠. 3e-3을 시도해보죠. 비용이 여전히 폭발합니다. 보통 우리가 보고 싶은 학습률의 대략적인 범위는 1e-3와 1e-5입니다. 그 범위 사이에서 우리는 교차 검증을 해보고 싶습니다. 여러분들은 그 범위에서 값들을 시도해보고, 손실이 너무 작은지, 너무 큰지에 따라서 이것을 기반으로 조정하고 싶을 겁니다.

    댓글

Designed by Tistory.