본문 바로가기
Python

신경망과 회귀분석 비교하기 (Neural Net vs. Regression)

by 슬통이 2020. 7. 22.
반응형

저번 시간 우리는 파이토치에서 신경망을 정의하는 방법에 대하여 알아보았다. 오늘은 정의한 신경망을 어떻게 학습하는가에 대하여 알아보도록 하자. 오늘 우리의 목표는 다음과 같다.

  1. 정의된 신경망의 학습 방법 알기

  2. Activation function에 따른 학습차이 비교

  3. 옵티마이져에 따른 학습차이 비교

  4. 히든 레이어 노드 갯수에 따른 학습차이 비교

위의 효과들을 알아보기 위하여 필자가 만든 학생들의 중간, 기말고사 데이터에 적용된 회귀분석 모델과의 비교를 시도하겠다.

학습 준비 - 데이터 import

이번 포스트에서는 필자가 만들어놓은 가상 데이터를 간단히 설명하면 다음과 같다. 30명 학생들의 정보가 들어있는 데이터이고, id, 성별, 중간고사, 기말고사 성적이 들어있는 데이터이다. 필자의 R을 사용한 통계학이라는 수업에서 사용된 데이터이다. R과 통계학이 궁금하신 분들은 필자의 유튜브도 체크해보시길 바란다. 깨알 홍보. 오늘은 데이터 중에서 중간고사와 기말고사 정보만을 가지고 포스팅을 진행한다.

### R 코드 ###
library(reticulate)

# 데이터 불러오기
mydata <- read.csv("https://www.theissaclee.com/ko/courses/rstat101/examscore2.csv", 
                   header = TRUE)

# 데이터 헤드
head(mydata)
##   student_id gender midterm final
## 1          1      M      62    63
## 2          2      F      60    53
## 3          3      M      60    62
## 4          4      M      30    26
## 5          5      F      80    91
## 6          6      F      33    29
# 중간, 기말고사만 뽑아오기
mydata <- mydata[,3:4]

R을 사용한 데이터 시각화

이 데이터를 학습데이터와 테스트 데이터로 나누고 (학습 데이터 20개, 테스트 데이터 10개), 학습 데이터의 중간고사 사용해서 기말고사 점수를 예측하는 회귀분석 직선을 그려보면 다음과 같다.

 

더보기
### R 코드 ###

# seed 고정
set.seed(1234)
index <- sample(1:30, 30) <= 20

# train vs. test
train_data <- mydata[index,]
test_data <- mydata[!index,]

# plot
library(ggplot2)
pbase <- ggplot(train_data, aes(x = midterm, y = final)) +
  geom_point(color = "#E69F00") +
  labs(title = "학생별 성적분포도",
       caption = "https://statisticsplaybook.tistory.com/",
       x = "중간고사 점수",
       y = "기말고사 점수",
       color = "성별"
       ) +
  theme_linedraw() + ylim(0, 100) + xlim(0, 100) + coord_fixed()

p1 <- pbase +
  geom_smooth(method=lm, se=FALSE, color = "#999999") # 회귀분석 직선 add
p1 

또한, 나중에 비교를 위하여 MSE (mean squared error) 값을 구해놓자.

### R 코드 ###

# 회귀분석
model <- lm(final ~ midterm, train_data)
coefficients(model)
## (Intercept)     midterm 
##   -11.56575     1.18470
# Mean Squared Error for train data
mean((model$residuals)^2)
## [1] 52.46827
# Mean Squared Error for test data
y_hat <- predict(model, test_data)
mean((test_data$final - y_hat)^2)
## [1] 29.75033

reticulate을 이용한 데이터 전달

R에서 데이터를 불러왔으니, reticulate을 통해서 파이썬에서 바로 로딩을 할 수 있다.

### Python ###
r.train_data.head()
##    midterm  final
## 0       60     53
## 1       80     91
## 2       33     29
## 3       32     43
## 4       49     40
r.test_data.head()
##    midterm  final
## 0       62     63
## 1       60     62
## 2       30     26
## 3       88     86
## 4       49     36

