본문 바로가기

Programmer Jinyo/Machine Learning

Pytorch 초보를 위한 튜토리얼 강의 1 ( linear regression, SVM Loss Function)


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

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

이 글은 


2018/06/29 - [Programmer Jinyo/Machine Learning] - 머신러닝,딥러닝 초보를 위한 튜토리얼 강의 4 ( linear classification , SVM Loss Function)

에서 이어진다.


이번 글에서는 Linear classifier을 SVM Loss와 함께 Pytorch를 이용해 구현해보도록 하겠다.


이 글에서는 train data, test data, validation data를 따로 나누지 않고 하나의 데이터로 진행한다. 사전 지식이 있는 독자들의 경우에는 특이하다고 느낄 수 있겠지만, 기본적인 사용법을 배우는 것이 목적인 데다가, 아직 해당 부분을 이론적으로 다루지 않아서 그렇다. )




Pytorch


Pytorch는 Python상에서 돌아가는 오픈소스 머신러닝 라이브러이이다.

Pytorch를 이용해서 프로그래밍을 진행하게 되면 엄청 손쉽게 이미 알려진 딥러닝 모델을 유연하게 구현할 수 있을 뿐더러, 보통의 프로그래밍으로는 GPU를 써서 머신러닝을 가속화시키기가 쉽지 않은데 Pytorch는 내부적으로 그것을 가능하게 해놓았다.


정리하자면 다음과 같다.

1. GPU를 이용한 빠른 연산을 가능하게 함.

2. Model 자체를 구현하기에도 유연하며 빠름.




설치


설치는 다양한 환경에서 다양한 방식으로 이루어 질 수 있으므로 본 글에서 다루기에는 조금 큰 주제인 것 같아서, 개인적으로 검색해서 설치를 마치고 오는 것을 추천한다. (파이토치 설치라던가 하는 식으로 검색)


참고로 필자는 pytorch를 install 이전에 아나콘다를 이용해 기본적인 라이브러리(numpy 등)를 인스톨했고, jupyter notebook을 통해서 코딩을 진행한다.


여러 라이브러리들을 install하는데에 큰 어려움이 없길 빌면서 ... ㅎㅎ


(사실 이 부분만 마치고 와도 몇시간이 지날 것으로 예상한다)

