기본편 게시물과 전혀 다른 방법으로, numpy로 세련되게 데이터를 정리해보자
column_stack(리스트1, 리스트2.. .) <- 리스트 첫째 값을 1행, 둘째 값을 2행.. 등 으로 묶는 함수
import numpy as np
fish_data = np.column_stack((fish_length, fish_weight))
# 길이와 무게 data를 이렇게 한번에 묶는다.
print(fish_data[:5])
[[ 25.4 242. ]
[ 26.3 290. ]
[ 26.5 340. ]
[ 29. 363. ]
[ 29. 430. ]]
ones(개수), zeros(개수) : 개수만큼 1(0)을 리스트로 반환
concentrate(리스트1, 리스트2...) : 리스트들을 그대로 가로로 이어붙이기
fish_target = np.concatenate((np.ones(35), np.zeros(14)))
print(fish_target)
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0.]
(!) numpy array 사용 이유: 데이터 클수록 파이썬 리스트는 비효율적이므로 array(배열; matrix) 사용 권장.
train, test set 한 번에 나누기
from sklearn.model_selection import train_test_split
# Test 데이터를 2.5:1로(test size 미입력 default) 분할
train_input, test_input, train_target, test_target = train_test_split(fish_data, fish_target,
stratify=fish_target, random_state=42)
stratify = target data로 지정하여 sampling bias를 방지
KN으로 다시 훈련.
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(train_input, train_target) #훈련
kn.score(test_input, test_target) #테스트
1.0 <- 100%
print(kn.predict([[25, 150]])) # 도미데이터 예측 시도
[0.] <- 1이 나와야하는데 0이 나온다. 그래프로 보자
import matplotlib.pyplot as plt
plt.scatter(train_input[:,0], train_input[:,1])
plt.scatter(25, 150, marker='^') # 마커로 표시하기.
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
이유는 KN default 개수가 5개인데 가까운 5개 주변값중 4개가 빙어이기 때문이다.
distances, indexes = kn.kneighbors([[25, 150]]) # 특정 데이터 주변의 5개 거리, 인덱스 반환
print('distances = ', distances) # 5개의 이웃 데이터의 거리
print('indexes = ', indexes) # 5개의 이웃 인덱스 번호
distances = [[ 92.00086956 130.48375378 130.73859415 138.32150953 138.39320793]]
indexes = [[21 33 19 30 1]]
plt.scatter(train_input[:,0], train_input[:,1]) # 전체 데이터를 스케터 플랏에 표시
plt.scatter(25, 150, marker='^')
plt.scatter(train_input[indexes,0], train_input[indexes,1], marker='D')
#위 index 5개 값을 Diamond로 표시
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
print(train_target[indexes]) # 위 인덱스의 training Target data(1:도미, 0:빙어)
[[1. 0. 0. 0. 0.]] <- 이러니 다수결로 0이 출력됨
더 큰 문제는 x축과 y축 단위가 g와 cm으로 다르다는 점이 문제다. 즉, 두 값의 scale이 다르다. 이 둘의 측정 단위가 다른데 KN으로 근사 5개 값을 찾는게 정확하다고 보기 힘들다.
이에 따라 두 데이터를 표준점수로 만들어서 측정해야한다. 가장 무난하고 대중적인 scale 정리 방법이다.
표준점수 = (데이터 - 평균) / 표준편차
mean = np.mean(train_input, axis=0) # axis=0:행을 고정, 열의 평균을 구함
std = np.std(train_input, axis=0)
train_scaled = (train_input - mean) / std # 표준점수로 변환된 데이터
new = ([25, 150] - mean) / std # 샘플 25, 150 데이터를 동일한 비율로 변환한 것.
plt.scatter(train_scaled[:,0], train_scaled[:,1]) # 동일한 비율로 변환된 train data 표시
plt.scatter(new[0], new[1], marker='^') # 샘플 25, 150을 동일한 비율로 변환된 data 표시
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
test_scaled = (test_input - mean) / std
# train set 기준으로 변환된 테스트 데이터 값. 까먹지 말고 변환!
kn.fit(train_scaled, train_target) # 동일한 비율로 변환된 데이터 값 학습
kn.score(test_scaled, test_target)
1.0 <- 100%
print(kn.predict([new])) # 샘플데이터 빙어로 예측
[1.]
K 근방 5 이웃이 어떻게 잡혔는지 그래프로 보자
distances, indexes = kn.kneighbors([new]) # KN의 거리, 인덱스 default 5개 출력
plt.scatter(train_scaled[:,0], train_scaled[:,1])
plt.scatter(new[0], new[1], marker='^') # 측정하고자하는 값
plt.scatter(train_scaled[indexes,0], train_scaled[indexes,1], marker='D') #주변 5개
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
제대로 분류하였다.
'Programming > Python' 카테고리의 다른 글
[ML] Feature engineering, 다중회귀, 릿지회귀, 라쏘회귀 (1) | 2023.09.11 |
---|---|
[ML] KN 회귀 알고리즘, 선형회귀, 다항회귀 (0) | 2023.09.11 |
[ML] KN 분류 알고리즘 (기본편) (0) | 2023.09.11 |
[ML] Gradient Descent(경사하강법) (1) | 2023.09.07 |
[ML] Cross Validation(CV; 교차검증), Grid Search (0) | 2023.09.07 |