02-2 데이터 전처리
02-2 데이터 전처리
올바른 결과 도출을 위한 데이터 전처리 과정 유무의 따른 모델의 훈련 차이와
표준점수로 특성의 스케일을 변환하는 방법
💡용어 정리💡
❓ tuple ➡️ 리스트와 배우 비슷하게 인덱스가 있지만, 수정이 불가능함!
❓ 데이터 전처리 ➡️ 특성값을 일정한 기준으로 맞춰 주는 작업
❓ 표준점수(z 점수) ➡️ 가장 널리 사용되는 전처리 (각 특성값이 표준편차의 몇 배만큼 떨어져 있는지를 나타냄)
–> 반드시!! 훈련 세트의 평균과 표준편차로 테스트 세트를 바꿔야 함!!
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,
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
# column_stack() --> 전달 받은 리스트를 일렬로 세운 다음 차례대로 짝지음!
# 원래는 zip()와 for()이용해서 리스트 업 한 뒤, 넘파이로 배열 생성
np.column_stack(([1, 2, 3], [4, 5, 6]))
실행결과)
array([[1, 4],
[2, 5],
[3, 6]])
2) 넘파이를 이용한 특성 데이터의 이차원 배열 생성 및 타깃 입력
-
concatenate() –> 첫 번째 차원을 따라 배열 연결
-
ones(), zeros() –> 원하는 개수의 1과 0을 채운 배열 생성
# 생선의 길이, 무게 데이터를 넘파이 배열로 생성
fish_data = np.column_stack((fish_length, fish_weight))
# 타깃 생성 --> 1 35개, 0 14개
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.]
3) train_test_split()를 이용한 훈련 세트와 테스트 세트 구분
- train_test_split() –> 사이킷런의 함수로 전달되는 리스트나 배열을 비율에 맞게 훈련 세트와 테스트 세트로 구분하며 기본적으로 25%를 테스트 세트로 지정
(나누기 전에 적절히 섞어서)
-
2개의 배열(fish_data, fish_target)을 전달했으므로! –> 2개씩 나뉘어 총 4개의 배열 반환
-
fish_data –> train_input, test_input
-
fish_target –> train_target, test_target
-
stratify 속성 –> 타깃 데이터를 전달하면 클래스 비율에 맞게 데이터를 나눔
(훈련 데이터가 작거나, 특정 클래스의 샘플 개수가 적을 때 유용함)
from sklearn.model_selection import train_test_split
# 각 훈련 데이터와 테스트 데이터를 train_test_split()를 이용하여 구분함!
train_input, test_input, train_target, test_target = train_test_split(fish_data, fish_target, random_state=42)
# 배분 상태 확인 --> shape()
print(train_input.shape, test_input.shape)
print(train_target.shape, test_target.shape)
print(test_target)
# stratify 속성 추가
train_input, test_input, train_target, test_target = train_test_split(fish_data, fish_target, stratify=fish_target, random_state=42)
print(test_target)
실행결과)
(36, 2) (13, 2)
(36,) (13,)
[1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[0. 0. 1. 0. 1. 0. 1. 1. 1. 1. 1. 1. 1.]
4) 모델 훈련 및 테스트
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(train_input, train_target)
kn.score(test_input, test_target)
실행결과)
1.0
임시 배열을 이용한 predict()
print(kn.predict([[25, 150]]))
실행결과)
[0.]
특성 산점도에 대해서 (25, 150)의 위치 파악
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()
실행결과)
(25, 150)에 가까운 이웃들을 산점도를 이용하여 파악
- kneighbors() –> KNeighborsClassifier 클래스의 메서드
–> 주어진 샘플에서 가장 가까운 이웃까지의 거리와 이웃의 인덱스를 반환
# kneighbors()를 이용하여 이웃들의 거리와 인덱스 반환 --> 리스트로 들어감
distances, indexes = kn.kneighbors([[25, 150]])
plt.scatter(train_input[:, 0], train_input[:, 1])
plt.scatter(25, 150, marker='^')
# 찾은 이웃 인덱스 5개를 산점도 표현
plt.scatter(train_input[indexes, 0], train_input[indexes, 1], marker='D') # 산점도를 마름모로 표시
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
# 하나를 제외하고, 나머지 4개가 전부 빙어 샘플
print(train_target[indexes])
실행결과)
5) 산점도의 x축과 y축의 범위를 동일하게 설정
- xlim() –> x축의 범위 설정 (ylim은 y축)
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')
# x축 범위를 0~1000으로 설정
plt.xlim((0, 1000))
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
실행결과)
6) 표준점수 구하기
-
np.mean() –> 평균 계산
-
np.std() –> 표준편차 계산
(axis=0 –> 행을 따라 각 열의 통계 값 계산, 생선의 길이/무게별로 계산!)
- 브로드캐스팅 –> 넘파이 배열에서 일어나는 기능, train_input의 각 열에 열마다 계산된 평균값과 표준편차를 모든 데이터에 대해 계산해줌!
# 평균 계산
mean = np.mean(train_input, axis=0)
# 표준편차 계산
std = np.std(train_input, axis=0)
# 원본 데이터에서 평균을 빼고 표준편차로 나누어서 표준점수로 환산
train_scaled = (train_input - mean) / std
테스트 세트만 표준화되어서 이상한 산점도가 생성됨
# 앞에서 계산된 표준점수를 이용해 산점도 생성
plt.scatter(train_scaled[:, 0], train_scaled[:, 1])
plt.scatter(25, 150, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
실행결과)
7) 테스트하고자 하는 샘플의 표준화 진행
- 테스트 세트를 표준화 했던 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()
실행결과)
8) 모델 훈련 및 평가
# 모델 훈련
kn.fit(train_scaled, train_target)
# 테스트 세트 또한 같은 방식으로 변환
test_scaled = (test_input - mean) / std
# 모델 평가
print(kn.score(test_scaled, test_target))
# 훈련 세트의 평균과 표준편차로 변환한 new를 예측! --> 1 이므로, 도미로 예측 성공
print(kn.predict([new]))
실행결과)
1.0
[1.]
비교하고자 했던 샘플의 이웃 샘플들 산점도로 그리기
# kneighbors를 이용하여 new(비교하고자 하는 샘플)의 이웃 샘플들의 거리와 인덱스 반환
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')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
실행결과)
댓글남기기