3 minute read

Deep_Learning study Lec02 (Pytorch, TensorFlow)

Boostcourse의 ‘파이토치,텐서플로우로 시작하는 딥러닝 기초’를 통한 공부와 정리 Post

Goal of Study

  • 선형회귀(Linear Regression)에 대해 알아본다.

Keyword

  • 선형회귀(Linear Regression)
  • 평균 제곱 오차(Mean Squared Error)
  • 경사하강법(Gradient descent)
  • 가설(Hypothesis)
  • 비용함수(Cost function)

1. 강의 요약

What is Regression?

회귀(Regression)란 데이터들이 전체의 평균으로 되돌아가려는 특징이 있다는 통계적 원리를 설명하는 말이다.
“Regression toward the mean”

Linear Regression

=> 선형 회귀

Linear Regression은 데이터를 가장 잘 대변하는 직선의 방정식을 찾는 것이라고 요약할 수 있다.

위 그림에서 파란색 점들은 데이터를 의미한다.
이 파란색 점들을 가장 잘 대변하는 직선을 긋는다면 이 직선의 모습은 어떻게 되는지가 이 선형 회귀의 핵심이다.

즉, Linear Regression은 데이터들을 가장 잘 대변하는 저 직선의 기울기(a)와 y절편(b)을 결정하는 것이다.

Hypothesis(Linear)

그래서 Linear Regression의 개념을 가지고, 데이터들을 가장 잘 대변할 수 있는 직선을 가정하게 된다.

이를 Hypothesis(가설)라고 하며, 아래와 같은 식으로 표현한다.

Hypothesis function에 대한 추가 개념

이 가설을 데이터를 가장 잘 대변하도록 설정하기 위해서는 어떻게 해야할까? (Which hypothesis would be better?)

Cost

그래서 우리는 W(Weight)와 b(bias)를 데이터를 가장 잘 대변하도록 정하기 위해 비용(Cost)이라는 것을 생각해볼 수 있다.

실제 데이터의 y값과 그 데이터 지점(x)에서의 직선의 방정식의 y값의 차이의 합들이 작을수록 이 직선의 방정식이 데이터를 가장 잘 표현하고 있다고 할 수 있다.

이 때 가설에서 실제 데이터를 뺀 값을 Cost, Error, Loss라고 한다. (빨간색 선)

우리가 하려는 것은 Cost를 최소화하는 방법을 찾는 것이다.

하지만, 이 때 문제가 발생할 수 있는데 Hypothesis와 y(실제 데이터)값의 차이가 음수가 된다면 이 cost를 모두 더하는 것이 무의미해질 수 있다.

Cost Function

=> How to fit the line to our training data

그래서 이 에러값을 제곱하여 사용한다.

보통 많이 쓰는 방법은 에러 값을 제곱하여 평균을 내는 것으로 비용 함수로 많이 사용한다.

목표는 결국 Cost를 최소화하는 것이다.

결론

딥러닝, 머신러닝에서 이야기하는 러닝은 이 Cost를 최소화(minimize)하는 것을 의미한다.

2. 실습

간단한 Linear Regression을 구현해보자.

Data Definition

다음과 같은 Training dataset을 통해 내가 4시간을 공부했을때 몇 점을 받게 되는가? (Dataset과 머신러닝에 관한 기초적 개념은 이전 포스팅를 참고하세요.)

코드 구현

1. 학습을 위한 Data Set

x_train = torch.FloatTensor([[1], [2], [3]])
y_train = torch.FloatTensor([[2], [4], [6]])

입력과 출력을 다른 Tensor에 저장해준다. 입력은 x, 출력은 y로 구분하였다.

2. Hypothesis

위에서 Linear Regression의 Hypothesis의 개념과 그 식을 다루었다. 이를 코드로 나타내기 위해, 먼저 W와 b를 정의해주고 이를 식으로 만들 수 있다.

W = torch.zeros(1, requires_grad = True)
b = torch.zeros(1, requires_grad = True)
hypothesis = x_train * W + b

결론적으로, W와 b를 학습시키는 것이 우리의 목적이다. 여기서 W, b에 사용된 torch.zeros와 그 매개변수들을 설명하자면, 먼저 W와 b를 0으로 초기화 시키는 작업을 선행한다. 즉, 처음에 어떤 입력을 받더라도 출력으로 0을 예측하는 것이다.

이에 대한 이해와 부가적인 설명을 위해, Pytorch의 Docs에서 torch.zeros에 관한 내용을 찾아볼 수 있다.

torch.zeros(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) torch.zeros는 0으로 된 텐서를 만드는 함수이고, size 이외의 Parameter들은 전부 선택사항(Optional)이다.
W는 꼭 0으로 초기화 할 필요가 없다.

size는 텐서의 형태를 결정한다. a by b의 텐서라면 torch.zeros(a, b)라고 적을 수 있다. requires_grad = True 라는 내용은 학습을 할 것이라는 명시이다. boolean 형태로 들어가며, default는 False이다.

3. Compute loss

또한, 위에서 Cost function과 Cost(Loss)에 대한 개념을 알아보았다.

Cost function의 방법으로 다루었던 Mean Squared Error(MSE)를 코드로 표현해보자.

하지만 복잡해보이는 이 수식을 .mean 함수를 사용하여 cost를 구할 수 있다.

cost = torch.mean((hypothesis - y_train) ** 2)

4. 모델 개선 및 Gradient Descent(경사 하강법)

강의 내용에 따라 위의 모델을 개선시켜보자.

먼저 torch.optim 라이브러리에서 SGD(Stochastic Gradient Descent)라는 기법을 사용한다.

강의 내용상 다음 포스팅에서 다룰텐데, 간단히 살펴보면 Loss Function을 계산할 때, 전체 Train set을 사용하는 것을 Batch Gradient Descent라고 한다.

그러나 이렇게 계산하면 한번의 step을 내딛을 때, 전체 데이터에 대해 계산을 해야 하므로, 계산의 양이 상당해 질 수 있다.

이 점을 해결하기 위해, 데이터의 일부를 이용하여 Loss Function을 계산한다. 이 과정에서 Batch Gradient Descent보다는 부정확할 수 있지만, 계산 속도가 훨씬 빠르기에 같은 시간에 더 많은 step을 갈 수 있으며, 이를 반복하며 결과를 수렴시킬 수 있다.

이를, SGD라고 한다.

이 기법에 관해서는 다른 포스팅에서 다루겠다.

다시, SGD를 포함한 코드를 살펴보면

optimizer = optim.SGD([W, b], lr = 0.01)

#항상 붙어 다니는 3줄
optimizer.zero_grad()
cost.backward()
optimizer.step()

W와 b는 학습할 tensor들이며, lr = 0.01은 Learning rate이다.

zero_grad()로 gradient를 초기화하고, backward()로 gradient를 계산한다. 그리고 계산된 gradient의 방향대로 step()을 통해 W, b를 개선한다.

이를 위해 라이브러리를 import하는 것을 잊지말자.

from torch import optim

5. Full training code

import torch
from torch import optim

x_train = torch.FloatTensor([[1], [2], [3]])
y_train = torch.FloatTensor([[2], [4], [6]])

W = torch.zeros(1, requires_grad = True)
b = torch.zeros(1, requires_grad = True)

optimizer = optim.SGD([W, b], lr = 0.01)

nb_epochs = 1000
for epoch in range(1, nb_epochs + 1):
    hypothesis = x_train * W + b
    cost = torch.mean((hypothesis - y_train) ** 2)
    
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()

Leave a comment