Machine Learning Technical

편하게 써보는 ML – 1 – [로또 맞추기]

ML과 같은 복잡한 학문은 연구자의 흥미가 중요합니다. 이 연재는 독자들이 ML에 대한 흥미를 갖을 수 있기를 바라는 마음으로 작성하게 되었습니다.

시작하기에 앞서서…

ML은 활용하기 위해 많은 시간과 노력이 필요한 학문입니다. ML의 알고리즘들은 확률과 통계, 선형대수학 등의 다양한 학문들이 합쳐져서 만들었습니다. 때문에 정확히 이해하려면 많은 수학적 지식들이 필요합니다. 또한 ML 프로그래밍은 기존의 프로그래밍 보다 직관적인 부분이 많고, 결과값을 예측 불가능한 경우가 많습니다. 그래서 반드시 많은 시행착오가 필요합니다.

이처럼 시간과 노력의 투자가 필요한 학문은 연구자의 흥미가 중요하다고 생각합니다. 흥미가 있어야 어려운 분야에 자발적으로 더 파고들게 되기 때문입니다. 그러기 위해 우선은 ML에 익숙해져야 합니다. 쉽고 간단한 문제부터 차근차근 해보며, 막연하게나마 ML이 무엇인지 알아야 학문적인 재미가 붙을 수 있습니다.

이 연재는 독자들이 ML 을 재밌는 학문으로 여겼으면 하는 마음으로 쓰게 되었습니다. 단 한 명이라도 제 글로 인해 ML에 대한 흥미가 생겼다면 성공이라고 생각합니다. 그러기 위해 ML을 편하게 써볼 수 있는 방법을 최대한 편안한 글로 써내려가보도록 하겠습니다.

Machine Learning 시작하기

ML을 수행하는 과정을 간단하게 정리하자면 다음과 같습니다.

  1. 데이터 수집
  2. 데이터 분석
  3. 문제 도출
  4. ML 적용 

ML은 무엇보다도 데이터가 가장 중요합니다. 내가 아무리 풀고 싶은 문제가 있더라도, ML은 데이터가 풀수 있는 문제를 풀어줍니다. 그래서 항상 데이터에 대한 연구를 먼저 진행해야 합니다.

하지만 아무리 뛰어난 ML전문가라고 해도, 이과정이 한 번에 되는 경우는 거의 없습니다. 하물며 우리같은 비 전문가들은 원하는 정답률을 갖는 결과를 얻기 위해 다음과 같은 과정을 수십번 반복하게 될 것입니다.

데이터 수집 -> 데이터 분석 -> 문제 선정 -> ML 적용 -> 데이터 수집 -> 데이터 분석 -> 문제 선정 -> ML 적용 -> 데이터 수집 -> 데이터 분석 -> 문제 선정 -> ML 적용 …

이제부터 각 단계를 하나씩 밟아가면서 ML을 한 번 시작해 보겠습니다.

데이터 수집

처음으로 우리가 다루어볼 데이터는 로또 데이터 입니다. 로또 데이터는 아래의 로또 공식 홈페이지에서 구할 수 있습니다.

동행복권 복권통합포털 : https://dhlottery.co.kr/gameResult.do?method=byWin

사이트에 들어가 당첨결과 메뉴를 찾아가면 각 회차별 당첨 번호가 기록되어 있는 엑셀 형식의 데이터를 얻을 수 있습니다.

하단의 엑셀다운로드 버튼을 누르면 된다.
로또 당첨 번호는 숫자로만 이루어진 ‘정형화’된 깔끔한 데이터이다.

그러면 위 그림과 같이 각각의 회차에 대해서 당첨자수 당첨금, 당점번호가 있는 것을 확인할 수 있을 것입니다. ML에서는 데이터의 형식도 매우 중요합니다. 로또 데이터와 같이 모든 속성이 ‘숫자’인 데이터는 특별한 데이터에 대한 가공이 필요 없기 때문에 굉장히 깔끔하고 다루기 쉬운 데이터라고 볼 수 있습니다.

데이터 분석

이제 수집한 데이터를 한번 분석해보도록 하겠습니다. 데이터 분석의 경우에도 전문적으로 파고들면 한도 끝도 없습니다. 하지만 이 연재는 전문적인 지식은 조금 익숙해진 뒤에 살펴보려고 합니다. 지금은 일상적으로 해석가능한 범위에서만 한 번 분석을 해보고자 합니다. 우리가 현재 수집한 로또 데이터의 특징을 정리해 보면 크게 두 가지가 있습니다.