파이썬 Numpy, Pandas 사용

혹시 모를 독자를 위하여 파이썬 판다스를 사용한 코드를 남겨놓는다. 필자는 파이썬을 공부한 지가 얼마 되지 않아서 코딩이 깔끔하지 않을 수 있음. 더 좋은 코딩이 있으면 언제든지 댓글로 남겨주시면 좋겠다.

### Python ###

import numpy  as np
import pandas as pd

# 데이터 불러오기
df = pd.read_csv('https://www.theissaclee.com/ko/courses/rstat101/examscore2.csv')

# 데이터 확인
df.head()

# 중간, 기말고사 점수 선택
##    student_id gender  midterm  final
## 0           1      M       62     63
## 1           2      F       60     53
## 2           3      M       60     62
## 3           4      M       30     26
## 4           5      F       80     91
df = df[df.columns[2:4]]

회귀분석 결과 비교를 위하여, 파이썬 코드로 진행하되, R에서 정의한 index 벡터를 불러와 학습 데이터와 테스트 데이터를 동일하게 만들자.

### Python ###

# 파이썬 사용시
# train and test split
# number_assign = np.random.choice(30, 30, replace=False)
# index = number_assign < 20 # < 부호 주의

# R에서 index 벡터 불러와서 같은 학습 데이터셋 만들기
index = np.array(r.index)
train_data = df[index]
test_data = df[~index]
train_data.shape

# 결과 확인
## (20, 2)
test_data.head()
##     midterm  final
## 0        62     63
## 2        60     62
## 3        30     26
## 8        88     86
## 10       49     36
r.test_data.head()
##    midterm  final
## 0       62     63
## 1       60     62
## 2       30     26
## 3       88     86
## 4       49     36

파이토치로 데이터 옮기기

준비된 학습 데이터를 파이토치로 불러온다. 파이토치에서는 데이터의 타입이 float인 것을 기대하기 때문에 torch.FloatTensor()를 사용해서 불러와야 한다. shape을 사용해서 우리가 가지고 있는 데이터의 정보를 신경망 학습에 사용할 변수에 담아오도록 하자.

### Python ###

import torch

# same as torch.tensor(, dtype = torch.float)
X = torch.FloatTensor(train_data['midterm'].values).view(-1,1)
y = torch.FloatTensor(train_data['final'].values).view(-1,1)

test_X = torch.FloatTensor(test_data['midterm'].values).view(-1,1)
test_y = torch.FloatTensor(test_data['final'].values).view(-1,1)

X.shape
## torch.Size([20, 1])
y.shape

# X 샘플 확인
## torch.Size([20, 1])
X[1:5,:]
## tensor([[80.],
##         [33.],
##         [32.],
##         [49.]])

파이토치를 사용한 신경망 정의

위에서 가져온 신경망 정보를 가지고, 이전 포스트에서 정의한 신경망 코드를 사용해서 신경망을 만들어보자. 주의할 점은 nn.Linear()의 기본 옵션이 bias를 포함하고 있다는 것이다. 좀 더 명료하게 구조를 보고 싶다면 bias = True로 설정한 뒤 입력 행령에 1벡터를 붙여서 2행인 매트릭스를 입력하면 된다.

### Python ###

import torch.nn as nn
import torch.nn.functional as F
import torch.optim as opt

class TwoLayerNet(nn.Module):

    def __init__(self, D_in, H, D_out):
        super(TwoLayerNet, self).__init__()
        self.layer2 = nn.Linear(D_in, H)  # bias = True
        self.layer3 = nn.Linear(H, D_out) # bias = True
        
    def forward(self, X, act_fcn):
        z2 = self.layer2(X)
        a2 = act_fcn(z2)
        y_hat = self.layer3(a2)
        return y_hat

참고로 저번 포스팅에서는 F.sigmoid 을 사용했는데, torch.sigmoid으로 바꿈. 돌려보니 설명서에 F. 스타일은 점점 지원하지 않는 중이라고 뜬다.

