본문 바로가기

Programming Project/Pytorch Tutorials

Pytorch 머신러닝 튜토리얼 강의 5 (Linear Regression in the PyTorch way)


투명한 기부를 하고싶다면 이 링크로 와보세요! 🥰 (클릭!)

바이낸스(₿) 수수료 평생 20% 할인받는 링크로 가입하기! 🔥 (클릭!)

2018/07/02 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 1 (Overview)

2018/07/02 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 2 (Linear Model)

2018/07/03 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 3 (Gradient Descent)

2018/07/03 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 4 (Back-propagation and Autograd)



이전 글에서는 연산을 통해서 자동으로 그래프를 만들고, 결과적으로 나온 loss에 대해서 .backward()를 통해서 뒤로 보내줌으로써 손쉽게 back propagation을 하는 것을 살펴보았습니다.


텐서들로 이루어진 연산을 수행하는 동안, 자동으로 computational graph가 만들어지고, 마지막으로 구한 loss에서 backward()를 실행함으로써 모든 변수가 loss에 대한 미분값을 .grad.data에 저장하고 있게 되는 것을 이용하였습니다.


하지만 이번 글에서는 더욱 Pytorch 스러운 방법으로 Linear Regression을 하는 법을 배워보도록 하겠습니다.





Pytorch Rhythm (파이토치스러운 설계)



파이토치는 기본적으로 설계하기를, 세가지의 큰 흐름을 따라 설계합니다.


1. 머신러닝 모델을 Variable(파라미터)을 포함한 class로 디자인합니다.

-> 파이토치의 class 개념을 모르신다면.. 다른 java, C++등의 class와 비슷합니다. ㅠㅠ.. 찾아보시길


2. loss를 설계하고 optimizer을 선택합니다.

-> PyTorch 에서 미리 구현해놓은 PyTorchAPI를 통해서 선택 가능합니다.

-> optimizer 은 gradient를 구한 것을 가지고 update를 해주는 역할입니다.

-> 아래에서 좀 더 자세히 다루겠습니다.


3. 트레이닝 사이클을 돌립니다.

-> forward , backward , update 등을 말합니다.






이제 예제를 살펴보면서 하나하나 진행합시다.


이전 글과 같은 데이터를 쓰지만, 행렬식으로써 표현할 수 있게 모양을 바꾸겠습니다.



import torch
from torch.autograd import Variable

x_data = torch.tensor([ [1.0],[2.0],[3.0] ])
y_data = torch.tensor([ [2.0],[4.0],[6.0] ])


그리고 이제 Step 1을 진행 해 봅시다.

자세한 코드에 대한 설명은 주석으로 달아 놓았습니다.






Step 1 : variable을 포함하는 class로 모델 디자인하기


class MyModel(torch.nn.Module):#torch.nn.Module을 상속받음
    #class 생성자 같은 느낌임. 처음 만들어질 때 초기화 해줌. 반드시 필요.
    def __init__(self):
        #부모 class로부터 상속받은 class는 처음 initialize 해줄 때 부모의 init을 해 주어야 한다.
        super(MyModel,self).__init__()

        self.linear = torch.nn.Linear(1,1) #MyModel에 실질적인 연산을 할 모델을 구성하는 부분.
        # 우리는 간단한 모델을 구성할 것이기 때문에 
        # torch API에서 제공하는 torch.nn.Linear만 가지고 우리의 모델을 구성했다.
        # input개수가 한개이고 output 개수도 한개인 Linear model을 만들어주게 된다.
        
    #forward (예측을 수행)하는 함수. 모델을 만들 때 반드시 필요.
    def forward(self,x):
        y_pred = self.linear(x)
        return y_pred
    
model = MyModel() #model이라는 변수에 만든 모델을 넣어준다.


#여기까지가 step 1




Step 2 : Loss를 구하고 Optimizer을 선택하기


#PyTorch API 로부터 loss 를 만들어내기. (이미 있는 loss들 중 선택할 수 있음.)

#criterion : 기준. 어떤 loss를 줄일 것인지에 대해서 명시한다.
criterion = torch.nn.MSELoss(size_average=False) 
# MSELoss는 Mean Squared Error Loss의 줄임말로, 원본과 예측의 차이의 제곱의 평균을 구해준다는 의미를 가진다.
# size_average를 false로 하면 Loss를 발생시키는 것들의 평균으로 나누지 않는다.