(1) 각 회차별 1등 당첨 번호’만’을 알 수 있다.

데이터에 있는 번호는 7개의 ‘1등’ 당첨 번호입니다. 이 말은 즉 2, 3,4,5 등 당첨자 또는 꽝 번호는 유추해 볼 수는 있지만, 현재 데이터 자체만으로는 확인 할 수는 없다는 것을 의미합니다. ML은 데이터에 있는 정보만 학습할 수 있습니다. 1등만 존재하는 데이터를 학습하면, 컴퓨터는 이 세상에 1등만 있는줄 알게 됩니다. 이렇게 학습한 컴퓨터에게 새로 2등 데이터를 보여주더라도 ‘등수가 다른 번호’ 라는 것을 깨닳지 못하고, 1등 데이터 중에 다른 특성을 갖고 있는 데이터라고 생각하게 됩니다.

따라서 만약 1등을 다른 등수와 구분하도록 컴퓨터를 가르치고 싶다면, 2, 3등데이터 또는 꽝에 해당하는 실 데이터를 추가해줘야 합니다. 실제 꽝이나 다른 등수의 데이터를 새로 구할 수도 있을 것이고, 사다리타기나 수학적 계산을 하여 임의로 번호를 만들어 넣을 수도 있을 것입니다. 실제 데이터를 구할 수 있다면 최고입니다. 하지만 피치 못하게 데이터를 만들어 넣을 경우, ML의 결과가 실제 데이터와 무관한 결과가 나올 수 도 있습니다.

이는 ML이 생각보다도 엄청 똑똑하게 동작하기 때문입니다. 만약에 수학적으로 넣은 데이터로 학습을 한다면, ML은 데이터를 넣었던 ‘수학 공식’을 찾는 결과를 반환될 수도 있습니다. 물론 로또 번호는 무작위성이 강한 데이터 이므로 수학적으로 계산한거랑 예측율이 비슷할 수 있습니다. 하지만, 수학공식을 계산해낼 꺼면 굳이 비싼 돈 써서 ML을 쓸 필요가 없을 것입니다. 따라서 ML은 가능한한 실 데이터에 기반하도록 설계하는 것이 좋습니다. 물론 강화학습 등 좀 더 깊게 파고 들어가면 다른 얘기를 하게 되지만, 이건 나중에 살펴보도록 하겠습니다.

(2) 각 회차별 1,2,3,4,5 등의 당첨자 수 , 당첨금액을 알 수 있다.

(1)의 경우와 비슷하게, 어떤 번호로 2등을 했고, 3등을 했는지 알 수 없습니다. 그러다보니 1등 당첨자수나 당첨 금액정도만 약간의 의미를 갖게 되는 것을 알 수 있습니다. 하지만, 한 가지 생각해 볼 만한 요소로 당첨금액이 있습니다. 왜냐하면 당첨금액은 당첨자가 없을 경우 금액이 이월되서 커지기 때문입니다. 따라서 시분할 분석이 가능한 Deep Learning 알고리즘인 RNN을 이용해 이 당첨금액 특성을 파고들 경우 어떤 의미가 담긴 결과를 도출할 수도 있을 것입니다.

분석 정리 및 문제 도출

분석 내용을 종합해보았을 때, 현재 구한 데이터만으로는 실제로 로또를 맞출 수 있게 도와주는 ML을 하기에는 어려움이 많이 있습니다. (1)번 특성의 경우 데이터를 만들거나 구해야하며, (2)번 특성의 경우 ML을 넘어서서 Deep Learning의 영역까지 살펴봐야 합니다. 따라서, 다시 데이터를 수집해서 분석하는 작업으로 돌아가야 합니다. 하지만 이 데이터에 대한 내용은 바로 이어지는 2부에서 조금 더 다루도록 하고, 이번 1부에서는 그냥 이 데이터로 바로 ML을 수행해보고 넘어가려고 합니다. 단, 풀 수 있는 문제는 다음과 같이 제한된 조건의 문제 뿐입니다.

문제 : 6개의 당첨 번호를 알고 있을 때, 1개의 당첨 보너스 번호를 찾아보기

