개발자의시작

Natural Language Processing with PyTorch 정리 3-2 본문

자연어처리

Natural Language Processing with PyTorch 정리 3-2

LNLP 2020. 5. 13. 16:24

이 글은 Natural Language Processing with Pytorch 강의자료를 번역 및 정리해놓은 글입니다.

 

강의 자료 및 코드 링크 :

https://github.com/dlsucomet/MLResources/blob/master/books/%5BNLP%5D%20Natural%20Language%20Processing%20with%20PyTorch%20(2019).pdf

 

dlsucomet/MLResources

Repository for Machine Learning resources, frameworks, and projects. Managed by the DLSU Machine Learning Group. - dlsucomet/MLResources

github.com

Diving Deep into Supervised Training

 

지도학습은 레이블(label)이 부착된 데이터에 따라 지정된 대상에 매핑하는 방법을 학습하는 문제이다. 이번 섹션에서는 더 자세히 설명한다. 특히 모델의 예측 및 손실 함수를 사용하여 모델 매개 변수의 그래디언트 기반 최적화를 수행하는 방법을 명시적으로 설명한다. 추후 이어지는 내용들은 이번 부분에 설명한 내용을 바탕으로 작성되었으므로 자세히 살펴볼 필요가 있다.

 

지도학습에는 모델, 손실 함수, 학습 데이터 및 최적화 알고리즘이 필요하다. 지도 학습의 학습 데이터는 관측(observation)과 목표(target)의 쌍이다. 모델은 관측치로부터 예측을 계산하고 손실은 목표와 비교하여 예측의 오차를 측정한다. 학습의 목표는 그라디언트 기반 최적화 알고리즘을 사용하여 모델의 매개변수를 조정하여 손실이 가능한 낮도록 하는 것이다. 

 

이번 섹션의 나머지 부분에서는 고전적인 문제인 2차원 분류(two-dimensional)에 대해 설명한다. - 두 클래스 중 하나를 가리키는 문제

 

직관적으로 이것은 의사 결정 경계 또는 초평면이라는 단일 라인을 학습하여 한 클래스의 포인트를 다른 클래스와 구별하는 것을 의미한다. 데이터 구성, 모델 선택, 손실 함수 선택, 최적화 알거리즘 설정 및 마지막으로 모두 실행하는 단계를 설명한다.

 

Constructing Toy Data

 

기계학습에서는 알고리즘을 이해하려고 할 때 잘 이해되는 속성을 가진 합성 데이터를 만드는 것이 일반적이다. 이 부분에서는 2차원 점을 두 클래스 중 하나로 분류하는 작업에 합성데이터를 사용한다. 데이터를 구성하기 위해 xy-좌표의 서로 다른 두 부분에서 점을 샘플링하여 모델에 대해 배우기 쉬운 상황을 만든다. 샘플은 아래의 그림 figure 3-2에 묘사된다. 모델의 목표는 별(★)을 한 클래스로 분류하고 원(O)을 다른 클래스로 분류하는 것이다. 오른쪽 그림을 목표로 하며 선 위의 모든 항목이 선 아래의 모든 항목과 다르게 분류된다. 데이터 생성을 위한 코드는이 장과 함께 제공되는 Python 노트북의 get_toy_data () 함수에 있습니다.

 

 

CHOOSING A MODEL

 

여기서 사용하는 모델은 3-1에서 도입된 모델이다. 퍼셉트론은 모든 입력 크기를 허용한다는 점에서 융통성이 있다. 일반적인 모델링 상황에서 입력 크기는 작업 및 데이터에 의해 결정된다. 이 예제에서 입력 크기는 2이다. 데이터를 2차원으로 명시적으로 구성했기 때문이다. 이 two-class 문제의 경우 0과 1의 숫자 인덱스를 클래스에 할당한다. 문자열 레이블 ★ 및 O을 클래스 인덱스에 매핑하는 것은 데이터 전처리, 학습, 평가 및 테스트 전체에서 일관성이 있는 한 임의적(arbitrary)이다. 이 모델의 중요한 추가 속성은 출력의 특성이다. 퍼셉트론의 활성화 함수가 sigmoid이므로 퍼셉트론의 출력은 데이터 포인트(x)가 클래스 1 즉 P(y=1| x)가 될 확률이다. 

 

