관리 메뉴

Bull

[ML] 가중치 초기화 / 정칙화 | study book 본문

Artificial Intelligence/Machine Learning

[ML] 가중치 초기화 / 정칙화 | study book

Bull_ 2024. 8. 26. 03:44

가중치 초기화

가중치 초기화는 모델의 초기 가중치 값을 설정하는 것을 말한다. 모델의 배개변수에 적절한 초깃값을 설정하면 기울기 폭주나 기울기 소실문제를 완화할 수 있다. 또한 모델의 수렴 속도를 향상시켜 전반적인 학습 프로세스를 개선할 수 있다.

상수 초기화

상수 초기화는 초기 가중치 값을 모두 같은 상수 값으로 초기화한다. 그 값은 0, 1, 특정 값, 단위 행렬, 디렉 델타 함수 등이 올 수 있다.
$$ W=a $$
$$
\mathbf{W} =
\begin{bmatrix}
0 & 0 & 0 \\
0 & 0 & 0 \\
0 & 0 & 0
\end{bmatrix}
$$
상수 초기화는 구현이 간단하고 계산 비용이 거의 들지 않지만 잘 사용하지 않는다. 모든 가중치의 초기값을 같은 값으로 초기화하면 배열 구조의 가중치에서 문제가 발생한다. 이 문제는 대칭 파괴 현상으로 인해 모델의 학습이 어렵거나 불가능하게 든다.

무작위 초기화

무작위 초기화는 랜덤한 값으로 초기화 하거나 특정 분포 형태로 초기화 하는 것을 말한다. 대표적으로 random, uniform, normal, truncated normal, sparse initialization 등이 있다. 무작위 초기화는 노드의 가중치와 편향을 무작위로 할당해 네트워크가 학습할 수 있게 하여 대칭 파괴 문제를 방지할 수 있다. 하지만 계층이 많아지고 깊어질수록 활성화 값이 양 끝단에 치우치게 되어 기울 시 소실 현상이 발생한다.

1. Random Initialization (무작위 초기화)

가중치를 완전히 무작위로 초기화하는 방법이다. 보통 가중치를 작은 값으로 설정하기 위해 -1과 1 사이 또는 0과 1 사이의 임의의 값으로 초기화다.

2. Uniform Distribution (균등 분포)

균등 분포에서 가중치를 샘플링하여 초기화한다. 가중치가 특정 범위 내에서 균일하게 분포되도록 초기화하는 방법이다. 예를 들어, -0.05와 0.05 사이에서 균일하게 값을 샘플링할 수 있다.

$$
\mathbf{W} \sim U(a, b)
$$

여기서 $U(a, b)$는 $a$와 $b$ 사이의 균등 분포를 의미한다.

3. Normal Distribution (정규 분포)

가중치를 정규 분포에서 샘플링하여 초기화하는 방법이다. 보통 평균이 0이고, 표준 편차가 작은 정규 분포를 사용하여 초기화한다.

$$
\mathbf{W} \sim \mathcal{N}(0, \sigma^2)
$$

여기서 $\mathcal{N}(0, \sigma^2)$는 평균이 0이고, 분산이 $\sigma^2$인 정규 분포를 의미한다.

4. Truncated Normal Distribution (절단된 정규 분포)

정규 분포에서 샘플링하되, 극단적인 값들은 잘라내고 (truncated) 중간 범위의 값들만 사용하여 가중치를 초기화하는 방법이다. 매우 큰 값이나 작은 값이 가중치로 선택되지 않도록 하여 초기화의 안정성을 높인다.

$$
\mathbf{W} \sim \text{Truncated } \mathcal{N}(0, \sigma^2)
$$

5. Sparse Initialization (희소 초기화)

이 방법은 대부분의 가중치를 0으로 초기화하고, 일부 가중치만을 무작위 값으로 초기화하는 방식이다. 대규모 신경망에서 효율성을 높이기 위해 사용되며, 가중치 행렬이 희소(sparse)하도록 만든다.

