4 분 소요

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()

실행결과)

02


(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])

실행결과)

03


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()

실행결과)

04


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()

실행결과)

05


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()

실행결과)

06


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()

실행결과)

07

카테고리:

업데이트:

댓글남기기