[혼자공부하는 머신러닝 + 딥러닝] 3_train_set, test_set 분리
2. 훈련세트와 테스트세트
1. 들어가며
- 도미와 빙어에 관한 데이터를 전부 저장하고 맞추는 거라면, 다 못맞추는게 이상한것이 아닌가? 생각하게 되었다.
- 머신러닝 알고리즘에는 크게 지도학습, 비지도학습으로 나눌 수 있다. 지도학습 알고리즘은 훈련을 위한 데이터와 정답이 필요하다.
- 지도학습에서는 입력, 타깃이 각각 데이터와 정답을 의미합니다. 그리고 이 둘을 합쳐 훈련데이터라고 합니다.
- 또한 사용된 길이와 무게 등을 특성이라고 합니다. 지도학습은 정답(타깃)이 있으니 정답을 맞추는 법을 학습한다. 하지만 비지도학습은 정답을 사용하지 않으므로 무언가는 맞추는것은 불가능하지만 데이터를 파악하거나 변형하는데 도움을 준다.
- 만약 중간고사에서 모든 문제와 답을 알려주고 시험을 본다면, 엄청 잘 보는게 가능할것이다. 하지만 이는 정확하게 학생의 능력을 평가하는 지표가 되지는 못한다. 따라서 시험 전의 연습문제와 실제 시험문제는 달라야 한다. 이와 마찬가지로 지도학습에 있어서도 훈련데이터셋과 성능을 시험하는 셋이 따로 존재해야 한다.
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
kn = KNeighborsClassifier()
- 마찬가지로 필요한 라이브러리와 메소드를 임포트 해준 뒤 K-최근접 이웃 객체를 지정한다.
- 이후 마찬가지로 도미와 빙어 데이터를 합친 리스트형태의 데이터를 불러온다.
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]
fish_data = [[l,w] for l, w in zip(fish_length, fish_weight)]
fish_target = [1]*35 + [0]*14
- 2차원 리스트로 변환하고, 타겟값도 준비한다.
- 슬라이싱을 이용해 불러오면 아래와 같이 값을 확인할 수 있다.
print(fish_data[4])
[29.0, 430.0]
print(fish_data[0:5])
[[25.4, 242.0], [26.3, 290.0], [26.5, 340.0], [29.0, 363.0], [29.0, 430.0]]
2. 샘플링 편향
train_input = fish_data[:35]
train_target = fish_target[:35]
test_input = fish_data[35:]
test_target = fish_target[35:]
- 각각을 35개의 물고기 데이터를 훈련 입력값과 타깃값으로 지정하고 나머지 14개를 훈련용 셋으로 분할한다.
- 이후 fit()을 이용하고 점수를 확인하면 다음과 같다.
kn = kn.fit(train_input, train_target)
kn.score(test_input, test_target)
0.0
- 이상하게 값의 정확도가 떨어진다 그 이유는 무엇일까?
- 앞에서 부터 도미, 빙어가 적절하게 나눠지지 않았기 때문이다. 앞의 35개의 데이터는 전부 도미를 나타낸다. 즉 훈련셋에는 전부 도미만 들어있고, 테스트 셋에는 빙어만 들어있기 때문에 도미로만 훈련받아서, 빙어를 예측하지 못하는 것이다. 이를 샘플링 편향 이라고 한다.
- 이를 해결하기 위해서는 훈련셋, 테스트셋 모두에 적절한 비율로 도미와 빙어가 모두 들어있어야 한다.
3. 넘파이
input_arr = np.array(fish_data)
target_arr = np.array(fish_target)
print(input_arr)
[[ 25.4 242. ]
[ 26.3 290. ]
[ 26.5 340. ]
[ 29. 363. ]
[ 29. 430. ]
[ 29.7 450. ]
[ 29.7 500. ]
[ 30. 390. ]
[ 30. 450. ]
[ 30.7 500. ]
[ 31. 475. ]
[ 31. 500. ]
[ 31.5 500. ]
[ 32. 340. ]
[ 32. 600. ]
[ 32. 600. ]
[ 33. 700. ]
[ 33. 700. ]
[ 33.5 610. ]
[ 33.5 650. ]
[ 34. 575. ]
[ 34. 685. ]
[ 34.5 620. ]
[ 35. 680. ]
[ 35. 700. ]
[ 35. 725. ]
[ 35. 720. ]
[ 36. 714. ]
[ 36. 850. ]
[ 37. 1000. ]
[ 38.5 920. ]
[ 38.5 955. ]
[ 39.5 925. ]
[ 41. 975. ]
[ 41. 950. ]
[ 9.8 6.7]
[ 10.5 7.5]
[ 10.6 7. ]
[ 11. 9.7]
[ 11.2 9.8]
[ 11.3 8.7]
[ 11.8 10. ]
[ 11.8 9.9]
[ 12. 9.8]
[ 12.2 12.2]
[ 12.4 13.4]
[ 13. 12.2]
[ 14.3 19.7]
[ 15. 19.9]]
- 넘파이는 파이썬의 대표적인 배열 라이브러리이다. 앞서서 파이썬의 리스트를 통해 2차원 리스트를 표현할 수 있었지만 고차원 리스트 표현에는 어려움이 따른다. 하지만 넘파이를 이용하면, 고차원의 배열을 손쉽게 만들 수 있다.
print(input_arr.shape)
(49, 2)
np.random.seed(42)
index = np.arange(49)
np.random.shuffle(index)
- 넘파이에서 무작위 결과를 만드는 함수들은 실행할 때마다 다른 결과를 만들어 낸다. 하지만 일정한 결과가 필요하기 때문에 초기에 랜덤시드를 지정해주면, 일정한 결과로 랜덤하게 만들어준다.
print(index)
[13 45 47 44 17 27 26 25 31 19 12 4 34 8 3 6 40 41 46 15 9 16 24 33
30 0 43 32 5 29 11 36 1 21 2 37 35 23 39 10 22 18 48 20 7 42 14 28
38]
3. 훈련셋과 테스트 셋 분리
train_input = input_arr[index[:35]]
train_target = target_arr[index[:35]]
test_input = input_arr[index[35:]]
test_target = target_arr[index[35:]]
- 랜덤한 인덱스를 이용해 훈련셋과 테스트셋을 아까와 같은 방법으로 나눠준다. (하지만 각 셋에는 일정하게 도미와 빙어가 섞여들어간다.)
plt.scatter(train_input[:,0], train_input[:,1])
plt.scatter(test_input[:,0], test_input[:,1])
plt.xlabel('lenght')
plt.ylabel('weight')
plt.show()
- 산점도를 이용해 확인해보면, 주황색이 테스트셋이고 파란색이 훈련셋이다. 도미와 빙어 데이터가 적절하게 섞여 들어간 것을 볼 수 있다.
kn = kn.fit(train_input, train_target)
kn.score(test_input, test_target)
1.0
- 다시 모델을 훈련시킨 결과를 살펴보면 정확하게 예측하는것을 볼 수 있다.
- predict()를 이용해 테스트 셋의 예측결과와 실제 타깃을 확인해보면 아래와 같다.
- 예측결과가 정답과 일치하는 결과를 알 수 있다.
- 이전의 예측과 다른것은 기존에는 모든 데이터셋을 이용해 100%의 결과를 도출했지만 이번에는 훈련때와 전혀 다른 데이터를 이용했음에도 정확하게 예측했다는 점에서 조금 더 신뢰감이 상승했다고 볼 수 있을 것이다.
kn.predict(test_input)
array([0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0])
4. 마치며
- 이번 시간에는 단순 데이터를 이용하는 것 뿐 아니라 훈련 셋과 테스트 셋을 분할해 완전히 다른 데이터를 예측하도록 만드는 것을 해보았다. 넘파이를 사용해 랜덤하게 데이터를 추출해 각각 세트에 탑재하고 이를 활용해 정확한 예측을 하는것을 배울 수 있었으며, 샘플링 편향이라는 새로운 개념도 알 수 있었다.
Leave a comment