CHOOSING AN OPTIMIZER

 

이 단순한 지도 학습 예제의 최종 선택 지점은 최적화이다. 모델이 예측을 생성하고 목표(target)와의 오차를 계산하는 동안 최적화 프로그램은 오차 신호를 사용하여 모형의 가중치를 업데이트한다. 가장 간단한 형태로 옵티마이저(optimizer)의 업데이트 동작을 제어하는 단일 하이퍼 파라미터가 있다. 학습률(learning rate)이라 하는 이 하이퍼 파라미터는 오류 신호가 가중치 업데이트에 미치는 영향을 제어한다. 학습률은 중요한 하이퍼파라미터이므로 몇 가지 다른 학습률을 시도하고 비교해야 한다. 학습률이 크면 매개변수가 크게 변경되어 수렴에 영향을 줄 수 있다. 너무 작은 학습률은 학습 중에 진전이 거의 없을 수 있다. 

 

PyTorch 라이브러리는 옵티 마이저를 위한 몇 가지 선택 사항을 제공합니다. SGC (Stochastic Gradient Descent)는 고전적인 알고리즘이지만, 최적화 문제가 어려운 경우 SGD에 수렴 문제가 있어 모델이 더 나빠질 수 있다. 현재 선호되는 대안은 다음과 같은 적응형 최적화 프로그램이다.

 

example 3-10. Instantiating the Adam optimizer

1
2
3
4
5
6
7
import torch.nn as nn
import torch.optim as optim
input_dim = 2
lr = 0.001
perceptron = Perceptron(input_dim=input_dim)
bce_loss = nn.BCELoss()
optimizer = optim.Adam(params=perceptron.parameters(), lr=lr)
 

 

 

 

Putting It Together: Gradient-Based Supervised Learning

 

학습은 손실을 계산하는 것부터 시작된다. 즉, 모델 예측이 목표에서 얼마나 멀리 떨어져 있는지 계산한다. 손실 함수의 기울기는 결과적으로 매개 변수가 얼마나 많이 변화해야 하는지에 대한 신호이다. 각 매개 변수의 기울기는 해당 매개 변수가 주어진 손실 값의 순간 변화율을 나타낸다. 실제로 이것은 각 매개 변수가 손실 함수에 얼마나 많은 영향을 주었는지 알 수 있다. 직관적으로 보면 이것은 경사이며 각 매개 변수가 자체 언덕(hill)에 있고, 언덕 위로 또는 아래로 한 걸음을 내딛고 싶다고 상상할 수 있다. 가창 최소한의 형태로 기울기 기반 모델 학습과 관련된 모든 것은 해당 파라미터에 대한 손실 함수의 기울기로(손실 함수를 줄이는 방향) 각 파라미터를 반복적으로 업데이트하는 것이다. 

 

이 gradient-stepping 알고리즘이 어떻게 생겼는지 살펴보자. 첫째 모델(perceptron) 객체 내부에 현재 저장되어 있는 경사와 같은 부기(bookkeeping)정보는 zero_grad()라는 함수로 지워진다. 그럼 다음, 모델은 입력 데이터(x_data)에 주어진 출력(y_pred)을 계산한다. 다음으로, 모델 출력(y_pred)을 의도된 목표물(y_target)과 비교하여 손실을 계산한다. 이것은 지도학습 학습에 해당하는 부분이다. PyTorch 손실 객체(criterion)는 연산 그래프를 통해 손실을 반복적으로 역방향으로 전파하고 각 파라미터에 그 손실을 알리는 backward() 라는 함수를 갖는다. 마지막으로 optimizer는 매개변수에게 step()라는 함수로 기울기를 전달해 어떻게 값을 업데이트하는지 지시한다. 

 

모든 학습 데이터는 batches로 분할된다. gradient step의 각 반복(iteration)은 데이터 batch에서 수행된다. batch_size 라는 하이퍼파라미터는 배치의 크기를 지정한다. 학습 데이터 세트의 크기가 고정되어 있기 때문에 batch의 크기를 늘리면 batch의 수는 감소한다. 

 

