사이킷런으로 train_set / test_set 나누기
from sklearn.model_selection import train_test_split
머신러닝 혹은 딥러닝을 한번즘 보셨다면, 이런 코드를 흔히 보셨을 겁니다.
sklearn.mode_selection 에서 train_test_split이라는 기능을 소개하며 데이터 전처리의 흐름을 소개하겠습니다.
train_set과 test_set으로 올바르게 나누는 것은 매우 중요합니다. 예시를 들겠습니다.
bream_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]
bream_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]
smelt_length = [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]
smelt_weight = [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]
length = bream_length + smelt_length
weight = bream_weight + smelt_weight
fish_data = [[l,w] for l,w in zip(length,weight)]
fish_target = [1] *35 + [0] *14
train_input = fish_data[:35]
train_target = fish_target[:35]
test_input = fish_data[35:]
test_target = fish_target[35:]
임의의 빙어와 도미 데이터가 있습니다. KNN 학습 전에 먼저 train_set과 test_set을 나누기 위해 위와 같이 작업했습니다.
하지만 이와 같이 나누고 점수를 확인해본다면 Score가 0.0에 무조건적으로 박힐 것 입니다.
이유는 단순합니다. 현재 annotation이 데이터셋에 맞쳐져 있는데 fish_data[:35] 까지는 도미 데이터이고 fish_data[35:]는 빙어 데이터 입니다. 이렇게 학습 데이터를 나눈다면 의미가 없습니다. 왜냐하면 빙어 데이터는 학습하지 않기 때문입니다.
빙어 데이터를 예측하려고 넣는다면 KNN이 참고하는 점에는 도미 밖에 없으니 도미만 인식 할 것 입니다. 그렇다면 정확도는 0이 나옵니다.
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
print(kn.fit(train_input, train_target))
print(kn.score(test_input, test_target))
이를 방지하기 위해 직접 shuffle을 번거롭게 하는 것 보다 sklearn을 적극적으로 사용하시면 됩니다.
하지만 sklearn도 자체적으로 랜덤 시드를 지정하게 된다면 의도치 않게 편향된 학습 데이터가 나올 수도 있습니다.
이를 방지하고자 stratify 매개변수가 존재합니다.
train_input, test_input , train_target, test_target = train_test_split(fish_data, fish_target,stratify=fish_target,random_state=42)
stratify 매개변수에 타깃 데이터를 전달하면 클래스 비율에 맞게 데이터를 나눕니다. 하지만 여기서 표현하는 클래스는 파이썬에서 나타내는 클래스가 아닌 피쳐라고 생각하시면 됩니다.
이제 데이터를 올바르게 나누고 학습 할 준비가 됐습니다.
바로 학습 해보겠습니다. train_input , train_target , test_input, test_target은 위에서 얻은 인자를 그대로 받겠습니다.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.modeL_selection import train_test_split
kn = KNeighborsClassifier()
kn.fit(train_input, train_target)
kn.score(test_input, test_target)
정확도가 100%가 됐습니다. 데이터가 적어서 가능할 순 있지만 현실 세계에서 정확도 100%는 좋은 결과는 아닙니다.
아마 모델링 하시다 보면 가장 무서운게 정확도가 100%로 예측하는 것 입니다. 이는 나중에 배우게 될 오버핏팅과 관련이 있습니다. 이번에 [25,100]의 데이터를 가진 도미(1)을 예측해보겠습니다. 정확도가 100%라고 한다면 도미로 예측할 수 있다는 것이 일반적인 생각입니다.
0으로 예측을 했습니다. 0은 빙어를 라벨한 숫자입니다. 올바르지 않게 예측했습니다.
왜 그런걸까요?
현재 cyan색으로 된 세모 부분입니다. 최근접으로 따진다면 직관적으로 봤을 때 어느 부분에 최근접으로 됐는지 한번 생각해보시길 바랍니다. 다음 게시글에서 왜 라벨0이 나왔는지에 대해 설명하겠습니다.
'Machine-Learning' 카테고리의 다른 글
Linear Regression _ 선형 회귀 (4) | 2025.03.26 |
---|---|
K-NN Regression _ K-최근접 이웃 회귀 (1) | 2025.03.26 |
Scaling ? Z-score (1) | 2025.03.19 |
K-Nearest Neighbors, KNN (0) | 2025.03.13 |