정의한 TwoLayerNet 클래스를 사용하여 입력 레이어 노드가 1, 히든 레이어 노드가 3, 아웃풋 레이어 노드가 1인 신경망은 다음과 같이 만들 수 있다. 패라미터 값과 shape를 확인해보자. 각각의 레이어에 bias 패러미터 역시 존재한다는 것에 주의.

### Python ###

torch.manual_seed(1234)
## <torch._C.Generator object at 0x7f353641b150>
D_in, H, D_out = 1, 3, 1
testmodel = TwoLayerNet(D_in, H, D_out)

# 패러미터 값 확인
[param.shape for param in testmodel.parameters()]
## [torch.Size([3, 1]), torch.Size([3]), torch.Size([1, 3]), torch.Size([1])]
list(testmodel.parameters())
## [Parameter containing:
## tensor([[-0.9420],
##         [-0.1962],
##         [-0.4803]], requires_grad=True), Parameter containing:
## tensor([-0.2667, -0.8834,  0.4013], requires_grad=True), Parameter containing:
## tensor([[-0.5175, -0.0368,  0.2007]], requires_grad=True), Parameter containing:
## tensor([-0.1946], requires_grad=True)]

신경망 학습하기

신경망을 학습한다는 이야기는 정해진 최적화 함수의 패널티 값을 최소화시키는 패러미터 값을 찾는다는 이야기이다. 따라서 어떤 최적화 함수를 사용하느냐에 따라서 학습 결과가 달라지는 것이 당연한 것이다.

손실 함수와 최적화 방법 선택

파이토치에서는 많은 손실 함수 (loss function)와 최적화 함수 (optimizer)를 모두 제공하는데, 그중 가장 기본적인 손실 함수와 최적화 방법은 MSELossSGD 방법이 있다. 둘은 다음과 같은 방법으로 선언한다.

### Python ###

loss_fn = torch.nn.MSELoss(reduction='mean')
optimizer = torch.optim.SGD(testmodel.parameters(), lr=0.001)

세부적인 내용은 나중에 따로 시간을 내어 파보기로하고, 일단 간단하게 정리만 해보자.

torch.nn.MSELoss()

torch.nn.MSELoss 함수의 경우, 다음의 두 가지 타입 손실함수를 제공한다. reduction 옵션을 sum 설정할 경우 손실함수는 다음과 같다.

\[ L(\hat{\boldsymbol{y}}, \boldsymbol{y}) = \sum_i^{n}(\hat{y_i}-y_i)^2 \] 혹은 reduction 옵션을 mean으로 설정할 경우 손실함수는 MES를 반환한다. \[ L(\hat{\boldsymbol{y}}, \boldsymbol{y}) = \frac{1}{n}\sum_i^{n}(\hat{y_i}-y_i)^2 \]

참고로 none으로 설정시 입력한 두 벡터의 차이의 제곱 값들이 벡터 형식으로 나온다. 앞에 신경망 정의에서 보았듯 히든 레이어를 지날 때, activation 함수를 통과하므로, 로스 값 역시 어떤 activation 함수를 사용하느냐에 따라서 달라질 수 있다는 것을 염두에 두자. 주어진 데이터에 대한 손실 함숫값은 다음과 같이 구할 수 있다.

### Python ###

y_hat = testmodel(X, torch.sigmoid)
loss_fn(y_hat, y)
## tensor(4144.1382, grad_fn=<MseLossBackward>)
y_hat = testmodel(X, torch.tanh)
loss_fn(y_hat, y)
## tensor(4102.7852, grad_fn=<MseLossBackward>)

 

torch.optim.SGD()

최적화 함수에 대하여는 나중에 따로 포스트로 다루겠다. 현재는 torch.optim.SGD가 파이토치에서 제공하는 최적화 함수 중 하나이며, 입력값으로 패라미터와 lr 즉, learning rate를 받는다는 것을 알아두자. learning rate는 신경망 학습 과정에서 중요한 역할을 차지한다. 보통 신경망이 복작해질수록 작은 좀 더 세밀한 탐색을 위해 learning rate를 줄여준다. 하지만, 작은 learning rate는 학습 시간이 길어지게 만든다. learning rate를 정확리 어떻게 정하는지에 대하여는 현재 필자의 지식이 짧아 포스팅은 나중으로 미루겠다.

