[로또 결과 예측] 기계학습 기반 로또 결과예측 프로그램 개발하기(미완)

류명운

·

2016. 10. 1. 02:30

반응형

[로또 결과 예측] 기계학습 기반 로또 결과예측 프로그램 개발하기(미완)

기계학습 기반 로또 결과예측 프로그램을 개발해보고 싶은 마음에 컴퓨터를 켰다. 매달 적게는 1회 많게는 2~3회 구입하는 로또.. 이번에 좋은 기회가되서 기계학습을 어느정도 할줄 알게되었으니 내가 필요한 프로그램을 만들어봐야겠다.

시작하기에 앞서, 본인은 본 프로젝트의 최종 결과 값인 학습 후 분류의 정확도에 대한 확신 같은 게 있어서 시작한게 아니라는 것을 알리고 싶다.

1등, 2등, 3등, 4등, 5등, 꽝에 대한 학습을 할 것인데 1등에 해당하는 당첨번호 데이터셋이 700회(누적회차 수)?정도 라면 꽝에 해당하는 데이터는 58억개쯤..? 애초에 각 분류의 학습 양이 너무 다르기 때문에.. 

"그냥 앞으로의 인공지능 즉, 기계가 인간을 위협한다는데... 그렇게 대단한 기계라면 그리고 현재 그 정점에 있는 기술인 머신러닝이라면 인간의 두뇌로는 알아차리지 못한 특수한 영역에 대해 알아낼 수 있지 않을까?"

그리하여.. 적합한 주제를 찾던 중 인간인 내가 판단할때 로또 당첨번호에 대한 기준은 존재하지 않고 단지 운이라고 생각하는데, 혹시나 머신러닝은 당첨번호 혹은 꽝에 대한 역대 번호를 학습하여 미래의 당첨번호 혹은 꽝에 대한 분류 기준을 도출해낼 수 있지 않을까? 라는 생각에 무작정 시작하게 되었다. 분명 원하는 결과값은 도출해내지 못할거라는 생각이 머릿속에 대부분이지만, 직접 두 눈으로 확인하고 싶은 마음이 더 크기에 앞으로 시간이 날때마다 조금씩 프로젝트를 수행해보도록 하겠다.

 

대충 누워서 머릿속으로 기획해본 전체적인 구조..(추후에 진행하면서 수정)

  • 플랫폼 : Web
  • Front-End : Bootstrap/nodejs
  • Back-End : Java, MongoDB
  • 언어 : Java
  • 인프라 : AWS EC2 - Linux(Ubuntu) - Apache Hadoop 2.0 YARN
  • 머신러닝 프레임워크 : Apache Spark Mllib
  • 머신러닝 모델 : LogisticRegression

우선, 포스팅은 정리가 안된 자료들을 남기다가 어느정도 아웃풋이 나오면 다듬도록 하겠다.

진행 중인 소스코드는 https://github.com/myeonguni/LottoMachine (깃허브) 원격 저장소를 참고하면 된다.

 

1. 기계학습에 사용될 데이터 셋 만들기

우선 가장먼저 작업할 내역은 기계학습을 위한 데이터를 구하는 것이다. 데이터는 총 6가지의 분류로 나뉘어 기계학습을 진행할 계획이며 이에 해당하는 분류는 다음과 같다.

  • 1등 당첨번호
  • 2등 당첨번호
  • 3등 당첨번호
  • 4등 당첨번호
  • 5등 당첨번호
  • 꽝 번호

데이터는 로또 공식 홈페이지에서 제공해주는 각 회차별 당첨결과 값을 파싱해서 필요한 부분(당첨 숫자 6개 + 보너스 숫자 1개)만을 가져다가 위에서 제시한 분류를 도출해내는 알고리즘을 작성하여 데이터 셋을 만든 뒤 기계학습에 사용되는 포맷(.CSV)으로 가공하는 작업을 진행해야 겠다. 이에 대한 작업 과정은 다음과 같다.

  • 필요한 데이터만 뽑아내기(파싱 및 문자열처리)
  • 위에서 뽑아낸 데이터를 파일에 처리(출력)하기

 

