crossorigin="anonymous"> [훈련 세트 & 테스트 세트] Chapter 2-1. 데이터 다루기 (수상한 생선을 조심하라!)

카테고리 없음

[훈련 세트 & 테스트 세트] Chapter 2-1. 데이터 다루기 (수상한 생선을 조심하라!)

Writing coder 2024. 8. 27. 22:26
반응형

학습 목표 :  지도학습과 비지도 학습의 차이를 배웁니다. 모델을 훈련시키는 훈련 세트와 모델을 평가하기 위한 테스트 세트로 데이터를 나눠서 학습해 봅니다.

 

Sampling bias 문제 해결 shceme

1. 데이터 불러오기 (Input, Target) (2차원 array)

2. Train, Test set 나누기

3. 각 데이터 index로 shuffling 하기 (.shuffle / np.arange 활용)

4. Model 학습 시키기

5. Model 평가 하기 (Accuracy)

 

[문제 상황]

도미 35마리와 빙어 14마리를 모두 학습 시키고 맞추게 하면 당연히 정확도는 100%가 아닐까요?

어떤것이 도미이고 빙어인지 아는 상황인데, 못맞추는 것이 이상한것 아닌가요?

 

그렇다. 학교에서 중간 고사를 볼때, 시험 문제를 알려주고 시험을 치면 당연히 100점이 나올것이다. 이번장에서 우리를 가르치려고 하는것은 "100문제 중에 80문제를 알려주고 20문제는 시험을 치는것" 이라고 비유적으로 생각하면 좋을것 같다. 

 

 

 

지도학습 vs 비지도 학습

  • 지도학습 (Supervised learning) : input(데이터)과 target (정답)을 전달하여 모델을 훈련한 다음 새로운 데이터를 예측하는 데 활용함. k-nearest neighobrs에도 사용. ex) 도미인지 방어인지 정답을 알려주고 생선을 주며 구분 하는 모델을 만들 때 사용.

       지도 학습을 진행하는데, 몇 가지 알고 넘어가야 할 점이 있다.

 

       1. 지도학습 알고리즘은 훈련하기 위한 데이터 (input) 와 정답 (target)이 필요하다.

       2. 데이터 : 입력 (input), 정답 : 타깃 (target) 이라고 한다.

       3. input에는 데이터의 특성 (feature들이 있다. ex. 키, 몸무게 등등)

       4. 훈련 데이터 = input + target

 

  • 비지도학습 (Unsupervised learning) : target 없이 입력 데이터만을 사용. 따라서 무엇을 예측하는 것이 아니라 입력 데이터에서 어떤 특징을 찾는 데 주로 활용함.

        무언가를 맞힐수는 없지만, 데이터를 잘 파악해서 변형하는데 도움을 준다. chapter 6에서 다룰 예정

 

        그래도 이해가 안됩니다. 정답을 알려주고 지도 학습을 시켜서 도미인지 빙어인지 판별하는 모델을 만들어서 100% 판별했는데, 무엇          이 문제일까요? 위에서 말한 "100문제 중에 80문제를 알려주고 20문제는 시험을 치는" 적용이 되어야 합니다.

 

훈련 세트 vs 테스트 세트

위에서 말했듯이 중간고사 문제를 미리 알려주고 그대로 내면, 당연히 100점을 맞을수 밖에 없습니다.

이와 같은 맥락에서 머신러닝의 알고리즘의 성능을 제대로 평가하려면, 훈련 데이터와 평가에 사용할 데이터가 각각 달라야 합니다.

  • 훈련 세트 (Train set) : 모델을 훈련 할 때 사용 되는 데이터, 보통 훈련 세트가 클 수록 좋기 때문에 test set를 제외한 모든 데이터를 사용.
  • 테스트 세트 (Test set): 알고리즘의 평가를 위해 이미 준비된 데이터 일부를 떼어내서 활용. 주로 전체 데이터에서 20-30%를 테스트 세트로 사용하며, 전체 데이터가 아주 크다면 1%만 덜어내도 충분한다.
  • 샘플 (Sample) : 하나의 데이터 ex) 생선 1개의 무게와 길이 데이터

아래에서 샘플편향을 공부하면서 조금 더 이해해 보자.

 

샘플 편향(Sampling bias) : Train set와 Test 에 샘플이 골고류 섞여 있지 않고 sampling이 한쪽으로 치우치게 되는 현상

 