트레이닝 루프 설정하기

학습을 위한 트레이닝 루프를 설정한다. 코딩은 Deep learning with pytorch 책에서 따와 수정했다.

### Python ###

def training_loop(n_epochs, optimizer, model, act_fcn, lrate,
                  data_X, data_y, test_X, test_y):

    loss_fnc = torch.nn.MSELoss(reduction='mean')
    optimizer = optimizer(model.parameters(), lr=lrate)

    # loss값 저장 벡터
    train_loss = torch.zeros(int(n_epochs/5000)+1)
    test_loss = torch.zeros(int(n_epochs/5000)+1)
    
    for epoch in range(1, n_epochs + 1):
        # 학습 loss 계산 과정
        y_hat = model(data_X, act_fcn)
        loss = loss_fnc(y_hat, data_y)
        
        # 테스팅 과정
        y_hat_val = model(test_X, act_fcn)
        loss_val = loss_fnc(y_hat_val, test_y)
        
        # 학습 과정
        optimizer.zero_grad() 
        loss.backward()
        optimizer.step()
        
        # 5000번째 마다 손실값 확인
        # epoch % 5000 부분: epoch를 5000으로 나눈 나머지
        if epoch == 1 or epoch % 5000 == 0:
            train_loss[int((epoch)/5000)] = loss.item()
            test_loss[int((epoch)/5000)] = loss_val.item()
            print(f"Epoch {epoch}, Training loss {loss.item():.4f},"
                  f"Validataion loss {loss_val.item():.4f},")
    
    with torch.no_grad():
        X_plot = torch.linspace(start=0, end=100, steps=100).view(-1, 1)
        y_plot = model(X_plot, act_fcn)

    return y_plot

학습이 일어나는 부분은 다음의 코드 세 줄이다.

# optimizer.zero_grad() 
# loss.backward()
# optimizer.step()

optimizer.zero_grad() 이전 스탭에서 사용하던 결과값들을 리셋해주는 코드라고 생각하면 되고, loss.backward()는 기울기값을 구하는 과정, 그리고, optimizer.step()은 패라미터 업데이트 과정이라고 생각하면 된다.

두 개의 신경망 모델

앞선 신경망을 정의하는 코드를 사용해서 두 개의 모델을 설정하도록 하겠다.

  1. model1: 신경망의 히든 레이어의 노드가 3개인 경우
  2. model2: 신경망의 히든 레이어의 노드가 13개인 경우
### Python ###

model1 = TwoLayerNet(1, 3, 1)
model2 = TwoLayerNet(1, 13, 1)

두 개의 모델이 어떻게 학습하는지를 비교함으로써, 신경망에서의 노드 개수가 얼마나 중요한지 알 수 있을 것이다.

학습결과

Model 1 vs. Model 2

Model 1은 히든 레이어의 노드가 3개인 신경망이었다.

### Python ###

torch.manual_seed(2020)
## <torch._C.Generator object at 0x7f353641b150>
D_in, H, D_out = 1, 3, 1
model1 = TwoLayerNet(D_in, H, D_out)

m1_y_hat = training_loop(n_epochs = 50000,
                         optimizer = opt.SGD,
                         model = model1,
                         act_fcn = torch.sigmoid,
                         lrate = 1e-5,
                         data_X = X, data_y = y,
                         test_X = test_X, test_y = test_y)