1. 1 필요한 데이터만 뽑아내기

우선, 먼저 필요한 데이터를 뽑아내는 작업 과정을 살펴보겠다. 본 작업에 사용될 로또 공식 사이트는 다음과 같다.

위 사이트를 들어가 확인해보니 엄청난 수의 데이터가 추출될 것 같다. 대략적으로 계산해본 실제 회차별 1~5등의 당첨번호와 꽝에 해당하는 번호에 대한 수와 누적 회차(16-09-27 기준, 총 721회)를 고려한 데이터의 수는 다음과 같다(계산법 포함).

* 당첨번호 수 계산법(C는 Combination의 약어로 사용)

  • 1등 6C6 = 6!/(0!*6!) = 1
  • 2등 6C5 = 6!/(1!*5!) = 6
  • 3등 (6C5)*(38C1) = (6!/(1!*5!))*(38!/(37!*1!)) = 228
  • 4등 (6C4)*(39C2) = (6!/(2!*4!))*(39!/(37!*2!)) = 11115
  • 5등 (6C3)*(39C3) = (6!/(3!*3!))*(39!/(36!*3!)) = 182780

각 회차 별 당첨번호 데이터 수(공통 사항)

  • 1등 당첨번호 - 1개
  • 2등 당첨번호 - 6개
  • 3등 당첨번호 - 228개
  • 4등 당첨번호 - 11,115개
  • 5등 당첨번호 - 182,780개
  • 꽝 번호 - 7,950,930개
(잡담)실제 계산해보니.. [1~5등에 당첨될 수 있는 데이터 셋의 수]는 194,130개로 1/42의 확률이었다. 즉 최소 5천원(5등)에 당첨되기 위해서는 42 로또 즉, 42,000원을 구입해야 확률적으로 당첨이 된다는 것이었다. 너무하네...
총(누적 회차) 당첨번호 데이터 수
  • 8,145,060 * 721 = 5,872,588,260개(오십팔억 칠천이백오십팔만 팔천이백육십)

 