이 문제의 경우 조건 모수 자체가 ‘당첨번호’ 이기 때문에, (1)번에서 나타난 문제가 사라지게 되어 주어진 데이터만으로도 ML을 수행할 수 있습니다. 물론 당첨번호를 6개 알고있다고 가정한 것이기 때문에, 실제 로또를 살때 적용할 수 있는 문제는 아닙니다.

MACHINE LEARNING 적용

이 연재에서는 Python 3을 기반으로 ML을 실습해 볼 예정입니다. Python 코드를 실행 할 수만 있다면 어떤 환경이든 크게 상관 없긴 하지만, 필자는 Google Colab을 추천합니다. Google Colab은 google 아이디만 있을경우 바로 웹상에서 Jupyter notebook과 거의 같은 환경으로 Python 기반의 프로그래밍을 할 수 있는 무료 서비스입니다. 무료 서비스 이지만, 실행환경에서 GPU도 지원해주다보니 몇백만원짜리 병렬 계산용 GPU를 설치한 컴퓨터 수준의 성능을 보여줍니다. 앞으로 Deep learning 까지 하다보면 때에따라 아주 긴 학습시간이 필요 할 수 도 있는데, 이 경우 GPU 환경이 매우 유용합니다.

Google Colab은 colab.research.google.com 이 주소로 들어가면 바로 접속 및 튜토리얼이 가능합니다. 또한 google 드라이브로 접근할수도 있습니다.

위와 같이 google 드라이브에서 빈 곳에서 오른쪽 버튼을 클릭한 뒤 더보기 -> google colabration으로 들어가면 됩니다. 이렇게 들어갈 경우 바로 파일까지 생성이 되면서 코드를 쓸 수 있는 창이 뜨게 됩니다. 이제 Colab에도 들어왔으니 바로 코딩을 시작해보도록 하겠습니다. python 문법의 기초적인 부분의 설명은 이 글에서는 생략하려고 합니다.

가장 먼저 해야할 일은 데이터 파일을 읽어 오는 것입니다. DB에 데이터를 넣어두고 연동을 통해 가져오는 방법 도 있고, API를 활용하여 사이트로부터 직접 Json이나 xml로 가져오는 방법도 있지만, 오늘은 가장 간단한 방법인 구글 드라이브에 저장된 .csv 파일로부터 읽어 오는 방법을 사용하려고 합니다.

import pandas as pd     
# pandas 라이브러리 임포트, pandas 라이브러리는 sklearn 이나 tensorflow와 같은 ml 라이브러리에서 사용하기 편하라고 만든 DataFrame이라는 데이터타입을 사용하기 위한 라이브러리입니다.      

import csv     
# csv형식 파일을 다루기 위한 라이브러리 임포트                        

from google.colab import drive
drive.mount('/content/gdrive')
# google 드라이브에 있는 파일을 불러오기 위한 라이브러리

f = open('/content/gdrive/My Drive/lotto_data.csv', 'r', encoding='utf-8')
# 파일스트림 연결, 구글드라이브를 처음 들어갔을때의 가장 루트 디렉토리가 /content/gdrive/My Drive/  입니다. 따라서 이 코드를 그대로 따라하고 싶으실 경우, 데이터 파일이 들어있는 csv 파일을 구글드라이브 최상단, 내드라이브를 눌렀을때 보이는 부분에 넣으시면 됩니다. 


rdr = csv.reader(f)
# 연결된 csv형식 파일 읽기 

dataset = pd.DataFrame(rdr)
# 불러온 데이터를 DataFrame 형태로 변화해서 가져오기
  • from google.colab import drive
    drive.mount(‘/content/gdrive’)

위 코드를 실행하면 URL이 나오는데, URL에 들어가서 구글로그인을 하면 다음과 같이 나옵니다.

이제 허용을 누르면 어떤 코드가 나오게되는데,

google 드라이브와 연결

나온 코드를 위와 같이 입력하면, 이제 colab과 구글 드라이브 폴더가 마운트 되어서 구글드라이브의 파일을 마음대로 사용할 수 있게 됩니다.

  • dataset = pd.DataFrame(rdr)

ML을 하기 위해 데이터를 불러왔다면 DataFrame 형태로 변환하는 것이 좋습니다. 왜냐하면, 칼럼을 추가하거나 열을 다루는 일을 아주 편하게 할 수 있기 때문입니다. 위 코드를 실행할 경우 csv로 부터 불러온 데이터가 DataFrame형식으로 바뀌게 되지만, 아직은 바로 ML 라이브러리에 적용할 수는 없습니다. 현재 상태의 dataset 변수를 출력해보면 다음과 같습니다.