## Epoch 1, Training loss 4136.3115,Validataion loss 3552.9165,
## Epoch 5000, Training loss 2585.4973,Validataion loss 2094.9519,
## Epoch 10000, Training loss 1736.9565,Validataion loss 1314.9857,
## Epoch 15000, Training loss 1271.2430,Validataion loss 900.0759,
## Epoch 20000, Training loss 997.2466,Validataion loss 669.9962,
## Epoch 25000, Training loss 816.5131,Validataion loss 527.4304,
## Epoch 30000, Training loss 681.2778,Validataion loss 426.4737,
## Epoch 35000, Training loss 566.3116,Validataion loss 342.7260,
## Epoch 40000, Training loss 468.0708,Validataion loss 271.9267,
## Epoch 45000, Training loss 387.2747,Validataion loss 214.6450,
## Epoch 50000, Training loss 322.0588,Validataion loss 169.5488,
m1_y_hat =  m1_y_hat.numpy()

Model 2는 히든 레이어의 노드가 13개인 좀 더 넓은 신경망이다.

### Python ###

torch.manual_seed(2020)
## <torch._C.Generator object at 0x7f353641b150>
D_in, H, D_out = 1, 13, 1
model2 = TwoLayerNet(D_in, H, D_out)

m2_y_hat = training_loop(n_epochs = 50000,
                         optimizer = opt.SGD,
                         model = model2,
                         act_fcn = torch.sigmoid,
                         lrate = 1e-5,
                         data_X = X, data_y = y,
                         test_X = test_X, test_y = test_y)
## Epoch 1, Training loss 4135.0889,Validataion loss 3552.0615,
## Epoch 5000, Training loss 1269.8047,Validataion loss 898.8235,
## Epoch 10000, Training loss 749.3973,Validataion loss 478.0402,
## Epoch 15000, Training loss 604.5557,Validataion loss 384.9201,
## Epoch 20000, Training loss 521.5139,Validataion loss 335.7497,
## Epoch 25000, Training loss 432.6310,Validataion loss 277.5165,
## Epoch 30000, Training loss 357.1343,Validataion loss 228.0457,
## Epoch 35000, Training loss 290.0260,Validataion loss 183.3068,
## Epoch 40000, Training loss 233.8944,Validataion loss 145.7346,
## Epoch 45000, Training loss 188.9943,Validataion loss 115.7470,
## Epoch 50000, Training loss 153.9906,Validataion loss 92.4611,
m2_y_hat =  m2_y_hat.numpy()

학습 결과를 R로 빼기 위해서 m1_y_hat, m2_y_hat 텐서를 numpy 행렬로 저장시켰다.

R에서의 시각화

더보기
### R 코드 ###

pbase + 
  # model 1: red
  geom_line(data = data.frame(x=1:100, y=py$m1_y_hat),
            aes(x=x, y=y), col = "red") +
  # model 1: blue
  geom_line(data = data.frame(x=1:100, y=py$m2_y_hat),
            aes(x=x, y=y), col = "blue") +
  labs(title = "Node 갯수에 따른 모델별 학습결과 비교",
       subtitle = "모델 1 (빨간색) vs. 모델 2 (파란색)",
       tag = "Figure 1")

같은 epoch 기준으로 노드 갯수가 많은 (혹은 넓은) 신경망쪽이 적합이 더 잘 됨. train loss도 더 빨리 떨어졌다. 학습이 진행됨에 따라서 파란선과 빨간선의 기울기가 더 가파르게 될 것으로 예상한다.

Activation 함수에 따른 학습 결과 변화

이번에는 모델 2를 기준으로, activation 함수를 torch.tanh로 변화시켜보자. sigmoid 함수의 경우 0과 1사이의 값을 갖는 반면에 이 함수는 -1과 1사이의 값을 갖는다. sigmoid 함수를 위아래도 늘려놨다고 생각하면 된다. 비슷한 형태에 커버 범위가 넓은 함수인만큼, 학습이 더 빨리 될 것이라 생각한다.

### Python ###

torch.manual_seed(2020)
## <torch._C.Generator object at 0x7f353641b150>
m3_y_hat = training_loop(n_epochs = 50000,
                         optimizer = opt.SGD,
                         model = model2,
                         act_fcn = torch.tanh,
                         lrate = 1e-5,
                         data_X = X, data_y = y,
                         test_X = test_X, test_y = test_y)