1. 1. 1 역대 로또 당첨번호 데이터 파싱하기 (2017-02-05 : 파싱 URL 변경에 따른 수정

앞서 말했듯이 데이터는 로또 공식 홈페이지에서 제공해주는 각 회차별 당첨결과 값을 파싱해서 필요한 부분(당첨 숫자 6개 + 보너스 숫자 1개)만을 가져다가 사용할 예정이다. 이에 따라 작성된 코드와 파싱에 사용된 실제 URL은 다음과 같다.

LM_Data/LM_URLParsing.java (2016-09-30 01:47) (2017-02-05 19:54) 

package LM_DataParsing;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;

/**
 * 
 * @author Myeonguni
 * @since 17.02.05
 * 
 */
public class LM_URLParsing {
    public LM_URLParsing() {
    }
 
    /**
     * 
     * @param url 로또 당첨번호를 파싱할 공식 홈페이지 URL(http://www.nlotto.co.kr/gameResult.do?method=byWin&drwNo="회차")
     * @param start 추출할 당첨번호 시작회
     * @param end 추출할 당첨번호 마지막회
     * @return 로또 start~end회 당첨번호 데이터를 담은 ArrayList<String>
     * @throws IOException
     */
    public ArrayList<String> URLParsing(String url, int start, int end) throws IOException {
        String result = null, temp = null, line = null;
        String numbers[] = new String[7];
        ArrayList<String> list = new ArrayList<String>();
 
        /*
         * 1~734 회차에 따른 loop 진행(회차=변수 i값) 파싱하여 얻은 데이터에서 필요한 데이터(당첨번호)만 뽑아서
         * String 배열에 저장 : numbers[0,1,...,5] 위에서 저장한 String 배열을 각 회차별로 관리하기 위한
         * ArrayList객체에 저장
         */
        for (int i = start; i <= end; i++) {
            URL ParsingURL = new URL(url + i);
            BufferedReader bin = new BufferedReader(new InputStreamReader(ParsingURL.openStream(), "UTF-8"));
 
            while ((line = bin.readLine()) != null)
                result += line;
 
            result = result.substring(result.indexOf("<p class=\"number\">") + 19, result.length());
            for (int j = 0; j < 7; j++) {
                numbers[j] = result.substring(result.indexOf("alt=") + 5, result.indexOf("alt=") + 7).replaceAll("\"",
                        "");
                result = result.replaceFirst("alt=", "pass=");
            }
            list.add(numbers[0] + "," + numbers[1] + "," + numbers[2] + "," + numbers[3] + "," + numbers[4] + ","
                    + numbers[5] + "," + numbers[6]);
            bin.close();
            
            System.out.println(i + "회차 - " + list.get(i-1));
        }
        return list;
    }
}

위 코드를 실행하기 위해 메인클래스를 아래와 같이 작성하여 보았다.

Main/main.java (2016-09-30 01:47) (2017-02-05 19:54) 

package Main;

import java.io.IOException;
import java.util.ArrayList;

import LM_DataParsing.LM_FileWrite;
import LM_DataParsing.LM_URLParsing;

/**
 * 
 * @author Myeonguni
 * @since 17.02.05
 * 
 */
public class main {

	/** 로또 당첨번호를 파싱할 url address **/
	final static String url = "http://www.nlotto.co.kr/gameResult.do?method=byWin&drwNo=";
	
	/** 추출할 로또 당첨번호 시작 회차 **/
	final static int start = 1;
			
	/** 추출할 로또 당첨번호 마지막 회차 **/
	final static int end = 5;
	
	public static void main(String args[]) throws IOException{
		
		/** 로또 당첨번호를 파싱하여 데이터를 수집하는 객체 **/
		LM_URLParsing URLParsing = new LM_URLParsing();
		
		/** 수집된 로또 당첨번호 리턴 값을 담을 ArrayList 객체 **/
		ArrayList<String> LuckyNumber = new ArrayList<String>();
		
		/** 로또 당첨번호를 기반으로 실제 1~5등,꽝에 해당하는 번호를 추출하여 파일출력하는 객체 **/
		LM_FileWrite FileWrite = new LM_FileWrite();
		
		
		/* 로또 당첨번호 값 셋팅 : 당첨번호 공식번호 URL, 시작 당첨회차, 마지막 당첨회차 */
		LuckyNumber = URLParsing.URLParsing(url, start, end);
		
		/* 로또 당첨번호 데이터셋 파일 셋팅 */
		FileWrite.FileWrite(LuckyNumber); 
		
	}
	
}

코드를 실행하게되면 결과적으로 파싱되어 필요한 데이터만이 list객체(ArrayList)에 담긴 것을 확인해볼 수 있다. 이는 총 0~720번지까지의 방에 각 회차에 맞는 당첨 숫자 6개와 보너스 숫자 1개를 뜻한다.

이제는 이 데이터를 기반으로 총 6개의 클래스(학습) 분류에 사용될 데이터를 뽑아볼 차례이다.

 

1. 1. 2 조합(Combination)을 이용한 당첨번호 데이터 뽑아내기[최종적으로 당첨번호 및 꽝번호 추출 알고리즘 작성에 미사용 함]

[1. 1. 1]에서 추출한 6개의 당첨번호 + 보너스번호를 기반으로 실제 1~5등 당첨번호에 해당하는 데이터를 뽑아내기 위해서 다음과 같은 코드를 작성하여 선행 작업을 실시하였다.

18행에서는 각 등수 별로 공통적으로 6개의 숫자를 가지기 때문에 6개의 배열을 설정하였고 이어지는 19행에서는 실제 조합을 추출하기 위한 매개변수로 각 등수에 알맞게 작성해주어야 한다. 다음 예와 코드, 출력 결과를 참고하기 바란다.

  • 예) 4등(6C4) - combination(arr, 0, 6, 4, 0);

combination.java