제이비어 & 글로럿 초기화

제이비어 초기화는 글로럿 초기화 라고도 하며 균등 분포나 정규 분포를 사용한다.제이비어 글로럿과 요슈아 벤지오가 2010년에 제안한 방법으로 각 노드의 출력 분산이 입력 분산과 동일하도록 가중치를 초기화 하는 방법이다. 참고로 분포에서 가중치는 그 범위 내에서 랜덤으로 뽑는 것이다.

 

이 초기화 방법은 각 층에서 입력과 출력 간의 분산이 균형을 이루도록 설계되었다. 만약 가중치가 너무 크면, 신경망의 출력이 폭발적으로 커져 기울기가 매우 커질 수 있다. 반대로, 가중치가 너무 작으면 신경망의 출력이 매우 작아져 기울기가 0에 가까워질 수 있다. 제이비어 초기화는 이러한 상황을 뉴런의 입출력 노드 수에 따라 조정 가능하다.

 

제이비어 초기화는 시그모이드(Sigmoid) 함수나 하이퍼볼릭 탄젠트(Tanh)와 같은 활성화 함수를 사용하는 신경망에서 유용하다. 활성화 함수들은 입력값의 분산에 민감하기 때문에, 가중치가 잘못 초기화되면 기울기 소실 문제가 발생하기 쉽기 때문이다.

 

제이비어 초기화는 시그모이드나 Tanh와 같은 비선형 활성화 함수에 적합하지만, ReLU(Rectified Linear Unit)와 같은 활성화 함수에는 적합하지 않을 수 있다. 이러한 경우에는 He 초기화(He Initialization)와 같은 다른 초기화 방법이 더 적합할 수 있다.

균등 분포를 사용하는 경우 (Xavier Uniform Initialization)

$$
\mathbf{W} \sim U\left(-\frac{\sqrt{6}}{\sqrt{n_{in} + n_{out}}}, \frac{\sqrt{6}}{\sqrt{n_{in} + n_{out}}}\right)
$$

  • $U(a, b)$는 $a$와 $b$사이의 균등 분포
  • $n_{in}$은 해당 층으로 들어오는 입력 뉴런의 수
  • $n_{out}$은 해당 층에서 나가는 출력 뉴런의 수

정규 분포를 사용하는 경우 (Xavier Normal Initialization)

$$
\mathbf{W} \sim \mathcal{N}\left(0, \frac{2}{n_{in} + n_{out}}\right)
$$

  • $\mathcal{N}(0, \sigma^2)$는 평균이 0이고, 분산이 $\sigma^2$인 정규 분포

카이밍 허 초기화

카이밍 초기화는 허 초기화라고도 하며 제이비어 초기화와 마찬가지로 균등 분포나 정규 분포를 사용해 가중치를 초기화하는 방법이다. 카이밍 허가 2015년에 제안한 방법으로 순방향 신경망 네트워크에서 가중치를 초기화할 때 효과적이다.

 

카이밍 초기화는 신경망의 각 층에서 기울기 소실(vanishing gradient)이나 기울기 폭주(exploding gradient) 문제를 방지하기 위해 가중치를 적절하게 초기화하는 방법이다. 제이비어 초기화가 입력과 출력 간의 분산을 동일하게 유지하려는 것과 달리, 카이밍 초기화는 ReLU와 같은 비대칭적인 활성화 함수의 특성을 고려하여 가중치를 초기화한다.

 

카이밍 초기화는 제이비어 초기화보다 더 큰 가중치를 사용하여, 특히 ReLU 활성화 함수를 사용하는 신경망에서 각 층의 출력이 너무 작아지지 않도록 한다. ReLU 함수는 양수 입력에 대해서만 활성화되므로, 가중치가 너무 작으면 많은 뉴런들이 0 출력을 내고 학습에 기여하지 못하는 문제가 발생할 수 있다. 카이밍 초기화는 이런 문제를 방지하기 위해 가중치를 적절히 조정한다.

 