## Epoch 1, Training loss 706.0967,Validataion loss 510.9811,
## Epoch 5000, Training loss 131.9696,Validataion loss 81.1063,
## Epoch 10000, Training loss 74.6601,Validataion loss 43.3035,
## Epoch 15000, Training loss 33.6046,Validataion loss 9.4184,
## Epoch 20000, Training loss 27.6527,Validataion loss 10.3907,
## Epoch 25000, Training loss 25.4622,Validataion loss 11.3635,
## Epoch 30000, Training loss 24.4035,Validataion loss 12.1903,
## Epoch 35000, Training loss 25.0119,Validataion loss 17.0187,
## Epoch 40000, Training loss 24.9847,Validataion loss 12.7971,
## Epoch 45000, Training loss 26.3041,Validataion loss 14.5403,
## Epoch 50000, Training loss 24.5741,Validataion loss 18.8128,
m3_y_hat =  m3_y_hat.numpy()
더보기
### R 코드 ###

pbase + 
  # model 1: red
  geom_line(data = data.frame(x=1:100, y=py$m2_y_hat),
            aes(x=x, y=y), col = "red") +
  # model 1: blue
  geom_line(data = data.frame(x=1:100, y=py$m3_y_hat),
            aes(x=x, y=y), col = "blue") +
  labs(title = "Activation 함수에 따른 학습결과 비교",
       subtitle = "Sigmoid (빨간색) vs. Tanh (파란색)",
       tag = "Figure 2") + ylim(0, 100) + coord_fixed()

예상대로 sigmoid보다 tanh 함수가 어떤 non-linear한 패턴을 approximation 하는 데 있어서 더 용이한 것 같다.

Optimizer에 따른 학습 결과 변화

이번에는 Optimizer를 바꿔보았다. 모델 2를 기준으로, activation 함수는 tanh로 고정하고, SGD와 Adam 옵티마이져의 학습 결과를 비교해보자. Adam에 대한 내용은 지금은 링크로 대체한다. 하지만 유명한 학습방법이니만큼, 다시 돌아와서 공부하도록 하자.

### Python ###

torch.manual_seed(2020)
## <torch._C.Generator object at 0x7f353641b150>
m4_y_hat = training_loop(n_epochs = 50000,
                         optimizer = opt.Adam,
                         model = model2,
                         act_fcn = torch.tanh,
                         lrate = 1e-5,
                         data_X = X, data_y = y,
                         test_X = test_X, test_y = test_y)
## Epoch 1, Training loss 25.4116,Validataion loss 13.9119,
## Epoch 5000, Training loss 22.7715,Validataion loss 14.0925,
## Epoch 10000, Training loss 22.5335,Validataion loss 14.2756,
## Epoch 15000, Training loss 22.3893,Validataion loss 14.4757,
## Epoch 20000, Training loss 22.3084,Validataion loss 14.5140,
## Epoch 25000, Training loss 22.2397,Validataion loss 14.4383,
## Epoch 30000, Training loss 22.1762,Validataion loss 14.3639,
## Epoch 35000, Training loss 22.1167,Validataion loss 14.3038,
## Epoch 40000, Training loss 22.0581,Validataion loss 14.2472,
## Epoch 45000, Training loss 22.0004,Validataion loss 14.1833,
## Epoch 50000, Training loss 21.9435,Validataion loss 14.1143,
m4_y_hat =  m4_y_hat.numpy()
더보기
### R 코드 ###

pbase + 
  # model 1: red
  geom_line(data = data.frame(x=1:100, y=py$m3_y_hat),
            aes(x=x, y=y), col = "red") +
  # model 1: blue
  geom_line(data = data.frame(x=1:100, y=py$m4_y_hat),
            aes(x=x, y=y), col = "blue") +
  labs(title = "Optimizer에 따른 학습결과 비교",
       subtitle = "SGD (빨간색) vs. ADAM (파란색)",
       tag = "Figure 3") + ylim(0, 100) + coord_fixed()