순서대로 데이터가 들어가 있다.

위처럼 데이터가 칼럼명이 없이 순서대로 인덱스가 되어서 들어있습니다. 이럴 경우 데이터에 대한 직관성이 떨어지고, 데이터 조작도 불편하기 때문에 칼럼명을 붙은 형태로 저장하는 것이 좋습니다. 칼럼명을 붙이는 방법은 pandas 라이브러리로 쉽게 만들 수 있습니다. 방법은 여러가지지만, 오늘은 Python 문법이 어색한 분들을 위해서 가장 기초적인 방법으로 한땀한땀 수행해 보겠습니다.

# one이라는 DataFrame 변수를 선언하고 이곳에 dataset에서 '0' 인덱스(최상단 가로 축에있는 숫자 0)에 해당하는 열의 데이터를 모두 추출하여서 저장  

one = pd.DataFrame();
one = dataset[0]


two = pd.DataFrame();
two = dataset[1]

thr= pd.DataFrame();
thr = dataset[2]

fou = pd.DataFrame();
fou = dataset[3]

fiv = pd.DataFrame();
fiv = dataset[4]

num1 = pd.DataFrame();
num1 = dataset[5]

num2 = pd.DataFrame();
num2 = dataset[6]

num3 = pd.DataFrame();
num3 = dataset[7]

num4 = pd.DataFrame();
num4 = dataset[8]

num5 = pd.DataFrame();
num5 = dataset[9]

num6 = pd.DataFrame();
num6 = dataset[10]

num7 = pd.DataFrame();
num7 = dataset[11]
  • one = pd.DataFrame();
    one = dataset[0]

위 코드는 데이터를 열별로 따로 변수에 저장하기 위한 코드입니다. ML을 하다보면 특정 열들 간의 상관관계를 살펴봐야 하는 경우도 있기 때문에 필자는 처음부터 따로 저장해 두는 것을 좋아합니다. 이제 원하는 열들만을 합쳐서 ML라이브러리에서 쓰기위한 데이터 집합(DataSet)을 만들어야 하는데, 그전에 간단하게 ML에서 사용하는 데이터 집합의 종류를 설명하고 넘어가겠습니다.

ML에서는 데이터를 훈련 데이터(Training data)와 시험 데이터(Test data)의 두 가지로 분류해서 사용합니다. 컴퓨터는 훈련데이터로 학습을 수행하여서 기계(Machine)를 만듭니다. 이제 이 기계에 학습했던 데이터와 동일한 형식의 데이터를 넣으면 짠하고 어떤 결과값이 나오게 됩니다. 이때, 만들어진 기계가 얼마나 잘 만들어 졌는지 확인하기 위한 일종의 시험문제를 시험 데이터라고 생각하시면 됩니다.

훈련 데이터와 시험 데이터는 서로 내용은 다르지만, 형식은 동일하도록 구성해야 합니다. 제대로된 시험을 위해서는 컴퓨터가 시험 문제(내용)를 먼저 알면 안되며, 시험 문제가 학습한 내용과 동일한 시험범위(형식)이어야 제대로된 평가가 이루어 질 수 있기 때문입니다. 이번 학습의 경우 시험문제는 따로 만들지 말고 우리가 수집한 데이터를 전부 훈련 데이터로 넣으려고 합니다. 훈련데이터 집합을 만들기 위해 우리가 정의 했던 문제를 다시 살펴 보도록 하겠습니다.

문제 : 6개의 당첨 번호를 알고 있을 때, 1개의 당첨 보너스 번호를 찾아보기

현재 우리는 6 개의 번호를 통해 1개의 보너스 번호를 알 수 있기를 원합니다. 이 말은 결국 6개 번호의 패턴에 따라서 한 개의 보너스 번호가 ‘정해진다’라는 것을 의미합니다. 이 6개의 번호와 보너스 번호의 관계처럼, 어떤 속성 집합의 패턴에 따라 값이 ‘정해지는’ 속성을 클래스 또는 레이블 이라고 합니다. 클래스는 수집된 데이터 속성에서 이미 맺어진 관계를 통해 찾을 수 도 있고, 연구자가 임의로 관계를 가정해서 만들어줄 수 도 있습니다. 전자의 경우가 더 높은 퍼포먼스는 보여주는 경우가 많습니다. 하지만 이번에 우리가 한 건 임의로 6개의 번호와 1개의 번호를 지정한 것이기 때문에 후자의 경우에 해당합니다.