/**
 * 등수 뽑아내는 함수
 * 배열(당첨번호 셋) : 배열(추출 데이터 셋)을 비교하여 당첨 등수 분별
 * 반환 값 : 일치 번호를 카운스한 수(정수)
 */
static int compare(int arr[], int arr2[]) {
	int count = 0;
	for (int i = 0; i < arr.length - 1; i++) {
		for (int j = 0; j < arr2.length; j++) {
			if (arr[i] == arr2[j])
				count++;
		}
	}
	return count;
}

 

각 당첨등수에 따른 출력 결과

  • 1등 당첨번호 6개 숫자일치(6C6=1) - 012345
  • 2등 당첨번호 5개 숫자일치(6C5=6) - 01234, 01235, 01245, 01345, 02345, 12345
  • 3등 당첨번호 5개 숫자일치(6C5=6) - 01234, 01235, 01245, 01345, 02345, 12345
  • 4등 당첨번호 4개 숫자일치(6C4=15) - 0123, 0124, 0125, 0134, 0135, 0145, 0234, 0235, 0245, 0345, 1234, 1235, 1245, 1345, 2345
  • 5등 당첨번호 3개 숫자일치(6C3=20) - 012, 013, 014, 015, 023, 024, 025, 034, 035, 045, 123, 124, 125, 134, 135, 145, 234, 235, 245, 345

 

1. 1. 3 실제 각 회차별 등수(1~5)에 따른 당첨번호 및 꽝 번호 추출하기

[1. 1. 1.], [1. 1. 2]의 작업을 거쳐 최종적으로 실제 각 회차별 등수에 따른 당첨번호와 꽝 번호를 추출하는 작업을 진행에보도록 하겠다.

이에 대한 작업 사항으로는 [1. 1. 2]에서 추출한 각 조합에 대한 경우의 숫자 셋을 이용하여 [1. 1. 1]에서 추출한 list 객체에 담긴 numbers 배열 변수의 방 번호에 대입하여 알고리즘을 작성해보았다. 

* 아직 58억 개에 해당하는 데이터를 어떻게 보다 효율적으로 파일처리(출력) 해야할 지 결론이 안나와서 현재 절에서는 추후에 실제 파일출력에 해당하는 부문은 각 클래스(분류) 별로 카운트(count) 변수를 두어 최종적인 카운트 값을 System.out.println()으로 출력하여 실제 알고리즘 작성이 문제없이 되었는지 확인해보는데 제한을 두었다.

각 회차별 당첨번호(1~5) 및 꽝 번호 추출에 사용된 알고리즘

 

compare(number2, number3)

/**
 * 등수 뽑아내는 함수
 * 배열(당첨번호 셋) : 배열(추출 데이터 셋)을 비교하여 당첨 등수 분별
 * 반환 값 : 일치 번호를 카운스한 수(정수)
**/
static int compare(int arr[], int arr2[]) {
    int count = 0;
    for (int i = 0; i < arr.length - 1; i++) {
        for (int j = 0; j < arr2.length; j++) {
            if (arr[i] == arr2[j])
                count++;
        }
    }
    return count;
}

출력 결과↓

  • 총데이터 : 8145060
  • 1등 : 1
  • 2등 : 6
  • 3등 : 228
  • 4등 : 11115
  • 5등 : 182780
  • 6등 : 7950930

작성 된 알고리즘을 테스트해 본 결과, 1~5등 및 꽝에 해당하는 데이터 셋을 추출하는 데는 문제가 없어보인다. 단지 효율적인 알고리즘인가에 대한 고민은 더 해봐야할 것 같다(나중에...).

 

1. 2 위에서 뽑아낸 데이터를 파일에 처리(출력)하기

역대 로또 당첨번호(1~5등에 대한)와 꽝 번호에 대한 필요한 데이터 셋은 이미 위 작업을 통해 얻어진 상태이다. 해당 데이터 셋은 앞서 예상했던대로 각 회차별로 8,145,060개(팔백십사만 오천육십개)이며, 총 누적 회차를 고려했을 시 5,872,588,260개(오십팔억 칠천이백오십팔만 팔천이백육십개)에 해당하는 어마어마한 데이터 셋이다.