optimizer = torch.optim.SGD(model.parameters(),lr=0.01)
#이전 글에서는 optimizer 없이 직접 그냥 뺀 값을 적용 해 주었는데, 
#이번에는 그 과정 대신 optimizer을 사용한다.
#model.parameters()를 통해서 
#우리가 만든 모델의 파라미터들을 옵티마이저에 전달해주면,
#우리가 이전에 gradient를 사용해서 업데이트하던 
#w = w - grad * learning rate 식 같은 것을 자동으로 해 준다.
#단순히 빼기만 해서 하는게 아닌 SGD(stochastic gradient descent) 라는 
#방법을 써서 optimizing을 진행한다. 자세한건 구글링해보자.
#lr = 0.01로 learning rate를 정해줄 수 있다.

criterion에 대해 추가적인 설명이 필요한 것 같아 첨부합니다.


이전 글에서 우리는 loss function을 정의해서 그 loss를 최소화 하는 방향의 파라미터가 정답이라고 생각하고 gradient descent를 진행했습니다.


PyTorch에서는 이미 loss를 다양한 방식으로 정의 해 주고 있습니다.


MSELoss는 그 중에서도 차이의 제곱을 평균내는 Loss이고, 이번에 써볼 Loss이기도 합니다.





Step 3 : 트레이닝 사이클 돌리기


for epoch in range(501):
    # 우리는 모든 x 데이터를 매트릭스(행렬) 형태로 모델에게 넘겨준다.
    y_pred = model(x_data) 
    
    # criterion이라는 함수를 통해서 예측과 정답을 비교하는 평가를 진행한다.
    # 이 때, MSE Loss 를 criterion에 넣었기 때문에 그것을 기준으로 진행하게 된다.
    loss = criterion(y_pred, y_data) 

    if(epoch%100==0):
        print(epoch, loss.data[0])
    
    #gradient descent 직전에 초기화 해주기.
    optimizer.zero_grad() 

    # 구한 loss로부터 back propagation을 통해 각 변수마다 loss에 대한 gradient 를 구해주기
    loss.backward() 
    
    # step()이란 함수를 실행시키면 우리가 미리 선언할 때 
    # 지정해 준 model의 파라미터들이 업데이트 된다.
    optimizer.step() 
    # 이전 글의 기존 for loop을 이용한 방법으로는 데이터를 
    # 한번에 하나씩 살펴봐야 해서 효율적이지 못했지만 이제는 한번에 묶어서 계산한다.
    # 지금 데이터는 3개라 한번에 봐도 문제가 없지만 몇백만개 이상이 되면 문제가 생긴다.
    # SGD를 통해서 업데이트를 진행할 경우에는 mini - batch를 
    # 사용하는 기법을 통해 이를 해결한다. 자세한 방법은 구글링 해 보자.





자 여기까지 따라오셨다면 이제 끝났습니다.


학습이 잘 진행 되던가요? ( loss가 잘 떨어졌나요? )


그렇가면 한번 4시간 공부한 친구를 8점 받을것이라고 예측하나 확인해봅시다.


hour_var = torch.tensor([[4.0]])
print("predict (after training)",4,model.forward(hour_var).data[0][0])

저는 predict (after training) 4 tensor(7.9839) 이라고 결과가 나왔네요!








위 그림은 sung kim님의 강의에서 스샷떠온것인데,


제가 소스 부분을 임의로 수정한 부분이 조금 있기 때문에 소스 내용은 조금 다를 수 있습니다.


여튼, 저 사진을 보시면 우리가 코딩한 저 코드가 3개의 스텝을 제대로 따라갔다는 것을 알 수 있습니다.








숙제입니다.


SGD optimizer만 사용하여 진행하였는데, 다른 옵티마이저도 사용해보도록 하죠.


위의 옵티마이저들 예시가 있으니 적당한거 하나씩 골라잡아서 써보도록 하시기 바랍니다.



옵티마이저가 왜 이렇게 많은가에 대한 의구심이 드실 수 있어, (혹은 뭐가 차이인지 모르겠을 것이므로)


옵티마이저들에 대한 설명이 잘 되어있는 링크 하나 첨부합니다.


http://shuuki4.github.io/deep%20learning/2016/05/20/Gradient-Descent-Algorithm-Overview.html