데이터 전처리 ch2_2
데이터 전처리
- 데이터 전처리는 머신러닝 모델에 훈련 데이터를 주입하기 전에 가공하는 단계를 말한다.
- 표준점수는 훈련 세트의 스케일(단위)을 바꾸는 대표적인 방법 중 하나이다. 표준점수를 얻으려면 특성의 평균을 빼고 표준편차로 나눈다.
- 브로드캐스팅은 크기가 다른 넘파이 배열에서 자동으로 사칙 연산을 모든 행이나 열로 확장하여 수행하는 기능이다.
- train_test_split, kneighbors()
넘파이로 데이터 준비하기
1 | 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, |
1 | import numpy as np |
- 넘파이의 column_stack() 함수는 전달받은 리스트를 일렬로 세운 다음 차례대로 나란히 연결한다.
1 | np.column_stack(([1, 2, 3], [4, 5, 6])) |
array([[1, 4],
[2, 5],
[3, 6]])
- 이 방법으로 fish_length와 fish_weight를 합친다.
1 | fish_data = np.column_stack((fish_length, fish_weight)) |
[[ 25.4 242. ]
[ 26.3 290. ]
[ 26.5 340. ]
[ 29. 363. ]
[ 29. 430. ]]
타깃 데이터
1 | print(np.ones(5)) |
[1. 1. 1. 1. 1.]
[0. 0. 0. 0. 0.]
- 이 두 함수를 가지고 1이 35개인 배열과 0이 14개인 배열을 만든다.
- 그다음 두 배열을 연결한다.
- np.column_stack() 함수를 사용하지 않고 첫 번째 차원을 따라 배열을 연결하는 np.concatenate() 함수를 사용한다.
1 | fish_target = np.concatenate((np.ones(35), np.zeros(14))) |
[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() 함수
- 훈련 데이터를 훈련 세트와 테스트 세트로 나누는 함수이다. 여러 개의 배열을 전달할 수 있다. 테스트 세트로 나눌 비율은 test_size 매개변수에서 지정할 수 있으며 기본값은 0.25이다.
- shuffle 매개변수로 훈련 세트와 테스트 세트로 나누기 전에 무작위로 섞을지 여부를 결정할 수 있다. 기본값은 True.
- stratify 매개변수에 클래스 레이블이 담긴 배열(일반적으로 타깃 데이터)을 전달하면 클래스 비율에 맞게 훈련 세트와 테스트 세트를 나눈다.
1 | from sklearn.model_selection import train_test_split |
- train_test_split() 함수에는 자체적으로 랜덤 시드를 지정할 수 있는 random_stat 매개변수가 있다.
1 | # fish_data와 fish_target을 나눈다. |
- 2개의 배열을 전달했으므로 2개씩 나뉘어 총 4개의 배열이 반환된다.
1 | # 잘 나누었는지 확인 |
(36, 2) (13, 2)
(36,) (13,)
- 훈련 데이터와 테스트 데이터를 36개와 13개로 나누었다.
- 입력 데이터는 2개의 열이 있는 2차원 배열이고 타깃 데이터는 1차원 배열이다.
- 도미와 빙어가 잘 섞였는지 테스트 데이터를 출력해본다.
1 | print(test_target) |
[1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
- 13개의 테스트 세트 중에 10개가 도미(1)이고, 3개가 빙어(0)이다.
- 빙어의 비율이 조금 모자르다.
- 원래 2.5:1 비율이었는데, 테스트 세트의 비율은 3.3:1으로 샘플링 편향이 나타났다.
stratify 매개변수
- 이것을 활용해 비율을 맞출 수 있다.
- 해당 매개변수에 타깃 데이터를 전달하면 된다.
1 | train_input, test_input, train_target, test_target = train_test_split( |
1 | print(test_target) |
[0. 0. 1. 0. 1. 0. 1. 1. 1. 1. 1. 1. 1.]
- 빙어가 한 마리 늘어나면서 테스트 세트의 비율도 2.25:1이 되었다.
수상한 도미 한 마리
- 앞서 준비한 데이터로 k-최근접 이웃 모델로 훈련해보자.
1 | from sklearn.neighbors import KNeighborsClassifier |
1.0
- 이 모델에 김 팀장이 알려준 도미 데이터를 넣고 결과를 확인하면 당연히 도미로 예측할까?
1 | print(kn.predict([[25, 150]])) |
[0.]
- 당황스러운 결과가 도출.
- 시각화로 확인해보자.
1 | import matplotlib.pyplot as plt |

- 분명히 도미쪽에 가까운 것 같은데… 이상하다.
- 이 샘플의 주변 샘플을 알아보자.
- KNeighborsClassifier 클래스의 kneighbors() 메서드를 활용한다.
- 기본값은 5로, 5개의 이웃이 반환된다.
1 | distances, indexes = kn.kneighbors([[25, 150]]) |
- 시각화로 표현해보자.
1 | fig, ax = plt.subplots() |

- 이웃한 샘플이 빙어가 4개, 도미가 1개구나!
1 | print(train_input[indexes]) |
[[[ 25.4 242. ]
[ 15. 19.9]
[ 14.3 19.7]
[ 13. 12.2]
[ 12.2 12.2]]]
1 | print(train_target[indexes]) |
[[1. 0. 0. 0. 0.]]
- 왜 가장 가까운 이웃을 빙어라고 생각한 걸까?
- 실마리를 찾기 위해 distances 배열을 출력해보자. 이 배열에는 이웃 샘플까지의 거리가 담겨 있다.
1 | print(distances) |
[[ 92.00086956 130.48375378 130.73859415 138.32150953 138.39320793]]
기준을 맞춰라
- x축은 범위가 좁고(10
40), y축은 범위가 넓다(01000). - 이를 명확히 확인하기 위해 x축의 범위를 동일하게 0~1000으로 맞추어 보자.
- xlim() 함수를 사용한다.
1 | fig, ax = plt.subplots() |

- 산점도가 거의 일직선으로 나타난다.
- 이런 데이터라면 생선의 길이(x축)는 가장 가까운 이웃을 찾는 데 크게 영향을 미치지 못한다.
- 오로지 생선의 무게(y축)만 고려 대상이 된다.
스케일(scale)
- 두 특성의 값이 놓인 범위가 다르다 = 두 특성의 스케일이 다르다
- 스케일을 같게 만들어 주는 것이 데이터 전처리(data preprocessing)이다.
데이터 전처리
- 가장 널리 사용하는 전처리 방법은 표준점수(standard score)이다.
1 | mean = np.mean(train_input, axis=0) |
[ 27.29722222 454.09722222] [ 9.98244253 323.29893931]
- axis=0은 행을 따라(아래방향), axis=1은 열을 따라(오른쪽방향) 통계값을 계산한다.
- 각 특성마다 평균과 표준편차가 구해졌다.
1 | # 표준점수 |
브로드캐스팅(broadcasting)
- 넘파이는 train_input의 모든 행에서 mean에 있는 두 평균값을 빼준다.
- 그다음 std에 있는 두 표준편차를 모든 행에 적용한다.
- 이러한 넘파이의 기능을 브로드캐스팅이라고 한다.
전처리 데이터로 모델 훈련하기
1 | plt.scatter(train_scaled[:,0], train_scaled[:,1]) |

- 주황색 세모가 동떨어져 있는 것은 당연하다.
- 표준화해주지 않았기 때문이다.
- 표준화를 해주고 다시 시각화해보자.
1 | new = ([25, 150] - mean) / std |

- x축과 y축의 범위가 -1.5~1.5 사이로 바뀌었다.
- 이제 이 데이터셋으로 k-최근접 이웃 모델을 다시 훈련해 보자.
1 | kn.fit(train_scaled, train_target) |
KNeighborsClassifier()
1 | test_scaled = (test_input - mean) /std |
1 | # 평가 |
1.0
- 앞서 골칫거리를 도미로 예측하는지 확인해보자
1 | print(kn.predict([new])) |
[1.]
- 제대로 예측했다.
- 그림으로 다시 확인해보자
- 아까와는 달리 가장 가까운 이웃에 변화가 생겼을 것이다.
1 | distances, indexes = kn.kneighbors([new]) |

- 주황색 세모가 가장 가까운 샘플은 모두 도미임을 확인했다.
데이터 전처리 ch2_2
You need to set
install_url to use ShareThis. Please set it in _config.yml.