실제 파일처리에 앞서 대략적으로 계산해본 파일의 크기는 다음과 같다.

1개의 데이터 셋(1행)에 해당하는 문자열의 크기

  • (최소)15Byte ~ (최대)25Byte + 2(개행문자) = 17~ 27Byte

1회차 데이터 셋의 크기(최대)

  • 대략 219,916,620 Bytes = 209MB

1~721회차 데이터 셋의 크기(최대)

  • 158,559,883,020 Bytes = 151,214MB = 148GB

이와 같은 데이터를 하나의 파일에 일괄적으로 출력하여 기계학습하기에는 무리가 있다고 판단하여 각 회차별로 나누어 파일데이터를 만들어 출력하는 방법으로 코드를 작성하였다. 일 처리는 추후 기계학습에서 사용될 LogisticRegressionModel에서 지원하는 'csv' 확장자에 '클래스분류 학습분류번호:학습데이터 학습분류번호:학습데이터...' 의 포맷을 따라 처리할 것이다. 보다 자세한 데이터 셋 형식과 작성된 코드는 다음과 같다.

[당첨결과(학습기준) 1:1번번호 2:2번번호 3:3번번호 4:4번번호 5:5번번호 6:6번번호]

  • * 1번번호, 2번번호, 3번번호, 4번번호, 5번번호, 6번번호 : 1~45까지 서로 중복되지 않은 번호
  • * 당첨결과(학습기준) : 1(1등), 2(2등), 3(3등), 4(4등), 5(5등), 6(꽝)
  • * 예) [1 1:1 2:2 3:3 4:4 5:5 6:6] = 1등 1번번호(1) 2번번호(2) 3번번호(3) 4번번호(4) 5번번호(5) 6번번호(6)

DataFileWriter (위 [1. 1. 3]에 이어서 작성, 2016-10-04 12:04 2017-02-05 20:35)

package LM_DataParsing;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * 
 * @author Myeonguni
 * @since 17.02.05
 * 
 */
public class LM_FileWrite {
	
	public LM_FileWrite() {
		
	}

    /**
     * 
     * @param list 추출한 로또 당첨번호 데이터를 담은 ArrayList<String>
     * @throws IOException
     * 추출한 로또 당첨번호 데이터를 기반으로 1~5등, 꽝 데이터를 추출하여 파일쓰기를 진행함<br>
     * 작성될 파일 포맷 : [당첨결과(학습기준) 1:1번번호 2:2번번호 3:3번번호 4:4번번호 5:5번번호 6:6번번호]
     */
	public static void FileWrite(ArrayList<String> list) throws IOException {
		/* 추출한 로또 당첨번호 셋에 따른 loop 진행 */
        for (int l = 1; l <= list.size(); l++) {
        	/* 파일출력을 위한 BufferedWriter 객체 : 각 회차별(리스트 1셋 당 1회차시)*/
            BufferedWriter br = new BufferedWriter(new FileWriter("C:\\lottoData\\LottoMachineLearningDataSet" + l + ".csv"));
            String numbers[] = list.get(l-1).split(",");
            int[] numbers2 = new int[numbers.length];
            for (int i = 0; i < numbers2.length; i++) numbers2[i] = Integer.parseInt(numbers[i]);
            /*
             * 당첨번호 및 꽝번호 셋 추출하기
             * 실제 로또 번호셋과 동일하게 중복 되는 번호를 제외한 loop 돌리기(6중)
             * 총 8,145,060건의 데이터 셋 추출
             * numbers2[] 에는 실제 당첨번호6개+보너스번호1개가 담겨져있음.
             * numbers3[] 에는 아래 작성된 알고리즘을 통해 추출한 번호6개가 담겨져있음
             * 각 데이터 셋의 등수 판별은 compare 함수 사용(하단 compare() 코드 참고)
             */
            for (int l1 = 1; l1 < 46; l1++) {
                for (int l2 = 1; l2 < 46; l2++) {
                    if (l1 == l2) break;
                    for (int l3 = 1; l3 < 46; l3++) {
                        if (l1 == l3 || l2 == l3) break;
                        for (int l4 = 1; l4 < 46; l4++) {
                            if (l1 == l4 || l2 == l4 || l3 == l4) break;
                            for (int l5 = 1; l5 < 46; l5++) {
                                if (l1 == l5 || l2 == l5 || l3 == l5 || l4 == l5) break;
                                for (int l6 = 1; l6 < 46; l6++) {
                                    if (l1 == l6 || l2 == l6 || l3 == l6 || l4 == l6 || l5 == l6) {
                                        break;
                                    } else {
                                        int numbers3[] = { l1, l2, l3, l4, l5, l6 };
                                        Arrays.sort(numbers3);
                                        switch (compare(numbers2, numbers3)) {
                                        case 6: /* 1등일 경우(당첨번호6개 일치) */
                                            br.write("1 " + "1:" + numbers3[0] + " 2:" + numbers3[1] + " 3:" + numbers3[2] + " 4:" + numbers3[3] + " 5:" + numbers3[4] + " 6:" + numbers3[5] + "\n");
                                            break;
                                        case 5:
                                        	/* 2등일 경우(당첨번호5개+보너스번호 일치) */
                                            if (numbers2[6]==numbers3[0] || numbers2[6]==numbers3[1] || numbers2[6]==numbers3[2] || numbers2[6]==numbers3[3] || numbers2[6]==numbers3[4] || numbers2[6]==numbers3[5]) {
                                                br.write("2 " + "1:" + numbers3[0] + " 2:" + numbers3[1] + " 3:" + numbers3[2] + " 4:" + numbers3[3] + " 5:" + numbers3[4] + " 6:" + numbers3[5] + "\n");
                                            } else { /* 3등일 경우(당첨번호5개 일치) */
                                                br.write("3 " + "1:" + numbers3[0] + " 2:" + numbers3[1] + " 3:" + numbers3[2] + " 4:" + numbers3[3] + " 5:" + numbers3[4] + " 6:" + numbers3[5] + "\n");
                                            } break;
                                        case 4: /* 4등일 경우(당첨번호4개 일치) */
                                            br.write("4 " + "1:" + numbers3[0] + " 2:" + numbers3[1] + " 3:" + numbers3[2] + " 4:" + numbers3[3] + " 5:" + numbers3[4] + " 6:" + numbers3[5] + "\n");
                                            break;
                                        case 3: /* 5등일 경우(당첨번호3개 일치) */
                                            br.write("5 " + "1:" + numbers3[0] + " 2:" + numbers3[1] + " 3:" + numbers3[2] + " 4:" + numbers3[3] + " 5:" + numbers3[4] + " 6:" + numbers3[5] + "\n");
                                            break;
                                        default: /* 꽝일 경우(당첨번호4개 이상 불일치) */
                                            br.write("6 " + "1:" + numbers3[0] + " 2:" + numbers3[1] + " 3:" + numbers3[2] + " 4:" + numbers3[3] + " 5:" + numbers3[4] + " 6:" + numbers3[5] + "\n");
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            br.flush();
            br.close();
        }
    }
	
	/**
	 * 등수 뽑아내는 함수
	 * 배열(당첨번호 셋) : 배열(추출 데이터 셋)을 비교하여 당첨 등수 분별
	 * 반환 값 : 일치 번호를 카운스한 수(정수)
	 */
    static int compare(int arr[], int arr2[]) {
        int count = 0;
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr2.length; j++) {
                if (arr[i] == arr2[j])
                    count++;
            }
        }
        return count;
    }
}

 

실제 작성된 코드를 이용하여 데이터 출력에 걸린 작업 소요시간은 1시간 가량된다. 이렇게 해서 1회~721회까지의 역대 당첨(1~5등) 및 꽝에 해당하는 모든 번호에 대한 데이터 셋은 준비가 완료되었다(LottoMachineLearningDataSet1~721.csv).

 

여기까지해서 기계학습을 진행하기 위한 준비를 마쳤다. 이 데이터셋을 기반으로 실제적인 기계학습을 진행해볼 차례다. 기계학습은 앞서 말한 서론에서 말한 구조인 Apache Spark Mllib 프레임워크에서 LogisticRegression 알고리즘 모델을 이용하여 진행할 예정이다.

 

2. 기계학습 (2017-02-05)

작년 10월 즈음 갑자기 시작된 로또 기계학습 포스팅을.. 교내 연구, 취업 준비 등으로 바쁜 시기를 보내다.. 다음해 2월인 이제서야 다시 진행하게 되었다. (죄송합니다 ㅜ_ㅜ)

그럼 본격적으로 본 포스팅의 실질적인 목적인 로또 당첨번호 기계학습에 들어가보도록 하겠다.

앞서 우리는 1. 기계학습에 사용될 데이터셋 만들기를 통하여 실제 기계학습에 필요한 데이터 준비를 마친 상태이다. 여기서 주의할 점은 여러 기계학습 알고리즘 모델들이 각각 다양한 포맷의 데이터셋을 지원하기 때문에 자신이 진행할 알고리즘에 대한 데이터셋 포맷에 맞추어 데이터를 준비해야 된다.

사실 본 프로젝트를 시작할때만 하더라도 WEKA 프레임워크를 사용하여 여러 기계학습 모델 중 SVM(LibSVM) 모델을 사용하여 기계학습을 진행할 예정이었다. (WEKA 프레임워크에서는 SVM 모델의 분류에 있어 MultiClass 지원을 해주기 때문에 문제가 없었다)

하지만... 문제가 있었으니.. 바로 WEKA 프레임워크로는 우리가 뽑아낸 58억개(-_-)나 되는 데이터 처리를 하기에는 문제가 있기 때문이다. (테스트 결과 10만건을 처리하는데 5시간동안 결과가 나오지 않아 프로그램 강제종료를 하였다...ㅎㅎ)

그래서 실시간 메모리 기반 분산처리가 가능한 'Apache Spark Mllib' 프레임워크로 기계학습을 진행는 방향을 택하게 되었다.

그런데 여기서 또 문제가 있었으니, Apache Spark Mllib에서 SVM모델은 데이터 분류에 대하여 BinaryClass 밖에 지원을 하지 않는 다는 것이다. 그래서 다른 머신러닝 알고리즘(LogisticRegression)을 사용하기로 하였다.

BinaryClass : 0과 1 즉, 2가지에 분류에 대한 학습만을 지원한다고 생각하면 된다. 약간 예를 들자면, 날씨에 대한 데이터를 학습하고 결과(분류) 값으로 0일 경우에는 외출한다. 1일 경우에는 외출하지 않는다. 정도로 이해하면 된다.

MultiClass : 다중 분류를 지원, 본 프로젝트의 경우는 1, 2, 3, 4, 5등, 꽝 총 6개의 분류를 지원해야 하기 때문에, LogisticRegression 알고리즘 모델을 사용하기로 하였다. 

 

자 그럼, 히스토리는 여기까지 끄적이고... 기계학습을 시작해보자 !

 

학습에 사용될 데이터셋이 준비된 현 시점에서 기계학습을 진행하기 위한 순서는 다음과 같다.

  • ① Aparch Spark Mllib 프레임워크 환경구축
    • Linux(Ubuntu) 설치
    • Aparch Hadoop 2.x (+YARN) 설치 (SingleNode로 진행)
    • Aparch Spark 설치
    • Eclipse 설치 및 Spark 플러그인 연동
  • ② 준비된 데이터 셋을 이용해 기계학습 진행

 

3. 결과 (미작성...)

(미작성...)

 

참고 문헌 (미작성...)

https://spark.apache.org/docs/latest/mllib-evaluation-metrics.html

https://en.wikipedia.org/wiki/Multiclass_classification

https://en.wikipedia.org/wiki/Binary_classification

반응형