만약 위와 같은 데이터 중에서 도미(Bream) 데이터로만 model이 학습을 한다면, 빙어 (Smelt)는 모델이 예측하지 못하고 어떤 물고기이든 모두 빙어로 예측할것이다. 결국, 올바른 모델 되지 못하는것이다.

 

 

다음과 같이 Train data가 여러군데 퍼져 있어야 model이 정확히 예측 할 수 있을것이다.

 

따라서, 우리는 numpy 라는 library에서 제공 arange() 함수와, shuffle() 함수를 통해 데이터를 무작위로 섞고 Train set와 Test set를 구분 하는 것을 공부 할 것이다.

Numpy 

1. 파이썬의 대표적인 배열 (array) library

2. 고차원의 배열을 손쉽게 만들고 조작할 수 있는 간편한 도구를 많이 제공

3. Sample을 섞거나, 골고루 뽑아서 훈련 세트와 테스트 세트를 만들어야 할 때 사용 하는데, 이를 도와주는 library

 

  • seeed() : 넘파이에서 난수를 생성하기 위한 정수 초깃값을 지정. 초기값이 같으면 동일한 난수를 뽑을 수 있다. 따라서, 랜덤 함수의 결과를 동일하게 재현하고 싶을 때 사용함.
  • arange() : 일정한 간격의 정수 또는 실수 배열을 만듦. 기본 간격은 1. 매개변수가 하나이면 종료 숫자를 의미함. 0에서 종료 숫자까지 배열은 만듦. 종료숫자는 배열에 포함 되지 않음.

       매개변수가 1개인 경우 : print(np.arange(3)) => [0, 1, 2]

       매개변수가 2개인 경우 : print(np.arange(1, 3)) => [1, 2] 

       매개변수가 3개인 경우 : print(np.arange(1, 3, 0.2)) => [1. , 1.2, 1.4, 1.6, 1.8, 2. , 2.2, 2.4, 2.6, 2.8]

매개변수가 1개인 경우 : print(np.arange(3))

[0, 1, 2]


매개변수가 2개인 경우 : print(np.arange(1, 3))

[1, 2] 


매개변수가 3개인 경우 : print(np.arange(1, 3, 0.2))

[1. , 1.2, 1.4, 1.6, 1.8, 2. , 2.2, 2.4, 2.6, 2.8]
  • shuffle() : 주어진 배열을 랜덤하게 섞는다. 다차원 배열일 경우 첫 번째 축(행)에 대해서만 섞는다.
  • array() : 1차원의 리스트 데이터 같은 경우, 2차원의 형태로 만들어 알아보기 쉽게 데이터를 다루기 용이하게 해준다.
                    특히, list 형태의 데이터인 경우 분석 전, np.array(list)를 해주고 시작하는 경우가 많은 것 같다.
arr = np.array([[1, 2], [3, 4], [5, 6]])
np.random.shuffle(arr)
print(arr)
[[3 4]
 [5 6]
 [1 2]]

 

이후, 다시 섞은 데이터를 모델에 학습 시키고, test set를 통해 model을 평가하는 score() 함수를 통해 accuracy를 측정하게 됩니다. 

 

Code - 문제 해결 과정과 개념

1차원 list 데이터를 불러옵니다.

#1.1. input 데이터 불러오기 
fish_length = [25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0, 30.0, 30.7, 31.0, 31.0, 
                31.5, 32.0, 32.0, 32.0, 33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0, 
                35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5, 39.5, 41.0, 41.0, 9.8, 
                10.5, 10.6, 11.0, 11.2, 11.3, 11.8, 11.8, 12.0, 12.2, 12.4, 13.0, 14.3, 15.0]
fish_weight = [242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0, 390.0, 450.0, 500.0, 475.0, 500.0, 
                500.0, 340.0, 600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0, 685.0, 620.0, 680.0, 
                700.0, 725.0, 720.0, 714.0, 850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0, 6.7, 
                7.5, 7.0, 9.7, 9.8, 8.7, 10.0, 9.9, 9.8, 12.2, 13.4, 12.2, 19.7, 19.9]

 

input과 target 데이터를 생성합니다.

#1.2. input을 2차원 리스트를 만들고 target 불러오기
fish_data = [[l,w] for l,w in zip(fish_length, fish_weight)]
fish_target = [1]*35 + [0]*14

 

