Link

그래디언트 클리핑

순환 신경망은 BPTTBack-Propagation Through Time 알고리즘에 의해서 학습됩니다. 이때 BPTT 알고리즘에 따라, 긴 데이터를 다루는 상황일수록 그래디언트가 더해지는 횟수가 늘어나게 됩니다. 달리 말하면 긴 순서 데이터를 다룰수록 그래디언트는 커집니다. 따라서 데이터의 길이에 따라서 적절한 학습률learning rate의 크기가 바뀔 수도 있고, 잘못하면 그래디언트가 너무 커져서 자칫 학습이 산으로 갈 수도 있게 됩니다.

이러한 상황을 방지하기 위해서 우리는 그래디언트 노름의 최대 값을 정하고, 최대 값을 넘길 경우 그래디언트를 강제로 줄여버리도록 할 수 있습니다. 이 방법을 그래디언트 클리핑gradient clipping이라고 합니다. 이 방법의 특징은 그래디언트 벡터의 크기는 줄이되 방향은 유지하도록 클리핑 작업을 수행한다는 것입니다. 그럼 클리핑 된 이후의 그래디언트 방향은 같으므로, 파라미터가 업데이트 되는 방향도 같을 것입니다.

예를 들어 우리는 그래디언트의 크기를 다음과 같이 구할 수 있습니다.

\[\begin{gathered} \|\nabla_\theta\mathcal{L}(\theta)\|_2 \end{gathered}\]

이때 만약 그래디언트의 크기가 임계 값threshold $\tau$ 을 넘는다면, 두 값 사이의 비율을 다음과 같이 구하고 $r$ 이라고 부르도록 합니다.

\[\begin{gathered} r=\frac{\|\nabla_\theta\mathcal{L}(\theta)\|_2}{\tau} \end{gathered}\]

그럼 기존의 경사하강법에 의한 파라미터 업데이트는 그래디언트 클리핑이 더해져서 다음과 같이 바뀌게 될 것입니다.

\[\begin{aligned} \theta_{t+1}&=\theta_t-\eta\nabla_\theta\mathcal{L}(\theta) \\ \\ &\Downarrow_\text{ by gradient clipping} \\ \\ \theta_{t+1}&=\theta_t-\eta\nabla_\theta\frac{\mathcal{L}(\theta)}{r}\text{, if }\|\nabla_\theta\mathcal{L}(\theta)\|_2>\tau. \end{aligned}\]

이와 같은 방법을 통해 우리는 그래디언트를 통제할 수 있고, 학습을 효율적으로 수행할 수 있게 됩니다. 아담Adam을 쓸 경우에도, 그래디언트가 너무 커지는 것을 방지하도록 유용하게 쓰일 수 있습니다.

그래디언트 클리핑의 구현

다행히도 파이토치에서는 그래디언트 클리핑 기능을 바로 제공하고 있어서, 우리가 직접 구현할 필요가 없습니다. 다음의 그림은 그래디언트 클리핑 함수인 clip_grad_norm_ 에 대한 파이토치 공식 문서입니다.

parameters 인자에 클리핑을 원하는 파라미터를 넣어주고, max_norm 인자에 임계 값 $\tau$ 을 넣어주도록 합니다.