곰퓨타의 SW 이야기

Lab 07-1 Tips 본문

이번 역시 모두의 딥러닝 시즌2인 부스트코스 강의를 참고했다.💪

www.boostcourse.org/ai214/lecture/42291/

 

파이토치로 시작하는 딥러닝 기초

부스트코스 무료 강의

www.boostcourse.org

 

 

Reminder : Maximum Likelihood Estimation (MLE)

압정을 떨어뜨릴 때,

class 1 : 납짝한 면이 바닥으로 떨어지는 경우

class 2: 그 외의 경우 라고 가정하자.

 

예측해야 하는 값이 두 가지이므로 베르누이 distribution (이항 분포)이다. (0과 1)

n= 100

k= 27

100번을 던졌을 때 class1이 나온 횟수가 27번이라 하자. 

 

MSE?

-> 우리가 관찰한 데이터를 가장 잘 설명하는 확률 분포 함수의 파라미터를 찾아내는 과정

 

Reminder : Optimization via Gradient descent

Gradient descent를 통해 손실값을 minimize하거나 objective function을 maximize하는 gradient ascent를 통해 loss를 최소화할 수 있다.

 

 

Reminder : Overfitting and Regularization

overfitting 

주어진 데이터에 대해 과도하게 fitting 된 경우이다.

train set으로 훈련을 한다면 train set에 대한 loss는 epoch 이 진행될 때마다 줄어들 것이다.

하지만 validation set의 경우, train set을 통해 훈련된 것이므로 특정 지점까지 loss가 줄어들다가 어느 지점에서부터 과적합된 prediction으로 인해 loss가 증가한다.

! 따라서 오버피팅이 되지 않도록 하는 것이 중요하다 !

 

 

--> 이를 방지하기 위해 훈련 set과 test set으로 나누어 훈련한다.

Development set은 test set에 대해서도 과적합이 되는 경우를 방지한다.

 

Training set에 대해서 훈련을 하고 test set에서 가장 좋은 성능을 가진 것을 선택할 때, 

train set과 test set에 대해 overfit이 될 수 있다.

따라서, 상황에 따라 train set으로 훈련을 한 후, dev set(Validation)에 대해서 검증을 한 이후, test set으로 성능을 측정한다.

 

 

overfitting 을 막기 위한 방법 :1. 데이터 더 수집하기2. feature를 적게 사용하기(데이터 분포 특징)

얼굴 특징을 설명할 때 여러개를 설명할 수 있겠지만  특징의 개수를 줄인다.

갸름한 턱, 오똑한 코, 등등이 있겠지만 몇개의 feature만 뽑아서 사용하는 것이다.

3. Regulation

 - Early Stopping : Validation loss가 더이상 낮아지지 않을 때

 - Reducing Network size

 - Weight decay

 - dropout

 - Batch normalization

 

Deep Neural Network의 훈련과정은 다음과 같을 것이다.

1. neural network architecture를 설계한다.

  입력 데이터가 1D vector이고 10개의 feature가 있고 5개의 class로 분류하는 경우,

  (input size와 output size는 fix되어 있다.)

2. Train and check that model is over-fitted

  overfitting이 될 때까지 model size를 늘려간다.  (중간의 layer들의 깊이와 넓이는 늘린다)

  --> validation set의 loss가 높아지고 training set의 loss는 줄어들 때 overfitting 지점이다.

  regularization을 추가한다. (drop-out, batch-normalization)한다.

3. step 2를 반복한다.

 

Training and Test Dataset

# 필요한 것들 import
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

# For reproducibility
torch.manual_seed(1)

# set 나누기
x_train = torch.FloatTensor([[1, 2, 1],
                             [1, 3, 2],
                             [1, 3, 4],
                             [1, 5, 5],
                             [1, 7, 5],
                             [1, 2, 5],
                             [1, 6, 6],
                             [1, 7, 7]
                            ])
y_train = torch.LongTensor([2, 2, 2, 1, 1, 1, 0, 0])

x_test = torch.FloatTensor([[2, 1, 1], [3, 1, 2], [3, 3, 4]])
y_test = torch.LongTensor([2, 2, 2])

 

Modeling

class SoftmaxClassifierModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(3, 3) # input 3-> output 3
    def forward(self, x):
        return self.linear(x) #|x| = (m,3) => (m,3)
        
 model = SoftmaxClassifierModel()
 
 # optimizer 설정