SGD보다 Adam optimizer가 학습이 더 잘 됨. 하지만 학습할 때의 로스 값을 보면 20000 epoch가 넘어가면서부터 과적합되는 경향이 있음.

최종 모델과 회귀분석 모델 비교

최종 학습 모델은 tanh 함수와 SGD 최적화 학습방법 쌍으로 정했다. 그리고 epoch값은 2000으로 설정했다. 이유는 학습할 때의 테스트 MSE가 가장 낮아져서 이다. 같은 조건의 Adam보다 더 낮게 내려갔다가 올라옴. 전형적인 잘 학습되다가 과적합되는 패턴이라서 과적합이 시작되는 그 부분에서 멈추도록 학습시켰다. 

### Python ###

torch.manual_seed(2020)
## <torch._C.Generator object at 0x7f353641b150>
final_y_hat = training_loop(n_epochs = 20000,
                         optimizer = opt.SGD,
                         model = model2,
                         act_fcn = torch.tanh,
                         lrate = 1e-5,
                         data_X = X, data_y = y,
                         test_X = test_X, test_y = test_y)
## Epoch 1, Training loss 21.9435,Validataion loss 14.1143,
## Epoch 5000, Training loss 22.1821,Validataion loss 15.4219,
## Epoch 10000, Training loss 22.1050,Validataion loss 15.2153,
## Epoch 15000, Training loss 22.0465,Validataion loss 15.0625,
## Epoch 20000, Training loss 22.0049,Validataion loss 14.9665,
final_y_hat =  final_y_hat.numpy()
더보기
### R 코드 ###

pbase + 
  # model 1: red
  geom_line(data = data.frame(x=1:100, y=py$final_y_hat),
            aes(x=x, y=y), col = "red") +
  geom_smooth(method=lm, se=FALSE, color = "#999999") + # 회귀분석 직선 add
  labs(title = "회귀분석과 신경망 학습결과 비교",
       subtitle = "회귀직선 (회색) vs. 신경망 (빨간색)",
       tag = "Figure 4") + ylim(0, 100) + coord_fixed()

최종 신경망 모델과 회귀분석 모델을 비교해보면 위와 같다. 일단 회귀분석 직선도 데이터의 추세를 잘 잡아낸다. 하지만 신경망 모델이 상위권 학생들의 점수 분포를 더 잘 잡아내도록 학습이 되었다. 테스트 데이터 기준으로 회귀분석의 MSE가 29.7이고, 학습된 신경망으로 계산한 테스트 데이터의 MSE가 15.6 근처이므로 최종 신경망 모델 승. 하지만 학습에 따라 모델이 과적합 되어있을 가능성을 배제할 수 없다. 항상 학습할 때 과적합을 체크하는 방법, 혹은 과적합을 방지하며 학습시키는 방법이 필요함. 이러한 방법은 나중에 다시 다뤄보고, 오늘은 여기까지 끝.

참고자료

1. 파이토치 튜토리얼: https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#define-the-network

2. Deep Learning with PyTorch, Eli Stevens et al. (2020)


아래는 현재 검색 가능한 파이토치 딥러닝 책 광고입니다! 파트너스 활동을 통해서 일정액의 수수료를 받을 수 있다고 하네요.ㅎㅎ 언젠가 제가 쓰는 이 블로그도 저 자리에 끼어있었으면 좋겠네요ㅎㅎ 밑에 책들은 한번 사서 읽어보고, 리뷰를 올려보도록 하겠습니다. =]

 

파이토치 첫걸음:딥러닝 기초부터 RNN 오토인코더 GAN 실전 기법까지, 한빛미디어 펭귄브로의 3분 딥러닝 파이토치맛:PyTorch 코드로 맛보는, 한빛미디어 딥러닝에 목마른 사람들을 위한 PyTorch:개인용 GPU 학습 서버 구축부터 딥러닝까지, 비제이퍼블릭 PyTorch로 시작하는 딥러닝:딥러닝 기초에서 최신 모던 아키텍처까지, 에이콘출판 [제이펍] 파이토치 첫걸음

반응형

댓글