배치들(일반적으로 유한 크기의 데이터 세트에 있는 배치의 수)후 학습 루프는 epoch을 완료한다. epoch은 완전한 학습의 반복이다. epoch 당 배치 수가 데이터 세트의 배치 수와 동일한 경우 epoch은 데이터 세트에 대한 전체 반복 완료이다. 모델은 특정 수의 epoch에 대해 학습된다. 선택하기 쉽지 않지만, 언제 반복을 멈추어야 하는지 결정하는 방법이 있다. example 3-11에서 알 수 있듯, 지도학습 루프는 중첩 루프이다. 즉, 데이터 세트 또는 배치 수에 대한 내부 루프와 고정된 수의 epoch 또는 기타 종료 기준에 대해 내부 루프를 반복하는 외부 루프이다. 

 

example 3-11. A supervised training loop for a perceptron and binary classification

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# each epoch is a complete pass over the training data
for epoch_i in range(n_epochs):
    # the inner loop is over the batches in the dataset
    for batch_i in range(n_batches):
    
        # Step 0: Get the data
        x_data, y_target = get_toy_data(batch_size)
        # Step 1: Clear the gradients
        perceptron.zero_grad()
        # Step 2: Compute the forward pass of the model
        y_pred = perceptron(x_data, apply_sigmoid=True)
        # Step 3: Compute the loss value that we wish to optimize
        loss = bce_loss(y_pred, y_target)
        # Step 4: Propagate the loss signal backward
        loss.backward()
        # Step 5: Trigger the optimizer to perform one update
        optimizer.step()
 
 

 

Auxiliary Training Concepts

gradient-based 지도 학습의 핵심 아이디어는 간단하다. 모델을 정의하고, 출력을 계산하며, 손실 함수를 사용하여 gradient를 계산하고, 모델 파라미터를 gradient로 업데이트하기 위한 최적화 알고리즘을 적용한다. 그러나, 학습 과정 중요한 몇 가지 보조 개념들이 있다. 이 부분에서는 그것들 중 몇몇을 다룬다.

 

Correctly Measuring Model Performance: Evaluation Metrics

핵심적인 지도 학습 외부 루프에 있는 가장 중요한 구성요소는 모델이 훈련하지 않은 데이터를 사용한 객관적인 성능 측정이다. 모델은 하나 이상의 평가 지표를 사용하여 평가된다. 자연어 처리에는 그러한 측정 지표가 여러 개 있다. 이 장에서 우리가 사용할 가장 일반적인 것은 정확성(accuracy)이다. 정확성은 학습 중에 없었던 데이터 집합에서 정확했던 예측의 일부분이다. 

 

Correctly Measuring Model Performance: Splitting the Dataset

데이터의 진정한 분포를 잘 일반화하는 것이 최종 목표라는 것을 항상 명심해야 한다. 쉽게 말하자면, 우리가 무한한 양의 데이터를 볼 수 있다고 가정할 때 전 세계적으로 존재하는 데이터의 분포가 존재한다(true/unseen distribution). 분명한 것은 우리는 할 수 없다. 대신에, 우리는 학습 데이터라고 부르는 유한한 견본으로 만든다. 우리는 실제 분포의 근사치 또는 실제 분포의 근사치 또는 불완전한 그림인 유한 표본의 데이터 분포를 관찰한다. 학습 데이터에서 본 표본의 오차는 물론 보이지 않는 분포의 표본 오차를 줄인다면 다른 모델보다 더 일반화(generalized better) 되었다고 한다. 이 모델은 학습 데이터의 손실을 줄이기 위해 작동하기 때문에 실제 데이터 배포의 일부가 아닌 특이점에 과적합(overfit)하고 적응(adapt)할 수 있다. 

 