카이밍 초기화는 주로 ReLU, Leaky ReLU, PReLU 등과 같은 활성화 함수와 함께 사용한다. 이 초기화 방법은 특히 깊은 신경망(deep neural networks)에서 효과적이다.

균등 분포를 사용하는 경우 (He Uniform Initialization)

$$
\mathbf{W} \sim U\left(-\sqrt{\frac{6}{n_{in}}}, \sqrt{\frac{6}{n_{in}}}\right)
$$

  • $U(a, b)$는 $a$와 $b$ 사이의 균등 분포
  • $n_{in}$은 해당 층으로 들어오는 입력 뉴런의 수

정규 분포를 사용하는 경우 (He Normal Initialization)

$$
\mathbf{W} \sim \mathcal{N}\left(0, \frac{2}{n_{in}}\right)
$$

  • $\mathcal{N}(0, \sigma^2)$는 평균이 0이고, 분산이 $\sigma^2$인 정규 분포

직교 초기화

직교 초기화는 특잇값 분해(SVD)를 활용해 자기 자신을 제외한 나머지 모든 열,행 벡터들과 직교이면서 동시에 단위 벡터인 행렬을 만드는 방법이다. LSTM및 GRU와 같은 순환 신경망에서 자주 사용된다. 직교행렬의 고윳값의 절댓값은 1이기 때문에 행렬 곱을 여러번 수행하더라도 기울기 폭주나 기울기 소실이 발생하지 않는다. 그러므로 가중치 행렬의 고윳값이 1에 가까워지도록 해 RNN에서 기울기가 사라지는 문제를 방지하는 데 사용된다. 직교 초기화는 모델이 특정 초기화 값에 지나치게 민감해지므로 순방향 신경망에서는 사용하지 않는다.

$$
A = U \Sigma V^T
$$

  • $U$와 $V$는 직교 행렬
  • $\Sigma$는 대각 행렬로, 대각선 요소는 특잇값(singular values)

직교 초기화에서는 임의의 행렬 $A$를 생성한 후, SVD를 통해 직교 행렬 $U$ 또는 $V$를 추출하여 가중치 행렬 $W$로 사용한다. $U$ 또는 $V$의 크기가 맞지 않으면 일부 요소만 선택하여 사용하거나 필요에 따라 크기를 조정한다.

 

RNN 구조에서 시간에 따라 입력이 반복되기 때문에, 직교 초기화는 기울기의 크기를 일정하게 유지하여, 신경망이 장기적인 의존성을 학습할 수 있도록 돕는다.

코드 적용

from torch import nn


class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer = nn.Sequential(
            nn.Linear(1, 2),
            nn.Sigmoid()
        )
        self.fc = nn.Linear(2, 1)
        self._init_weights()

    def _init_weights(self):
        nn.init.xavier_uniform_(self.layer[0].weight)
        self.layer[0].bias.data.fill_(0.01)

        nn.init.xavier_uniform_(self.fc.weight)
        self.fc.bias.data.fill_(0.01)


model = Net()

_init_weights : 메소드에서 모델의 매개변수의 초기값을 설정

n.init.xavier_uniform_(self.layer[0].weight) : 레이어 0의 가중치를 제이비어 초기화를 설정.
self.layer[0].bias.data.fill_(0.01) : 레이어 0의 편향을 적절한 값으로 설정.

메소드 종류