optimizer = optim.SGD(model.parameters(), lr=0.1)

def train(model, optimizer, x_train, y_train):
    nb_epochs = 20
    for epoch in range(nb_epochs):

        # H(x) 계산
        prediction = model(x_train) #|x_train| = (m,3) , |prediction| = (m,3)
        

        # cost 계산
        cost = F.cross_entropy(prediction, y_train) #|y_train| = (m,)

        # cost로 H(x) 개선
        optimizer.zero_grad()
        cost.backward()
        optimizer.step()

        print('Epoch {:4d}/{} Cost: {:.6f}'.format(
            epoch, nb_epochs, cost.item()
        ))
  
  
  
def test(model, optimizer, x_test, y_test):
    prediction = model(x_test) #|x_test| = (m',3)  , |prediction| = (m',3)
    predicted_classes = prediction.max(1)[1]
    correct_count = (predicted_classes == y_test).sum().item() # 맞는 것의 개수 셈
    cost = F.cross_entropy(prediction, y_test) # 얼마나 다른지 cross entropy

    print('Accuracy: {}% Cost: {:.6f}'.format(
         correct_count / len(y_test) * 100, cost.item()
    ))
    
train(model, optimizer, x_train, y_train)

test(model, optimizer, x_test, y_test)

 

Learning rate

Learning rate가 너무 크면 발산하면서 cost가 늘어난다. (overshooting)

1번에 비해 2번은 learning rate가 커서 발산하는 경우이다.

 

 

learning rate가 너무 작은 경우, cost가 거의 줄어들지 않는다. (loss가 거의 변하지 않는다.)

 

 

==> 적당한 Learning rate를 설정해야 한다. --> 데이터에 따라 다르다.

발산하면 learning rate 줄이기

너무 loss 값 진전이 없으면 learning rate 키우기

 

 

Data Preprocessing (데이터 전처리)

 

feature가 두 개인 경우, 한 쪽의 feature만 너무 큰 값을 갖게 된다면, 그 feature가 주를 이루어 학습하게 된다.

따라서 , 정규화를 시켜서 같은 범위 내의 숫자로 변경시켜주는 과정이 필요할 수 있다!!

 

 

정규분포를 만들어 데이터를 전처리해주자.

# 데이터
x_train = torch.FloatTensor([[73, 80, 75],
                             [93, 88, 93],
                             [89, 91, 90],
                             [96, 98, 100],
                             [73, 66, 70]]) # |X_train| = (m,3)
y_train = torch.FloatTensor([[152], [185], [180], [196], [142]]) #|Y_train| = (m,)


# 정규화
# Standardization 정규 분포화
mu = x_train.mean(dim=0)
sigma = x_train.std(dim=0)
norm_x_train = (x_train - mu) / sigma
print(norm_x_train)
# 정규화 된 데이터가 출력된다.
# tensor([[-1.0674, -0.3758, -0.8398],
        [ 0.7418,  0.2778,  0.5863],
        [ 0.3799,  0.5229,  0.3486],
        [ 1.0132,  1.0948,  1.1409],
        [-1.0674, -1.5197, -1.2360]])
        

 

정규화된 데이터를 통해 학습을 하자.

class MultivariateLinearRegressionModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(3, 1)

    def forward(self, x):
        return self.linear(x)
        
model = MultivariateLinearRegressionModel()
optimizer = optim.SGD(model.parameters(), lr=1e-1)

def train(model, optimizer, x_train, y_train):
    nb_epochs = 20
    for epoch in range(nb_epochs):

        # H(x) 계산
        prediction = model(x_train) # |X_train| = (m,3) , |prediction| = (m,1)

        # cost 계산
        cost = F.mse_loss(prediction, y_train)

        # cost로 H(x) 개선
        optimizer.zero_grad()
        cost.backward()
        optimizer.step()

        print('Epoch {:4d}/{} Cost: {:.6f}'.format(
            epoch, nb_epochs, cost.item()
        ))
        
train(model, optimizer, norm_x_train, y_train)

train(model, optimizer, norm_x_train, y_train) 
# |y_train| = (m,) 이니까 잘 됨
# |y_train| = (m,2) 이였다면 전처리 없이 사용하였다면 feature 중 큰 값을 갖는 것에 치우지게 된다.
# ==> 똑같은 값의 범위를 갖도록 해주어야 한다.
Comments