이 클래스는 ML이 데이터를 학습하는 기준으로 작용합니다. 우리는 클래스를 통해 컴퓨터에게 ‘어떤 데이터 패턴은 이걸 말하는 거야!’ 라고 가르칠 수 있기 때문입니다. 물론 ML 알고리즘에 따라 클래스 속성이 필요 없는 경우도 존재하지만, 우리가 오늘 사용하려는 Randomforest 알고리즘의 경우 클래스가 필요한 알고리즘입니다. 그래서 훈련데이터 집합을 만들 때 일반 속성과 클래스 속성을 구분해서 만들어야 합니다.

# 훈련데이터 집합 만들기 

x_data = pd.DataFrame();
x_data["num1"]= num1;

# x_data라는 DataFrame 변수를 선언하고, 이곳에  'num1'이라는 칼럼으로 num1에 들어있는 데이터들을 저장.

x_data["num2"]= num2;
x_data["num3"]= num3;
x_data["num4"]= num4;
x_data["num5"]= num5;
x_data["num6"]= num6;


# 클라스 속성은 따로 저장

y_data = pd.DataFrame();
y_data["num7"] = num7;

위 코드를 통해 훈련데이터를 생성 하였다면 이제 ML 알고리즘에 적용이 가능해집니다. 알고리즘에 대한 자세한 설명도 이후 글에서 하려고 합니다. 오늘은 그냥 바로 써보도록 합시다.

# ML 라이브러리 로드 
from sklearn.ensemble import RandomForestClassifier

# RandomForest 모델을 rf 변수에 할당
rf = RandomForestClassifier(n_estimators=100,oob_score=True,random_state=123456)

# 모델 학습
rf.fit(x_data,y_data )
  • from sklearn.ensemble import RandomForestClassifier

python에서 지원하는 대표적인 ML 라이브러리인 싸이킷런(Scikit-learn)으로 부터 Randomforest라는 ml 알고리즘을 불러오는 구문입니다. 이 싸이킷런 안에는 유명한 ML알고리즘이 최적화 되어서 대부분 들어있습니다. 매개변수만 검색해보고 쓰고싶은 알고리즘을 아무거나 가져다 쓸 수 있습니다.

  • rf.fit(x_data,y_data )

왼쪽에 문제를, 오른쪽에 정답지를 넣으면 됩니다. 위 구문이 실행 되면 이제 rf가 학습된 머신이 되며, 이렇게 학습된 머신을 ‘모델’이라고 부르게 됩니다. 이제 rf에 데이터를 넣으면 학습된 패턴에 따라 어떤 결과값을 보여주게 됩니다.

# 예측하고 싶은 데이터 생성
resultData=pd.DataFrame({"num1":[5],"num2":[22],"num3":[16],"num4":[25],"num5":[4],"num6":[10]})

# 결과값 예측
mlResult = rf.predict(resultData)
print(mlResult)

훈련데이터로 사용한 데이터 집합과 동일한 구조로 데이터를 만들어서 rf.predict 함수에 파라미터로 넣으면 특정 숫자가 출력될 것입니다. 이 숫자가 바로 우리가 입력한 6개의 숫자에 대한 보너스 점수를 예측한 결과값 입니다. 이렇게 결과값이 나옴으로써 이제 하나의 Machine learning이 끝나게 됩니다.

위 예제를 같이 해보며, ML 알고리즘을 다루는 코드는 몇 줄 안되는 것을 확인할 수 있었을 것입니다. 실제로 머신러닝이나 딥러닝 모두 데이터를 분석하고 가공하는 과정이 어렵지 ML알고리즘을 사용하는 것 자체는 매우 간단합니다. 그만큼 ML은 데이터를 다루는게 매우 중요합니다. 다음 2부 에서는 이 데이터를 다루는 부분을 집중적으로 다루려고 합니다. 그때 까지 ML에 대한 흥미가 생기셨기를 바라며 이만 글을 마치도록 하겠습니다.

– ML 1부 끝 –

1 comment

댓글 남기기

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.

%d 블로거가 이것을 좋아합니다: