클라이언트/ 서버/ 엔지니어 " 게임 개발자"를 향한 매일의 공부일지

데이터 다루기 1 - 훈련 세트와 테스트 세트 1 : 지도 학습과 비지도학습의 차이와 훈련세트와 테스트세트로 나누는 것에 대하여 본문

인공지능/머신러닝

데이터 다루기 1 - 훈련 세트와 테스트 세트 1 : 지도 학습과 비지도학습의 차이와 훈련세트와 테스트세트로 나누는 것에 대하여

huenuri 2024. 9. 28. 02:49

저녁을 먹고 나니 정신이 조금 몽롱하지만 그래도 공부를 시작해본다. 항상 내가 목표한 것의 1/3도 채우지 못할 때가 많아 실망이 크지만 그래도 목표가 있기에 하루하루가 기쁘고 감사하다.

이제 새로운 단원에 들어갔다. 이번에는 데이터에 대해서 다루게 된다.


 

 

 

학습 목표

지도학습과 비지도 학습의 차이를 배운다. 모델을 훈련시키는 훈련 세트와 모데을 평가하기 위한 테스트 세트로 데이터를 나누어 학습한다.

 

팀장은 혼공머싱의 보고서를 읽고 무척 의아해했다. 그것은 이미 도미와 빙어를 저장한 상태이기에 100% 정답을 맞추는 것이 당연하다는 것이다. 올바른 평가를 하기 위해서는 평가를 위한 다른 데이터를 준비해서 평가해야 할 것이다.


 

 

지도 학습과 비지도 학습

머신러닝 알고리즘은 크게 지도 학습과 비지도 학습으로 나눌 수 있다. 지도 학습알고리즘은 훈련하기 위한 데이터와 정답이 필요하다. 지도학습에서는 데이터를 입력, 정답을 타깃이라 하고 이 둘을 합쳐 훈련 데이터라고 부른다.

입력으로 사용된 길이와 무게를 특정이라고 했었다.  지도학습은 정답(타깃)이 있으니 알고리즘이 정답을 맞추는 것을 학습한다. 반면 비지도 학습 알고리즘은 타깃 없이 입력 데이터만 사용한다.

 

 

강화학습 알고리즘은 타깃이 아니라 알고리즘이 행동한 결과로 얻은 보상을 사용해 학습된다. k-최근접 이웃 알고리즘은 입력 데이터와 타깃(정답)을 사용했으므로 지도 학습알고리즘이다. 이 알고리즘을 훈련하여 생선이 도미인지 아닌지를 판별하고, 이 모델이 훈련 데이터에서 도미를 100% 완벽하게 판별했다. 하지만 무엇이 문제일까?


 

 

 

훈련 세트와 테스트 세트

도미와 빙어의 데이터와 타깃을 주고 훈련한 다음, 같은 데이터로 테스트한다면 모두 맞히는 것이 당연하다. 연습 문제와 시험 문제가 달라야 올바르게 학생의 능력을 평가할 수 있듯이 머신러닝 알고리즘의 성능을 제대로 평가하려면 훈련데이터와 평가에 사용할 데이터가 각각 달라야 한다.

이렇게 하는 가장 간단한 방법은 평가를 위해 또 다른 데이터를 준비하거나 이미 준비된 데이터 중에서 일부를 떼어 내어 활용하는 것이다. 일반적으로는 후자의 경우가 많다.

 

 

 

평가에 사용하는 데이터를 테스트 세트, 훈련에 사용되는 데이터를 훈련 세트라고 부른다. 훈련에 사용한 데이터로 모델을 평가하는 것은 적절하지 않다. 훈련할 때 사용하지 않은 데이터로 평가해야 한다. 

먼저 1장에서처름 도미와 빙어의 데이터를 합쳐 하나의 파이썬 리스트로 준비한다. 이제 이 두 파이썬 리스트를 순회하면서 각 생선의 길이와 무게를 하나ㅇ늬 리스트로 담은 2차원 리스트로 만들어본다.

 

이때 하나의 생선 데이터를 샘플이라고 부른다. 일반적으로 배열의 요소를 선택할 때는 배열의 위치 즉 인덱스를 지정한다. 그리고 슬라이싱을 하여 인덱스의 범위를 지정하여 선택한다. 이때 마지막 인덱스의 원소는 포함되지 않는다는 점을 주의한다.

 

 

 

데이터를 준비했으니 훈련 세트로 fit() 메스드를 호출해 모델을 훈련하고 테스트 세트로 score() 메서트를 호출해 평가를 진행해본다. 하지만 여기서 보니 데이터의 정확도가 0이 나왔다. 그 이유가 무엇일까?


 

 

 

샘플링 편향

 

 

 

데이터에서 마지막 14개만 따라 떼어서 훈련 세트로 만들면 여기에는 빙어가 하나도 없기 때문에 빙어 없이 모델을 훈련한 데이터가 만들어진 것이다. 훈련 세트와 테스트 세트를 나누려면 도미와 빙어가 골고루 섞이게 만들어야 한다.

훈련 세트와 테스트 세트에 샘플이 골고루 섞여 있지 않으면 샘플링이 한쪽으로 치우쳤다는 의미로 샘플링 편향이라고 부른다.

테스트 세트에는 빙어만 들어있기 때문에 정답을 하나도 맞히지 못한 것이다. 혼공머신이 훈련 세트와 테스트 세트를 나 누기 전에 데이터를 섞든지 아니면 골고루 샘플을 뽑아서 훈련 세트와 테스트 세트를 만들어야 한다.


 

 

 

 