type class mean
상수 초기화 torch.nn.init.constant_(tensor,val) tensor를 val로 초기화
스칼라(1) 초기화 torch.nn.init.ones_(tensor) tensor를 1로 초기화
스칼라(0) 초기화 torch.nn.init.zeros_(tensor) tensor를 0로 초기화
스칼라(eye) 초기화 torch.nn.init.eye_(tensor) tensor를 I(단위 행렬)로 초기화 (2차원 텐서만 가능
디렉 델타 초기화 torch.nn.init.dirac_(tensor) tensor를 디렉 델타로 초기화 (3,4,5차원만 가능)
균등 분포 초기화 torch.nn.init.uniform_(tensor,a=0.0,b=0.0) tensor를 U(a,b)로 초기화
정규 분포 초기화 torch.nn.init.normal_(tensor,mean=0.0,std=1.0) tensor를 N(mean,$std^2$)로 초기화
잘린 정규 분포 초기화 torch.nn.init.trunc_normal_(tensor,mean=0.0,std=1.0,a=-2.0,b=2.0) tensor를 N(mean,$std^2$)[a,b]로 초기화
희소 정규 분포 분포 초기화 torch.nn.init.sparse_(tensor,sparsity) tensor를 sparse 비율 만큼 N(mean,0.01)로 초기화
제이비어 초기화 (균등 분포) torch.nn.init.xavier_uniform_(tensor,gain=1.0) tensor를 제이비어 균등 분포 초기화
제이비어 초기화 (정규 분포) torch.nn.init. xavier_normal_ (tensor,gain=1.0) tensor를 제이비어 정규 분포 초기화
카이밍 초기화 (균등 분포) torch.nn.init.kaiming_uniform_(tensor,a=0) tensor를 카이밍 균등 분포 초기화
카이밍 초기화 (정규 분포) torch.nn.init. kaiming_normal_ (tensor,a=0) tensor를 카이밍 정규 분포 초기화
직교 초기화 torch.nn.init.orthogonal_(tensor,gain=1) tensor를 직교 행렬로 초기화 (gain은 비율)

정칙화 (Regularization)

정칙화란 모델 학습시 발생하는 과대적합 문제를 방지하기 위해 사용되는 기술로 모델이 암기가 아니라 일반화할 수 있도록 손실 함수에 규제(Panalty)를 가하는 방식이다.

 

암기(Memorization)란 모델이 데이터의 특성이나 패턴을 학습하는 것이 아니라 훈련 데이터의 노이즈를 학습했을 때 발생한다. 모델이 훈련 데이터에서는 잘 수행되지만 새로운 데이터에서는 제대로 수행되지 못하는 경우를 의미한다. 즉 학습 데이터의 노이즈나 특정 패턴을 학습하는 경우이다.

 

일반화란 모델이 새로운 데이터에서도 정확한 예측을 할 수 있음을 의미한다. 정칙화는 일반화된 모델을 구축하기 위해 사용하는 방법이다. 모델이 특정 피처나 특정 패턴에 너무 많은 비중을 할당하지 않도록 손실함수에 규제를 가해 모델의 일반화 성능을 향상시킨다.

 

정칙화는 모델이 비교적 복잡하고 학습에 사용되는 데이터 수가 적을 때 활용한다. 모델이 단순하면 정칙화가 필요하지 않다.

L1 정칙화

L1 정칙화는 라쏘(Lasso) 정칙화라고도 하며 L1 노름방식을 사용해 규제하는 방식이다. L1 노름은 벡터 또는 행렬값의 절댓값 합계를 계산한다. L1 정치고하는 손실 함수에 절댓값의 합으로 규제를 가하므로 모델은 가중치 절댓값의 합도 최소가 되는 방향으로 학습이 진행한다. 모델 학습시 값이 크지 않은 가중치들은 0으로 수렴하게 되어 예측에 필요한 특징 수가 줄어든다.

$$
\text{Regularized Loss} = \text{Original Loss} + \lambda \sum_{i} |w_i|
$$

  • $\lambda$는 정칙화의 강도를 조절하는 하이퍼파라미터로, 정칙화 계수
  • $w_i$는 모델의 각 가중치
  • $\sum_{i} |w_i|$는 모든 가중치의 절댓값 합을 계산하는 L1 노름

L1 정칙화는 학습 과정에서 가중치의 절댓값을 줄이도록 한다. 그 결과, 모델의 많은 가중치들이 학습 중에 0으로 수렴할 수 있다. 가중치가 0으로 수렴하면서, 모델은 특정 특징(feature)들을 무시하게 된다. 즉, 중요한 특징만을 선택하고 불필요한 특징은 제거하는 효과가 있다. 이로 인해 모델의 복잡도가 줄어들고, 해석 가능성이 높아진다. L1 정칙화는 결과적으로 가중치 벡터를 희소(sparse)하게 만든다. 모델이 단순해지고, 계산 효율성이 증가하는 효과를 가진다.

 

L1 정칙화는 특히 고차원 데이터에서 유용하다. 예를 들어, 데이터셋에 매우 많은 특징이 존재할 때, L1 정칙화는 그 중 중요한 특징만을 선택하도록 하여 모델의 성능을 개선할 수 있다. 이 방식은 라쏘 회귀(Lasso Regression)에서 대표적으로 사용된다.

for x, y in train_dataloader:
    x = x.to(device)
    y = y.to(device)

    output = model(x)

    _lambda = 0.5
    l1_loss = sum(p.abs().sum() for p in model.parameters())

    loss = criterion(output, y) + _lambda * l1_loss

L2 정칙화

L2 정칙화는 릿지(Ridge) 정칙화라고도 하며 L2 노름 방식을 사용해 규제하는 방식이다. L1 방식에서 수식만 바뀌었다고 보면된다.

$$
\text{Regularized Loss} = \text{Original Loss} + \lambda \sum_{i} w_i^2
$$

  • $\lambda$는 정칙화의 강도를 조절하는 하이퍼파라미터로, 정칙화 계수
  • $w_i$는 모델의 각 가중치
  • $\sum_{i} w_i^2$는 모든 가중치의 제곱합을 계산하는 L2 노름

L2 정칙화는 학습 과정에서 가중치들의 제곱합을 최소화하도록 만든다. 이로 인해 가중치의 크기가 축소되어, 모델이 과적합되는 것을 방지한다. L2 정칙화는 모든 가중치를 균일하게 줄이는 경향이 있다. 따라서 모든 가중치가 조금씩 작아지게 되고, 이로 인해 모델이 더 일반화된 형태로 학습된다. L1 정칙화와 달리, L2 정칙화는 가중치를 0으로 수렴시키는 대신, 가중치를 아주 작은 값으로 줄이는 역할을 한다. 모든 입력 특징을 어느 정도 유지하면서도 모델의 복잡도를 줄이는 데 좋다.

 

L2 정칙화는 일반적으로 선형 회귀, 로지스틱 회귀, 딥러닝 모델 등 다양한 상황에서 사용된다. 특히, 입력 데이터에 많은 특징이 있고, 과적합을 방지하고자 할 때 유용하다. 릿지 회귀(Ridge Regression)는 L2 정칙화를 사용하는 대표적인 선형 회귀 기법이다.

for x, y in train_dataloader:
    x = x.to(device)
    y = y.to(device)

    output = model(x)

    _lambda = 0.5
    l2_loss = sum(p.pow(2.0).sum() for p in model.parameters())

    loss = criterion(output, y) + _lambda * l2_loss

가중치 감쇠

가중치 감쇠는 L1, L2 과 마찬가지로 모델이 더 작은 가중치를 갖도록 손실함수에 규제를 가한다. 일반적으로 가중치 감쇠가 L2 정칙화와 동의어로 사용되지만 가중치 감쇠는 손실함수에 규제 항을 추가하는 기술 자체를 의미한다.

optimizer = torch.optim.SGD(model.parameters(), lr=0.01, weight_decay=0.01)

이는 L2 정칙화를 적용한 것이다. weight_decay 가 0.01임은 L2 수식에서 $\lambda=0.01$을 말한다. 파이토치에서 optim 메소드는 L2 정칙화를 사용한다. L1을 사용하지 않는 이유는 모르겠다.

모멘텀

모멘텀은 경사 하강법 알고리즘의 변형 중 하나로 이전에 이동했던 방향과 기울기의 크기를 고려하여 가중치를 갱신한다. 지수 가중 이동평균을 사용하며 이전 기울기 값의 일부를 현재 기울기 값에 추가해 가중치를 갱신한다. 이전 기울기 값에 의해 설정된 방향으로 더 빠르게 이동하므로 일종의 관성 효과를 얻을 수 있다.

$$
v_t = \beta v_{t-1} + (1 - \beta) \nabla L(\theta_{t-1})
$$
$$
\theta_t = \theta_{t-1} - \eta v_t
$$

  • $v_t$: 현재 모멘텀 벡터 (지금까지의 기울기의 지수 가중 이동평균)
  • $\beta$: 모멘텀 계수 (0과 1 사이의 값으로, 보통 0.9로 설정)
  • $\nabla L(\theta_{t-1})$: 이전 가중치에서의 손실 함수의 기울기
  • $\eta$: 학습률
  • $\theta_t$: 현재 가중치

모멘텀은 지수 가중 이동평균(Exponential Moving Average, EMA)을 사용하여 이전 기울기 값을 반영한다. 이로 인해, 최적화 과정에서 특정 방향으로의 움직임이 가속화되고, 최솟값 근처에서의 진동이 줄어든다.

 

모멘텀의 기본 아이디어는 물리학에서의 관성 효과와 유사하다. 이전의 움직임이 현재의 움직임에 영향을 미쳐, 일정한 방향으로 가속도 있게 움직이는 것이다. 경사 하강법이 넓은 지역에서 빠르게 수렴하도록 도와주며, 좁은 골짜기에서의 진동을 완화한다. 단순 경사 하강법에서는 최솟값 근처에서 좌우로 진동하는 경우가 많다. 모멘텀은 이러한 진동을 줄여, 최적화가 더 빠르고 안정적으로 이루어지도록 돕는다.

 

$\beta$는 모멘텀의 "기억력"을 조절하는 파라미터다. $\beta$가 0에 가까우면, 현재 기울기에 더 많은 비중을 두고, $\beta$가 1에 가까우면, 이전 기울기에 더 많은 비중을 둔다.

엘라스틱 넷(Elastic-Net)

엘라스틱 넷은 L1, L2 정칙화를 결합해 사용하는 방식이다. L1 정칙화는 모델이 희박한 가중치를 갖게 규제하는 반면, L2 정칙화는 큰 가중치를 갖지 않게 규제한다. 두 방식을 결합함으로써 희소성과 작은 가중치의 균형을 맞춘다.

 

엘라스틱 넷(Elastic-Net)L1 정칙화(라쏘 정칙화)와 L2 정칙화(릿지 정칙화)를 결합한 방식으로, 두 정칙화 기법의 장점을 동시에 활용하는 정칙화 방법입니다. 이 방법은 모델의 가중치가 희박(sparse)하면서도 지나치게 큰 가중치가 나타나지 않도록 규제하는 데 효과적입니다.
$$
\text{Regularized Loss} = \text{Original Loss} + \lambda_1 \sum_{i} |w_i| + \lambda_2 \sum_{i} w_i^2
$$

여기서 $\lambda_1$은 $1-\lambda_2$로 0에서 1 사이값을 가진다. $\lambda_1$이 1이면 라쏘 회귀와 등일해지고 $\lambda_2$가 1이면 릿지 회귀와 등일해진다. 이렇게 엘라스틱 넷은 트레이드 오프문제를 더 유연하게 대처할 수있다.

드롭아웃

드롭아웃은 모델의 훈련과정에서 일부 노드를 일정 비율로 제거하거나 0으로 만들어 과대 적합을 방지한다. 2012년 제프리 힌턴의 논문을 통해 소개됐다. 과대적합을 발생시키는 이유 중 하나가 모델 학습 시 발생하는 노드 간 동조화 현상이다. 동조화 현상은 학습 시 특정 노드의 가중치나 편향이 큰 값을 갖게 되면 다른 노드가 큰 값을 갖는 노드에 의존하는 것을 말한다.

 

이 현상은 특정 노드에 의존성이 생겨 학습 속도가 느려지고 새로운 데이터를 에측하지 못해 성능을 저하시킬 수 있다. 모델 일부를 제거해 학습을 진행하므로 동조화 현상을 방지할 수 있다. 노드를 제거함으로써 투표 효과를 얻을 수 있어 모델 평균화가 된다. 하지만 모델 평균화 효과를 얻기 위해 다른 드롭아웃 마스크를 사용해 모델을 여러 번 훈련해야 하므로 훈련 시간이 늘어난다.

from torch import nn


class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer1 = nn.Linear(10, 10)
        self.dropout = nn.Dropout(p=0.5)
        self.layer2 = nn.Linear(10, 10)

    def forward(self, x):
        x = self.layer1(x)
        x = self.dropout(x)
        x = self.layer2(x)
        return x

p 는 베르누이 분포의 모수를 의미하며 이 분포로 각 노드의 제거 여부를 확률적으로 선택한다. 드룹아웃은 일반적으로 배치 정규화와 동시에 사용하지 않으므로 다른 기법을 동시에 적용할 때 주의해야 한다. 서로 정칙화 효과를 방해할 수 있기 때문이다. 만약 같이 사용해야 하는 경우에는 드룹아웃, 배치정규화 순으로 적용한다.

그레디언트 클리핑(Gradient Clipping)

그레디언트 클리핑은 모델을 학습할 때 기울기가 너무 커지는 현상을 방지하는데 사용한다. 과대적합 모델은 특정 노드의 가중치가 너무 크다는 특징을 갖는다. 높은 가중치는 높은 분산 값을 갖게 하여 모델의 성능이 저하될 수 있다.

 

이런 현상을 방지하기 위해 가중치 최댓값을 규제해 최대 임계값을 초과하지 않도록 기울기를 잘라 설정한 임계값으로 변경한다.
$$
w = r\frac{w}{|w|}\ if:|w|\ >\ r
$$
그래디언트 클리핑은 가중치 노름이 최대 임계값 r보다 높은 경우에 수행된다. 최대 임계값 r은 하이퍼파라미털 사용자가 최대 임계값을 설정해야한다. 0.1,1 과 같이 작은 크기의 임곗값을 적용하며 학습률을 조절하는 것과 비슷한 효과를 얻을 수 있다.

 

그레디언트 클리핑은 RNN, LSTM 모델을 학습하는 데 주로 사용된다. 두 모델은 기울기 폭주에 취약하기 때문이다.

for x, y in train_dataloader:
    x = x.to(device)
    y = y.to(device)

    output = model(x)
    loss = criterion(output, y)

    optimizer.zero_grad()
    loss.backward()

    torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1)

    optimizer.step()
clip_grad_norm_(parameters, max_norm, norm_type=2.0)

max_norm 값일 때 잘라내고, norm_type은 클리핑을 계산하는 노름 유형을 설정한다. 역전파를 수행한 이후 최적화 함수를 반영하기 전에 호출한다. 모델의 매개변수와 임계값을 인수로 사용하고 임계값을 초과하는 경우 기울기를 임계값으로 자르기 때문이다.

참고 자료

https://product.kyobobook.co.kr/detail/S000209621433

 

파이토치 트랜스포머를 활용한 자연어 처리와 컴퓨터비전 심층학습 | 윤대희 - 교보문고

파이토치 트랜스포머를 활용한 자연어 처리와 컴퓨터비전 심층학습 | 트랜스포머는 딥러닝 분야에서 성능이 우수한 모델로 현대 인공지능 분야의 핵심 기술입니다. 트랜스포머와 비전 트랜스

product.kyobobook.co.kr