일반화를 잘하는 것은 목표를 달성하기 위해 데이터 집합을 무작위로 샘플링된 세 개의 파티션(학습, 검증, 평가)으로 분할하거나 k-fold 교차 검증을 수행하는 것이 표준 관행이다. 세 개의 파티션으로 분할하는 것이 한 번의 계산만 필요로 하기 때문에 더 간단하다. 그러나, 세 개의 파티션에서 클래스의 분포가 동일하게 유지되도록 주의해야 한다. 따라서, 클래스 라벨 별로 데이터 집합을 집계한 다음, 구분된 각 세트를 무작위로 학습, 검증, 평가 데이터로 분할하는 것이 바람직하다. 일반적인 분할 비율은 학습 70%, 검증 15%, 평가 15%를 지정하는 것이다. 이것은 다양하게 설정할 수 있다. 

 

k-fold 교차 검증을 통한 모델 평가는 미리 정의된 분할을 사용한 평가와 매우 유사하지만, 전체 데이터 집합을 동일한 크기의 "폴드"로 분할하는 추가 단계가 선행된다. 폴드 중 하나는 평가를 위해, 나머지 k1은 학습을 위한 폴드가 된다. 이는 평가에 사용된 폴드 부분을 스와핑 하여 반복적으로 사용하는 것이다. k 폴드가 있기 때문에 각 폴드는 평가 폴드가 되어 k 정확도 값이 된다. 최종 보고된 정확도는 단순히 표준 편차의 평균이다. k 폴드 교차 평가는 계산상 비용이 많이 들지만 소규모 데이터셋의 경우 매우 필요한데, 잘못된 분할은 너무 많은 낙관론( 평가 데이터가 너무 쉬워짐) 또는 너무 많은 비관론( 평가 데이터가 너무 어려워짐)으로 이어질 수 있다. 

 

Knowing When to Stop Training

이 예는 앞에서 정해진 수의 에폭에 대해 모델을 훈련시킨다. 비록 이것이 가장 간단한 접근이지만, 자의적이고 불편하다. 모델 성능을 올바르게 측정하는 핵심 기능 중 하나는 해당 측정을 사용하여 언제 훈련을 중단해야 하는지 결정하는 것이다. 가장 일반적인 방법은 조기 중단(early stopping)이라고 하는 휴리스틱스를 사용하는 것이다. 조기 중지 기능은 검증 데이터 집합의 성능을 epoch에서 epoch까지 추적하고 성능이 더 이상 향상되지 않는 시기를 알아채는 방식으로 작동한다. 그 후, 성능이 계속 향상되지 않으면, 훈련은 종료된다. 훈련을 종료하기 전에 대기할 에폭 수를 인내(patience)라고 한다. 일반적으로 모델이 일부 데이터 집합에서 개선을 중지하는 지점은 모델이 수렴된 시점이라고 한다. 실제로 우리는 학습이 시간이 많이 걸리고 과적합될 수 있기 때문에 모델이 완전히 수렴되기를 기다리는 경우가 거의 없다.

 

Regularization

 

딥러닝(및 일반적인 머신러닝)에서 가장 중요한 개념 중 하나는 정규화다. 정규화의 개념은 수치 최적화 이론에서 비롯된다. 대부분의 머신러닝 알고리즘이 관측치를 설명하는 매개변수(또는 "모델')의 가장 가능성이 높은 값을 찾기 위해 손실 함수를 최적화하고 있다는 점을 상기한다(즉, 최소 손실량을 산출한다.) 대부분의 데이터셋 및 작업의 경우, 이 최적화 문제에 대한 여러 솔루션(가능 모델)이 있을 수 있다. 그러면 어떤 것을 선택해야 할까? 직관적인 이해를 발전시키려면, 아래의 그림을 예로 설명할 수 있다.

 

 

두 곡선 모두 "적합"하지만, 어느 곡선이 설명하기 어려운가? 오캄의 면도날에 호소함으로써 우리는 복잡한 것보다 간단한 설명이 더 낫다는 것을 직감한다. 머신러닝에서 이러한 부드러운 제약을 L2정규화라고 한다. PyTorch에서는 최적기에서 weight_decay 파라미터를 설정하여 이를 제어할 수 있다. weight_decay 값이 클수록 최적기가 보다 부드러운 설명(즉, L2 정규화)을 선택할 가능성이 높다. 

 

 

Comments