넘파이

넘파이는 파이썬의 대표적인 배열 라이브러리이다. 파이썬 리스트로 2차원 리스트를 표현할 수 있지만 고차원 리스트를 표현하려면 매우 번거롭다. 넘파이는 고차원의 배열을 손쉽게 만들어주고 조작할 수 있는 간편한 도구를 많이 제공한다. 배열에서의 차원은 좌표계의 축과 같다.

 

 

1차원 배열은 선이며 벡터라고 표현한다. 2차원 배열은 면으로 행렬로 표현하기도 한다. 3차원 배열은 3차원 공간을 나타낸다. 파이썬에는 다른 종류의 타입값을 넣을 수 있지만 넘파이 배열에서는 실수값만 사용해야 한다.

넘파이 리스트를 넘파이 배열로 바꾸는 건 정말 쉽다. 넘파이 array() 함수에 파이썬 리스트를 전달하면 된다. 넘파이는 배열의 차원을 구분하기 쉽도록 행과 열을 가지런히 출력한다.

 

눈으로 확인하는 것 외에도 넘파이 배열 객체는 배열의 크기를 알려주는 shape 속성을 제공한다. 이제 생선 데이터를 넘파이 배열로 준비했으므로 이 배열에서 랜덤하게 샘플을 선택해 훈련 세트와 테스트 세트로 만들 차례이다 .여기서는 배열을 섞은 후에 나누는 방식 대신 무작위로 샘플을 고르는 방법을 사용하겠다.

한 가지 주의할 점은 input_arr과 target_arr에서 같은 위치는 함께 선택되어야 한다는 점이다.


 

 

 

 

예를 들어 input_arr의 두번째 값은 훈련 세트로 가고, target_arr의 두번째 값은 테스트 세트로 가면 안 된다. 타깃과 샘플이 함께 이동해야 올바른 훈련이 될 수 있다. 이렇게 하려면 훈련 세트와 테스트 세트로 나눌 인덱스값을 잘 기억해야 한다. 

인덱스를 섞은 다음 input_arr과 target_arr에서 샘플을 선택하면 무작이로 훈련 세트를 나누는 셈이 된다. 이렇게 0~48까지의 인덱스에서 35개는 훈련 세트로, 나머지 14개는 테스트 세트로 만든다.

 

넘파이 arrage() 함수를 사용하면 0에서 48까지 1씩 증가하는 인덱스를 만들 수 있다. 배열 슬라이싱은 인덱스가 담긴 배열을 넣어 원소를 선택하는 방법이다. 슬라이싱 외에도 넘파이는 배열 인덱싱이라는 기능을 제공한다. 1개의 인섹스가 아닌 여러 개의 인덱스로 한 번에 여러 개의 원소를 선택할 수 있다.

앞서 만든 index 배열의 저음 35개를 input_arr에 전달하여 랜덤하게 35개의 샘플을 훈련 세트로 만들어보았다. 그리고 나머지 14개를 테스트 세트로 만들었다. 이제 훈련 세트와 테스트 세트에 도미와 빙어가 잘 섞여 들어있는지 산점도로 그려보기로 하자.


 

 

 

 

 

그래프를 보면 훈련 세트에도 테스트 세트에도 도미와 빙어가 함께 섞여 들어있음을 확인할 수 있다. 2차원 배열은 행과 열 인덱스를 콤마로 나누어 지정한다. 전체를 선택하고 싶을 때는 슬라이싱 연산자를 사용한다.


 

 

 

 

두 번째 머신러닝 프로그램

앞서 만든 훈련 세트와 테스트 세트로 k-최근접 이웃 모델을 훈련시켜보겠다. fit() 메서드를 실행할 때마다 KNighborsClassifer 클래스의 객체는 이전에 학습한 모든 것을 잃어버린다.이전 모델을 그대로 두고 싶다면 KNighborsClassifer 클래스 객체를 새로 간들어야 한다. 여기서는 이전에 만든 kn 객체를 그대로 사용하겠다.

 

 

인덱스를 섞어 만든 train_input과 train_target으로 모델을 훈련시켰다. 테스트를 해보니 1.0으로 정확도가 100%임을 확인할 수 있다.

predict() 메서드의 출력 결과가 test_target의 출력과 동일하게 aray)로 감싸 있는 것을 확인해보라. 이 값은 넘파이 배열을 의미한다. 즉 predict() 메서드가 반환하는 값은 단순한 파이썬 리스트가 아니라 넘파이 배열이다.

 


 

 

 

학습을 마치고

어제밤에 아주 조금만 공부를 하고 얼마나 졸리던지 공부를 시작한지 20분도 되지 않아서 잠을 청했다. 그리고 다음날 새벽 1시 반에 일어나 나머지 학습을 이어가는 중이다. 앞으로는 졸려면 잠을 깨려고 애쓰지 않고 일찍 잠을 청하고 다음날 평소보다 더 일찍 일어나 공부하기로 다짐했다.

이른 새벽 공부를 하니 얼마나 머리도 맑고 행복한지 모른다. 아직도 내게 많은 시간이 있다는 사실이 감사하고 기쁠 뿐이다. 오늘 새벽에는 어제 다 하지 못했던 2장과 3장의 단원을 모두 마칠 수 있을 것 같다.