[머신러닝] 데이터 전처리 - 표준점수

데이터 전처리 - 표준점수


데이터 전처리란?

데이터 전처리(data preprocessing)란 머신러닝 모델에 훈련 데이터를 주입 하기 전에 가공하는 단계를 말한다. 데이터 전처리 작업을 거치지 않으면 모델의 학습 및 예측이 정확하게 이뤄지지 않을 수가 있다.


아래 그림을 보면 머신러닝 모델을 만드는 순서다.
크게 보면 데이터 준비 -> 데이터 전처리 -> 모델 훈련 -> 모델 평가 순서로 볼 수 있다.





표준점수란?

표준 점수(standard score)는 데이터 전처리 방법 중 하나다. 표준 점수는 각 특성 값이 평균에서 표준편차의 몇 배 만큼 떨어져 있는지 나타낸다.
표준점수는 이번 게시물에서 다룰 내용이다.



훈련 세트, 테스트 세트 만들기

우선 데이터 전처리 중 표준점수가 어디에 쓰는지 알기 위해서 모델부터 만들자.
K-최근접 이웃 알고리즘으로 모델을 만들기 위해서 훈련 세트테스트 세트를 만들자.
import numpy as np

#데이터 준비하기 ----------------------------------------------------------
child_height = [120,122,124,128,130,132,134,136,138,140] #어린이 특성
child_weight = [45,47,48,40,50,45,47,48,40,50]

adult_height = [170,175,180,185,190] #어른 특성
adult_weight = [300,350,300,400,450]

height = child_height + adult_height #리스트 합치기
weight = child_weight + adult_weight #리스트 합치기

#넘파이 column_stack()함수로 2차원 리스트 만들기
person_data = np.column_stack((height, weight))

# 정답 데이터 만들기/ 어린이는 0 어른은 1
#넘파이 concatenate() 함수는 두개의 배열을 이어준다.
#np.zero 0 10개 만들어 준다., np.ones 1 5개 만들어준다.
person_target = np.concatenate((np.zeros(10), np.ones(5)))


#훈련 세트, 테스트 세트 나누기----------------------------------------------------------
# 사이킷런 train_test_split함수는 리스트나 배열을 무작위로 섞고 알아서 나눠준다.
from sklearn.model_selection import train_test_split

#train_test_splite 25%를 테스트 세트로 떼어내어 샘플링 편향이 나타 날 수있다.
#이 때 stratify 변수에 타깃데이터를 전달하면 클래스 비율에 맞게 데이터를 나눈다.
train_input, test_input, train_target, test_target = (
train_test_split(person_data, person_target, stratify = person_target, random_state=42))


모델 평가하기

사이킷런으로 모델을 평가해보자.
정확도 100%가 나온다. 여기 까지는 문제가 없어 보인다.
#모델 평가하기 ------------------------------------------------------------------------
from sklearn.neighbors import KNeighborsClassifier #사이킷런 Kneighclass import

kn = KNeighborsClassifier()
kn.fit(train_input, train_target) #훈련 시키기
a = kn.score(train_input, train_target) #모델 평가하기
print(a)
결과 : 1.0



예측할 데이터를 포함한 산점도 그리기

이제 한번 예측 할 데이터 175, 200에 주황색 별을 찍어보자.
파랑 색 원은 현재 훈련 세트 입력 데이터다.
왼쪽에 모여있는 원 7개가 child 특성이며 오른쪽 상단에 원 4개는 adult특성이다.
그에 따라 사이킷런으로 perdict을 한다면 adult에 가까운 주황색 별은 adult가 나와야 한다.
현재 adult target은 1이다.
#그래프 그리기 -----------------------------------------
import matplotlib.pyplot as plt #그래프 그리는 패키지 import

plt.scatter(train_input[:,0], train_input[:,1])
plt.scatter(175, 200, marker ='*')

plt.xlabel('height')
plt.ylabel('weight')
plt.show()
결과 : 




새로운 데이터 예측하기

위에 산점도를 봤을 때 새로운 데이터(주황색 별)은 adult로 예상 가능 했다.
이제 predict 함수로 예측을 해보고 결과를 보자.
어라? 0(child)가 나왔다. 분명 새로운 데이터는 adult 와 가까운데 말이다.
#모델 예측하기 ------------------------------------------------------------------------
b = kn.predict([[175,200]])
print(b)
결과 : [0.]



child가 나오는 것은 스케일이 다르기 때문

산점도를 보면 X축은 35, Y축은 100이 차이난다.
따라서 Y축은 크게 영향을 미치지 못하고 X축만 고려되어 child(0)이 나오게 된다.
child와 adult 처럼 두 개의  특성의 값이 놓인 범위가 다른 것을 스케일이 다르다고 표현한다. 정확한 데이터를 보기 위해서는 특성 값을 일정한 기준으로 맞춰야 하며 이 과정을 데이터 전처리라고 부른다.



표준점수 만들기

위에 문제들을 해결하기 위해서는 데이터 전처리 방법 중하나인 표준점수를 만들어야 한다.
우선 표준편차란  분산의 제곱근으로 데이터가 분산 된 정도를 나타낸다.
표준점수는 각 데이터가 원점에서 표준편차의 몇 배만큼 떨어져 있는지 나타낸다.