모델 객체를 만듦니다.

#1.3. 모델 객체 만들기
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()

 

Train set와 Test set를 나누어 모델을 훈련 시키고, 평가 해보지만 정확도가 0인것을 확인했습니다.

# 1.4. Train set와 Test set 나누기

# 1.4.1 Train set로 인덱스 0부터 34까지
train_input = fish_data[:35]
train_target = fish_target[:35]

# 1.4.2. Test set로 인덱스 35부터 끝까지
test_input = fish_data[35:]
test_target = fish_target[35:]

# Sampling bias 때문에, 모델이 균일하게 학습 되지 않음.

kn.fit(train_input, train_target)
kn.score(test_input, test_target) # 0.0

 

Train set의 분포를 확인해 보니 도미만 훈련 된것을 확인

# 데이터 위치를 파악
# Train set = 파랑 / Test set = 빨강
# 파랑만 학습 된것을 알 수 있음.
import numpy as np
fish_data = np.array(fish_data)

import matplotlib.pyplot as plt

plt.scatter(fish_data[:35,0],fish_data[:35,1], c = 'b', label = 'Train set')
plt.scatter(fish_data[35:,0],fish_data[35:,1], c = 'r', label = 'Test set')
plt.legend()

 

파란색인 도미 데이터만 훈련 된 상황

 

Sampling bias를 해결하기 위해 데이터를 shuffling할것이고, 이를 numpy의 arange와 shuffle 함수를 사용해서 진행하기 위해

사용할 data 들을 2차원 array로 변형

## Sampling bias를 해소하기 위한 numpy

#1.5. 생선 데이터를 2차원 numpy array로 변환하기 => 보기도 쉽고, sample의 개수과 feature의 개수를 알 수 있는 효과가 있음.

import numpy as np

input_arr = np.array(fish_data)
target_arr = np.array(fish_target)

 

#1.6. arange 함수를 이용해 무작위 index 생성하기
# arange(N) : 0부터 N-1까지 1씩 증가하는 array를 만듦.
# random.shuffle(A) : A array를 무작위로 섞음. 

np.random.seed(42) # 책과 동일한 결과를 얻기 위해
index = np.arange(49)
np.random.shuffle(index) # 무작위로 섞음
print(index)

 

Train set : 앞에서부터 35개의 데이터 / Test set : 35번 부터 마지막 까지

 

#1.7. Array indexing을 이용해 혼합된 Train set 만들기

train_input = input_arr[index[:35]]
train_target = target_arr[index[:35]]

#1.8. 섞인 index를 받은 train set 첫번째 값과 원래의 index의 값을 비교

print(input_arr[13], train_input[0])

#1.9. Array indexing을 이용해 혼합된 Test set 만들기

test_input = input_arr[index[35:]]
test_target = target_arr[index[35:]]

test_input[0:5]

 

그리고 잘 섞였는지 확인해보기

 

#1.10. 잘 섞여 있는지 확인해보기

# 2차원 배열은 행과열 인덱스를 콤마(,)로 나누어 지정합니다. 슬라이싱 연산자로 처음부터 마지막  원소까지 모두 선택하는 경우 시작과 종료 인덱스를 모두 생략 할 수 있습니다.

import matplotlib.pyplot as plt

plt.scatter(train_input[:,0],train_input[:,1], c = 'b', label = 'Train data')
plt.scatter(test_input[:,0],test_input[:,1], c = 'r', label = 'Test data')
plt.xlabel('length')
plt.ylabel('weight')
plt.legend()
plt.show()

 

 

다시 모델을 훈련 시키고 평가해본다.

 

마지막에 짧게 Test set의 input을 넣은 model의 예측 값이 test의 정답과 같다면 "Accuracy가 100% 인 모델입니다." 라고 출력 하라는 짧은 코딩을 진행하였다.

# 1.11. 다시 모델 훈련 시키기

kn.fit(train_input, train_target)

# 1.12. 훈련 시킨 모델을 test set로 평가하기

kn.score(test_input, test_target)

kn.predict(test_input)

if np.array_equal(kn.predict(test_input), test_target):
  print('Accuracy가 100%인 model 입니다.')
else : print('다시 model의 최적화가 필요합니다.') # Accuracy가 100%인 model 입니다.

 

반응형