공부/머신러닝

[ 머신러닝 프로그램 ] k-최근접 이웃 분류 알고리즘 ver3 - 데이터 전처리

haena02 2023. 2. 13. 19:45
반응형

버전2의 머신러닝 프로그램은 완벽해보인다.

하지만 어떤 도미를 넣으면 빙어라고 판단하기도 한다!

이는 데이터들이 덜 가공되었기 때문이다.

이런 부분을 데이터 전처리로 해결해보자!

 

기본 데이터 준비

 

#머신러닝 프로그램 ver3


import numpy as np
import matplotlib.pyplot as plt 
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split

#도미의 정보
bream_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]
bream_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]
#빙어의 정보
smelt_length = [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]
smelt_weight = [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]

#머신러닝을 만들기 위한 데이터가공
length = bream_length+smelt_length
weight=bream_weight+smelt_weight

fish_data=np.column_stack((length, weight))  #인자로 받은 값을 하나의 열로 하는 2차원 리스트 생성

#정답데이터
target=np.concatenate((np.ones(35),np.zero(14)))  #1를 35개, 0을 14개 만들고 합친 리스트 생성

#훈련데이터와 테스트데이터 생성
train_input, test_input, train_target, test_target = train_test_split(fish_data, fish_target,stratity=fish_target,random_state=42)

먼저 기본적으로 필요한 데이터들을 세팅하였다.

저번과는 다르게 numpy의 기능을 많이 활용하였다.

몇개의 함수들을 소개 해보겠다.

column_stack()함수는 인자로 받은 리스트를 열로 만들어 나열하는 함수이다.

cocatenate()함수는 인자로 받은 리스트를 하나의 행으로 합치는 함수이다.

ones()zero()함수는 인자로 받은 수만큼 1과 0을 채운 리스트를 만들어준다.

 

또, 사이킷런에서는 훈련데이터와 테스트데이터를 생성해주는 함수도 있다.

이는 sklearn.model_selection 안에 들어있는 train_test_split()함수이다. 

이 함수는 인자에 나누고싶은 리스트를 넣으면 잘 섞어서 훈련데이터와 테스트 데이터로 반환해준다.

stratity 옵션을 이용하면 원하는 리스트와 비율을 맞출 수 있다. 

 

문제점 찾기

 

이 머신러닝은 아마 정확도 100이 나올 것이다.

하지만 길이가 25이고 무게가 150인 도미를 넣으면 빙어라고 판단한다. 

실제로 산점도에 나타내보면 육안으로 보기에는 도미들과 훨씬 가깝지만 머신러닝은 빙어랑 더 가깝다고 판단한다.

 

이는 길이의 범위는 10~40으로 좁고 무게는 0~1000으로 훨씬 넓기 때문이다.

그래서 눈으로 보는 것보다 무게차이가 더 많이 반영이 되는것이다..!

 

이를 스케일이 다르다고 표현한다.

xlim과 ylim을 히용해서 범위를 직접 조정해줄 수도 있다.

 

데이터 전처리

 

가장 널리 사용하는 전처리 방법 중 하나는 표준점수를 이용하는 것이다. 

표준점수는 각 특성값이 평균에서 표준편차의 몇 배만큼 떨어져 있는지 나타낸다

그렇게되면 특성값과 상관없이 동일한 조건으로 비교할 수 있다.

 

펑균과 표준편차를 구하는 함수가 numpy에 다 있기 때문에 어렵지 않게 구할 수 있다.

mean=np.mean(train_input,axis=0)
std=np.std(train_input,axis=0)

axis가 0이기 때문에 열의 평균을 각각 구해서 리스트에 저장된다.

train_scaled=(train_input-mean)/std

그 다음 표준점수를 구해준다.

이렇게 해주면 리스트 안의 값이 각각 계산되어 리스트로 만들어진다.

이런 넘파이기능을 브로드캐스팅이라고 한다. 

 

그 다음 다시 길이가 25, 무게가 150인 도미로 테스트해보자.

여기서 주의해야할 점은 테스트 값도 표준점수로 나타내야한다는 것이다. 

 

new=([25,150]-mean)/std

kn=KNeighborsClassifier()
kn.fit(train_scaled,train_target)
print(kn.predict([new]))

실제로 위 코드로 테스트를 진행해보면 1, 즉 도미가 나온다!!

반응형