계산은 다음과 같다. 평균을 빼고 표준편차를 나눠주면 된다.
이때 넘파이는 평균 구하는 함수, 표준편차 계산함수 이 두 함수를 제공한다.
이렇게 알아서 계산해주는 넘파이 기능을 브로드캐스팅 이라고 부른다.
#표준점수 구하기------------------------------------------------------------------------
mean = np.mean(train_input, axis = 0) #평균 계산
std = np.std(train_input, axis = 0) #표준편차 계산

train_scaled = (train_input - mean)/std #표준점수 구하기


산점도 그려보기

표는 바뀌지 않았지만 x, y축이 -1.0 ~ 1.5 사이로 바꼈다.
#표준 점수 구한 후 그래프 그리기 -----------------------------------------
new = ([175, 200] - mean) / std
plt.scatter(train_scaled[:,0], train_scaled[:,1])
plt.scatter(new[0], new[1], marker ='*')

plt.xlabel('height')
plt.ylabel('weight')
plt.show()
결과 :



모델 평가하고 예측하기

평가는 당연히 100%가 나오고
예측 데이터도 예상 한 결과 adult(1)로 나오게 된다.
#표준 점수 구한 후 모델 평가하기 ------------------------------------------------------------------------
from sklearn.neighbors import KNeighborsClassifier #사이킷런 Kneighclass import

kn = KNeighborsClassifier()
kn.fit(train_scaled, train_target) #훈련 시키기
a = kn.score(train_scaled, train_target) #모델 평가하기
print(a)

#준 점수 구한 후 새로운 데이터 예측하기 ------------------------------------------------------------------------
b = kn.predict([[175,200]])
print(b)
결과 : 
1.0
[1.]



전체 소스 코드

이 게시물에서 사용한 소스 코드다.
import numpy as np

#데이터 준비하기 ----------------------------------------------------------
child_height = [120,122,124,128,130,132,134,136,138,140] #어린이 특성
child_weight = [45,47,48,40,50,45,47,48,40,50]

adult_height = [170,175,180,185,190] #어른 특성
adult_weight = [300,350,300,400,450]

height = child_height + adult_height #리스트 합치기
weight = child_weight + adult_weight #리스트 합치기

#넘파이 column_stack()함수로 2차원 리스트 만들기
person_data = np.column_stack((height, weight))

# 정답 데이터 만들기/ 어린이는 0 어른은 1
#넘파이 concatenate() 함수는 두개의 배열을 이어준다.
#np.zero 0 10개 만들어 준다., np.ones 1 5개 만들어준다.
person_target = np.concatenate((np.zeros(10), np.ones(5)))


#훈련 세트, 테스트 세트 나누기----------------------------------------------------------
# 사이킷런 train_test_split함수는 리스트나 배열을 무작위로 섞고 알아서 나눠준다.
from sklearn.model_selection import train_test_split

#train_test_splite 25%를 테스트 세트로 떼어내어 샘플링 편향이 나타 날 수있다.
#이 때 stratify 변수에 타깃데이터를 전달하면 클래스 비율에 맞게 데이터를 나눈다.
train_input, test_input, train_target, test_target = (
train_test_split(person_data, person_target, stratify = person_target, random_state=42))

#모델 평가하기 ------------------------------------------------------------------------
from sklearn.neighbors import KNeighborsClassifier #사이킷런 Kneighclass import

kn = KNeighborsClassifier()
kn.fit(train_input, train_target) #훈련 시키기
a = kn.score(train_input, train_target) #모델 평가하기
print(a)

# #그래프 그리기 -----------------------------------------
import matplotlib.pyplot as plt #그래프 그리는 패키지 import
#
# plt.scatter(train_input[:,0], train_input[:,1])
# plt.scatter(175, 200, marker ='*')
#
# plt.xlabel('height')
# plt.ylabel('weight')
# plt.show()

#새로운 데이터 예측하기 ------------------------------------------------------------------------
b = kn.predict([[175,200]])
print(b)

#표준점수 구하기------------------------------------------------------------------------
mean = np.mean(train_input, axis = 0) #평균 계산
std = np.std(train_input, axis = 0) #표준편차 계산

train_scaled = (train_input - mean)/std #표준점수 구하기


#표준 점수 구한 후 그래프 그리기 -----------------------------------------
new = ([175, 200] - mean) / std
plt.scatter(train_scaled[:,0], train_scaled[:,1])
plt.scatter(new[0], new[1], marker ='*')

plt.xlabel('height')
plt.ylabel('weight')
plt.show()

#표준 점수 구한 후 모델 평가하기 ------------------------------------------------------------------------
from sklearn.neighbors import KNeighborsClassifier #사이킷런 Kneighclass import

kn = KNeighborsClassifier()
kn.fit(train_scaled, train_target) #훈련 시키기
a = kn.score(train_scaled, train_target) #모델 평가하기
print(a)

#준 점수 구한 후 새로운 데이터 예측하기 ------------------------------------------------------------------------
b = kn.predict([[175,200]])
print(b)


참조


혼자 공부하는 머신러닝 + 딥러닝(깃 허브) : https://github.com/rickiepark/hg-mldl


댓글

이 블로그의 인기 게시물

[Arduino] 아두이노 초음파 센서(HC-SR04) 사용하기

[Arduino] 아두이노 조이스틱 사용하기

[자연 환경] 농약의 장단점 농약이 환경과 인간에게 미치는 영향