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]
import numpy as np
#numpy의 column_stack() 함수는 전달받은 리스트를 일렬로
#세운 다음 차례대로 나란히 연결한다.
#연결할 리스트는 튜플로 전달한다.
np.column_stack(([1,2,3],[4,5,6]))
array([[1, 4], [2, 5], [3, 6]])
fish_data = np.column_stack((fish_length, fish_weight))
print(fish_data)
[[ 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]]
#np.column_stack() 옆으로 붙이기
#np.concatenate 뒤로 붙이기
fish_target = np.concatenate((np.ones(35),np.zeros(14)))
fish_target
array([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.])
train_test_split()함수
사이킷런은 머신러닝 모델을 위한 알고리즘 뿐만 아니라, 다양한 유틸리티 도구도 제공한다.
train_test_split() 함수는 전달되는 리스트나 배열을 비율에 맞게 훈련세트와 테스트세트로 나눠준다.
from sklearn.model_selection import train_test_split
#train_test_split()함수에는 자체적으로 랜덤 시드를 지정할 수 있는
#random_state 매개변수가 있다.
# 함수는 기본적으로 25%를 테스트 세트로 떼어 낸다
train_input,test_input,train_target, test_target =\
train_test_split(fish_data,fish_target, random_state=42)
print(train_input.shape,test_input.shape)
(36, 2) (13, 2)
print(train_target.shape, test_target.shape)
(36,) (13,)
print(test_target)
#샘플링 편향 현상이 나타남
[1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
#stratify 매개변수에 타깃데이터를 전달하면 클래스 비율에 맞게 데이터를 나눕니다.
train_input,test_input,train_target,test_target = \
train_test_split(fish_data, fish_target, stratify=fish_target, random_state=42)
test_target
#전체 비율과 비슷한 비율
array([0., 0., 1., 0., 1., 0., 1., 1., 1., 1., 1., 1., 1.])
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(train_input, train_target)
kn.score(test_input, test_target)
1.0
print(kn.predict([[25,150]]))
#빙어로 판단
[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()
distances, indexes = kn.kneighbors([[25,150]])
#클래스 이웃개수인 5개의 이웃이 반환된다(default)
indexes
array([[21, 33, 19, 30, 1]], dtype=int64)
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')
#수상한 도미의 이웃들 마름모로 나타내기
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
#가까운 이웃에 도미가 하나밖에 포함되지 않았다.
print(train_target[indexes])
#타깃 데이터로 확인
[[1. 0. 0. 0. 0.]]
print(distances)
[[ 92.00086956 130.48375378 130.73859415 138.32150953 138.39320793]]
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')
plt.xlim((0,1000))
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
#생선의 길이는 가장 가까운 이웃을 찾는데 영향을 끼치지 못한다.
데이터를 표현하는 기준이 다르면 알고리즘이 올바르게 예측할 수 없다. 알고리즘이 거리 기반 일 때 특히 그렇다.
제대로 사용하려면 특성값을 일정한 기준으로 맞춰 주어야 한다. 이런 작업을 데이터 전처리(data Preprocessing)라고 부른다.
가장 널리 사용하는 전처리 방법 중 하나는 표준점수(standard score)이다.
표준점수는 각 특성값이 평균에서 표준편차의 몇 배 만큼 떨어져 있는지를 나타낸다.
이를 통해 실제 특성값의 크기와 상관없이 동일한 조건으로 비교할 수 있다.
mean = np.mean(train_input,axis = 0)
#평균
std = np.std(train_input,axis =0)
#표준편차
특성마다 값의 스케일이 다르므로 평균과 표준편차는 각 특성별로 계산해야 한다. 이를 위해 axis = 0으로 지정했다. 이렇게 하면 행을 따라 각 열의 통계 값을 계산한다.
print(mean, std)
[ 27.29722222 454.09722222] [ 9.98244253 323.29893931]
train_scaled = (train_input - mean) / std
plt.scatter(train_scaled[:,0],train_scaled[:,1],train_scaled[:,1])
plt.scatter(25,150,marker = '^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
c:\Users\royal\anaconda3\lib\site-packages\matplotlib\collections.py:963: RuntimeWarning: invalid value encountered in sqrt scale = np.sqrt(self._sizes) * dpi / 72.0 * self._factor
# 샘플도 동일하게 mean, std를 이용하여 변환해야한다.
new = ([25,150]-mean)/std
plt.scatter(train_scaled[:,0],train_scaled[:,1])
plt.scatter(new[0],new[1],marker = '^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
kn.fit(train_scaled, train_target)
test_scaled = (test_input - mean)/std
kn.score(test_scaled, test_target)
1.0
print(kn.predict([new]))
#도미로 예측
[1.]
#산점도 다시 그려보기
distances,indexes = kn.kneighbors([new])
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()