(찾아보면 많은 링크가 나온다 http://bob3rdnewbie.tistory.com/313?category=780658 )



+ 주의 : 이 튜토리얼의 코드는 pytorch 1.2.0 버전 이상으로 하는 중이다.

+ pandas numpy 등등의 라이브러리도 install 해야 한다.





데이터


좀 재미있었으면 좋겠어서, 남들 다 하는거 말고 신선한 데이터로 재밌는 학습을 진행하려고 한다.


다음 URL로 들어가서 이번 실습에 쓸 데이터를 다운받자.


https://www.kaggle.com/tadhgfitzgerald/fifa-international-soccer-mens-ranking-1993now


피파 1993년부터 지금까지의 나라별 랭킹 변화 데이터이다.

한국의 미래 랭킹을 예측해보자.




from pandas import Series, DataFrame
import math
import torch
import torch.nn as nn
import numpy as np
import torch.nn.functional as F
import pandas as pd
import csv


임포트 할 친구들 임포트 해 주고


data = [] with open('fifa_ranking.csv', 'r', encoding='utf-8') as csvfile: rdr = csv.reader(csvfile) for row in rdr: data.append(row)


데이터를 위와 같이 읽어준다.


읽어들이고 나면


[['rank', 'country_full', 'country_abrv', 'total_points', 'previous_points', 'rank_change', 'cur_year_avg', 'cur_year_avg_weighted', 'last_year_avg', 'last_year_avg_weighted', 'two_year_ago_avg', 'two_year_ago_weighted', 'three_year_ago_avg', 'three_year_ago_weighted', 'confederation', 'rank_date'] ['1', 'Germany', 'GER', '0.0', '57', '0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'UEFA', '1993-08-08'] ['2', 'Italy', 'ITA', '0.0', '57', '0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'UEFA', '1993-08-08'] ['3', 'Switzerland', 'SUI', '0.0', '50', '9', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'UEFA', '1993-08-08'] ['4', 'Sweden', 'SWE', '0.0', '55', '0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'UEFA', '1993-08-08'] ['5', 'Argentina', 'ARG', '0.0', '51', '5', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'CONMEBOL', '1993-08-08'] ['6', 'Republic of Ireland', 'IRL', '0.0', '54', '0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'UEFA', '1993-08-08'] ['7', 'Russia', 'RUS', '0.0', '52', '1', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'UEFA', '1993-08-08'] ['8', 'Brazil', 'BRA', '0.0', '55', '-5', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'CONMEBOL', '1993-08-08'] ['9', 'Norway', 'NOR', '0.0', '49', '5', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'UEFA', '1993-08-08']

.......


이런식의 파일 내용이 존재한다.


label = data[0]


이렇게 레이블만 저장해놓은 다음에


kor_data = [x for x in data if x[2]=='KOR']

이렇게 kor_data에 대한 정보만 따로 불러오자.

(python 의 list comprehension 이라는 기능이다)


이제 우리의 모델을 정의하자.


class PredModel(nn.Module):
    def __init__(self, D_in,D_out):
        super(PredModel, self).__init__()
        self.linear1 = torch.nn.Linear(D_in,D_out)
        
    def forward(self,x):
        out = self.linear1(x)
        return out

우선 파이토치에 기본적으로 필요한 것은 nn.Module을 상속받는 class이다.

nn.Module을 상속받으면 class안에 model의 명세를 적어놓을 수 있다.


이제 저번 글에서 다뤘던 Linear model을 pytorch로 한번 구현해보도록 하자.

의외로 간단한데, init시에 torch.nn.Linear(입력개수,출력개수)의 형태로 넣어주면 된다.


그리고 꼭 정의해줘야 하는 forward 함수는 입력을 통해 출력을 뱉는 (즉 f(x)를 적용하는) 과정을 수행 해 준다.

(스칼라의 apply()같은 느낌)

이를 통해 모델 계산을 쭉 할 수 있게 된다.


model = PredModel(5,1) # 5개의 이전 대회의 성적을 입력받아서 1개의 다음 대회의 예측 output을 내보낸다.
criterion = torch.nn.MSELoss(reduction='sum') # 
optimizer = torch.optim.SGD(model.parameters(), lr=1e-5) # 

우리의 모델은 이전 5개의 랭킹 결과를 입력받아 바로 다음의 랭킹 결과를 예측하는 모델을 작성하는 것으로 하자.


MSE Loss라는 것과 SGD optimizer에 대해서는 아직 공부하지 않았지만 링크를 첨부한다.


MSE Loss는 새로운 loss function이라고 생각하면 되고 optimizer의 경우에는 파라미터의 값을 더 최적의 값이 나올 수 있도록 변화시켜가는 기준에 대한 설정이다.


MSE Loss : https://m.blog.naver.com/wideeyed/221025759001




for epoch in range (5):
    for i in range(len(kor_data)-5):
        x = torch.FloatTensor([kor_data[i:i+5]])
        
        y = torch.FloatTensor([[kor_data[i+5]]])
        # 우리 모델의 예측값
        y_pred = model(x) 
        
        # loss를 구하기.
        loss = criterion(y_pred, y)
        print(epoch, loss.item())

        # 변화도를 0으로 만들고, 역전파 단계를 수행하고, 가중치를 갱신합니다.
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

그럼 이제 트레이닝을 할 차례다.


epoch란 전체 데이터 세트를 몇번 반복할 것이냐라는 말이고 그 아래에 kor_data를 반복한다.


x = torch.FloatTensor(~~~)을 통해서 kor_data를 pytorch가 연산 가능한 tensor로 바꿔준다.

y도 마찬가지.


이제 x와 y는 입력과 출력이 되며 우리는 모델에게 model(x)를 통해서 모델의 예측값을 물어볼 수 있다.


그리고 이제 loss를 그 아래에서 구해준다.


이를 통해 마지막으로 loss.backward()를 통해서 에러를 줄이는 방향으로 학습하게 된다.


출력 결과는 아래와 같다.


0 3603.92724609375
0 2433.343994140625
0 1652.0155029296875
0 991.7066040039062
0 648.6072998046875
0 488.1907653808594
0 420.95660400390625
0 268.98089599609375
0 161.2364959716797
0 152.42730712890625
0 68.49036407470703
0 99.84678649902344
0 142.9169158935547
0 105.57722473144531
0 114.7032241821289
0 113.0716323852539
0 22.381593704223633
0 152.4935302734375
0 64.8158187866211
0 9.551613807678223
0 51.450401306152344
0 214.40521240234375
0 85.67092895507812
0 80.49425506591797
0 61.5733757019043
0 366.0848083496094
0 193.86151123046875
0 6.185337543487549
0 21.345834732055664
0 24.440649032592773
0 0.022126654163002968
0 67.62142181396484
0 21.048635482788086
0 10.248673439025879
0 0.019226714968681335
0 23.47830581665039
0 18.863590240478516
0 18.30381202697754
0 0.22507303953170776
0 21.219249725341797
0 111.88397979736328
0 15.50606918334961
0 3.278964042663574
0 1.9639208316802979
0 2.3613333702087402
0 3.6669070720672607
0 0.657988429069519
0 1.2695763111114502
0 1.1813905239105225
0 0.1724046915769577
0 319.1641540527344
0 360.2665100097656
0 168.76145935058594
0 130.8247833251953
0 0.07770019769668579
0 8.448528289794922
0 2.9515974521636963
0 2.8194024562835693
0 11.102482795715332
0 0.32785478234291077
0 0.7443063855171204
0 96.86847686767578
0 83.38269805908203
0 2.5420823097229004
0 54.64665985107422
0 117.73480224609375
0 111.76239776611328
0 11.729000091552734
0 11.221953392028809
0 13.309175491333008
0 32.620513916015625
0 46.60224533081055
0 0.029043521732091904
0 0.19807904958724976
0 1.8900794982910156
0 0.8984399437904358
0 1.4736772775650024
0 0.037983234971761703
0 1.31890869140625
0 13.841985702514648
0 0.30349868535995483
0 17.68707847595215
0 25.253936767578125
0 12.895415306091309
0 1.6975045204162598
0 2.259451389312744
0 3.779789447784424
0 4.760488033294678
0 2.980478048324585
0 0.27851402759552
0 1.4968571662902832
0 349.3695373535156
0 296.3369140625
0 61.60445022583008
0 29.76081085205078
0 5.371606826782227
0 8.663768768310547
0 11.050873756408691
0 12.880446434020996
0 6.050131797790527


이런 식인데, 에러가 점점 줄어드는걸 볼 수 있다.


마지막으로 학습이 끝나고 우리의 모델이 어떻게 예측하는지를 한번 살펴보자


x_test = torch.FloatTensor([[2,3,4,5,6]])
y_pred = model(x_test)
y_pred

2 3 4 5 6등인 랭킹을 가진 나라는 다음 달에 어떤 랭킹을 가질까?


tensor([[4.1512]], grad_fn=<ThAddmmBackward>)

내 모델은 이라는 결과를 냈다.



80등 이런 말 안하는걸 보니 학습이 잘 됐나보다.




끗 -



* 이 글 시리즈는 당분간 더이상 쓰지 않을 것 같습니다.


Sung kim님의 pytorch zero to all 강의 영상을 번역 해 놓은


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


에서 다시 시작해보시기 바래요!