2 - 2 데이터 전처리


앞의 모델에서, height = 25 , weight = 150의 데이터를 입력하면 도미가 아닌 빙어라고 예측한다.

이 문제를 해결하기 전, 먼저 데이터를 더 학습해보자.

 

데이터 다시 준비

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
np.columns_stack(([1,2,3],[4,5,6]))

array([[1,4],
       [2,5],
       [3,6]])

np.column_stack() = 전달받은 리스트를 일렬로 세운 다음 차례대로 나란히 연결해준다. [columns=열]

쉽게 말해, 리스트 안의 index끼리 차례대로 묶어 2개씩 리스트를 생성함. (이게 쉽게 말한거야?)

 

이 방법을 통해 fish data를 새로 만들어보자.

import numpy as np
fish_Data = np.columns_stack((fish_length,fish_weight))

# 잘 되었는지 확인하기 위해 5개의 표본만 살펴보자.
fish_Data[:5]

[[25.4 , 242], [26.3 , 290], [26.5 , 340], [29 , 340], [29 , 430]

ㅇㅋ 잘 되었다.

 

학교때 배운 numpy의 다양한 메서드들을 이용해 타겟도 만들어보자.

np.concatenate() = 배열 합치기

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,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,,0,0,0,0,0,0,0,0,0,0,0]

 

# 사이킷런으로 훈련 세트와 테스트 세트 나누기

앞의 인덱스 섞는 방법(random.shuffle) 보다 쉽게 쓸 수 있는 방법이 있다.

사이킷런은 머신러닝을 포함한 다양한 유틸리티 도구를 제공한다.

 

from sklearn.model_selection import train_test_split

tarin_set , test_set, train_target, test_target = train_test_split(fish_Data, fish_target, random_state=42)

train_test_split() : 매개변수의 리스트나 배열을 비율에 맞게 훈련세트와 테스트 세트로 나누어 준다 !

위에서는 2개의 배열을 전달했으므로 총 4개의 배열이 반환된다.

첫 번째 배열의 훈련,테스트 세트,

두 번째 배열의 훈련,테스트 세트

 

train_test_split(input, target, 랜덤시드)

 

# 복습 : [ 데이터 = 입력 = input  ] + [ 정답 = target ] = 훈련 데이터

 

이제 맨 위에서 도미 분류 오류를 살펴보자! 

from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(train_set, train_target)
kn.score(test_set, test_target)
1.0
print(kn.predict([[25, 150]])

0.0  # 도미= 1, 빙어 = 0

코드만 보고 문제는 해결되지 않으니 그림이라도 그려보자.

import matplotlib.pyplot as plt
plt.scatter(train_set[:,0],train_set[:,1])
plt.scatter(test_set[:,0], test_set[:,1])
plt.xlable("length")
plt.ylabel("weight")
plt.show()

직관적으로 그림만 보면 도미데이터와 가까워 보인다. 하지만 컴퓨터는 빙어로 인식한다. 왜일까? (x,y축 비율때문이다.)

우선 그 전에 Kneighborsclassifier()의 5가지 기준샘플들을 보기좋게 표시해보자.

distances , indexes = kn.kneighbors([[25,150]]) # 25,150의 k최근접이웃 5개의 거리와 인덱스번호

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') #깊생
plt.show()

5개의 기준샘플 중 다수(3개)는 빙어였다 ! 

직접 거리를 출력해보자.

print(distances)

array([[ 92.00086956, 130.48375378, 138.32150953, 140.00603558,
        140.62090883]])

92,130,138,140 이상하다. 기준을 맞춰보자! 

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')
plt.xlim((0,1000))
plt.show()

x축과 y축의 비율을 같게 했더니 일직선으로 나온다!! 이렇게 보면 직관적으로 봐도 k최근접 알고리즘과 유사하게 도출할 수 있다.

 

★★★이렇게 데이터를 일정한 기준으로 맞춰주는 것을 데이터 전처리라고 한다.★★★

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

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

표준점수 = 각 값에서 평균을 빼고 표준편차로 나누어 주면 된다. [ 넘파이를 통해 도출 ]

mean = np.mean(train_input, axis = 0)   # axis = 0, axis = 1 차이점?
std = np.std(train_input, axis = 1 )

axis = 0 : 행을 따라 각 열의 값들을 계산     ( 이게 맞다 !)             

axis = 1 : 열을 따라 각 행들의 값들을 계산 ( 행마다 값이 나옴 !)             (책 그림 p.100참조)

print(mean,std)

[ 26.175      418.08888889] [ 10.21073441 321.67847023]

표준점수 구하기 !!!! 값-평균/표편

train_scaled = (train_input - mean) / std   # 자동으로 해줌 = 브로드캐스팅

다시 산점도를 그려보자!

new = ([25,150]-mean/std)
plt.scatter(train_scaled[:,0],train_scaled[:,1])
plt.scatter(new[0],new[1],marker='^')
plt.show()

x,y축의 값이 -1.5~1.5로 바뀜!

 

다시 훈련시켜보자.

from sklearn.kneighbors import KNeighborsClassifier()
kn = KNeighborsClassifier()
kn.fit(train_scaled,train_target)

테스트 세트 또한 훈련 세트와 마찬가지로 변환해야함!!

test_scaled = (test_input-mean) / std
kn.score(test_scaled,test_target)

1.0

 

다시 문제의 그 데이터를 변환시켜 예측시켜보자.

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

1. (도미 = 1)

정답 !

그림으로 그려볼까?

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

5개의 기준 데이터 모두 도미로 성공!

 

2-1 훈련세트와 테스트세트


머신러닝 알고리즘은 크게 지도 학습비지도 학습으로 나뉜다.

 

일반적으로 훈련데이터를 입력 / 정답데이터을 타겟 이라고 한다.

지도학습 :훈련데이터와 정답이 필요 (도미/빙어)비지도 학습 : 타겟 없이 입력데이터만 사용

 

테스트 세트 = 평가에 사용하는 데이터
훈련 세트 = 훈련에 사용하는 데이터

 

1장의 도미,빙어 데이터를 2차원으로 변환

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]

fish_length = bream_length + smelt_length
fish_weight = bream_weight + smelt_weight

fish_data = [[l,w] for l,w in zip(fish_length,fish_weight)]
fish_target = [1] * 35 + [0] * 14

리스트 인덱싱, 슬라이싱을 통해서 훈련세트 / 테스트 세트 만들기

 

처음 35개를 훈련세트, 14개를 테스트 세트로 만들어보자.

train_set = fish_data[:35]
train_target = fish_target[:35]

test_set = fish_data[35:]
tset_target = fish_target[35:]

kn = kn.fit(train_data,train_target)
kn.score(test_data, test_target)
0.0

정확도가 0이 나온 이유는 샘플링 편향 때문이다.

 

위의 데이터는 섞이지 않고 차례대로 35개의 도미, 14개의 빙어 데이터로 이루어져 있으므로,

train_data에는 빙어 데이터가 하나도 들어있지 않기 때문에 좋은 모델이라고 볼 수 없다.

 

골고루 섞기 위해 numpy, random 라이브러리 사용해야한다.

import numpy as np
input_arr = np.array(fish_data)
target_arr = np.array(fish_target)

np.random.seed(42)
index = np.arrange(49)
np.random.shuffle(index)​

위의 코드에서 index를 print하게 되면

[ 13, 23, 9, 31, 19 , 5,,,,,,20 ] 처럼 1~49의 랜덤한 숫자 리스트가 출력된다. 

 

np.random.seed()는 난수를 고정시키는 용도로 이해 (일정한 결과를 얻기 위해 사용)

 

이렇게 순서를 섞은 뒤 다시 실행시키면

train_arr = np.array(fish_data)
train_target = np.array(fish_target)

tarin_set = train_arr[index[:35]]
train_target = train_target[index[:35]]

test_set = train_arr[index[35:]]
test_target = train_target[index[35:]]

준비가 다 되었으니 그래프를 그려봅시다!

import matplotlib.pyplot as plt
plt.scatter(train_set[:,0],train_set[:,1])
plt.scatter(test_set[:,0], test_set[:,1])
plt.xlabel("길이")
plt.ylabel("무게")
plt.show()

blue = 도미                                                              < 잘 섞인 모습이다 ! >

oran = 빙어

 

다시 훈련시켜보자 !

from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(train_set, train_target)     #훈련세트  = fit()
kn.score(test_set, test_target)		#테스트세트 = score()
1.0

< 성공적이다! >

 

print(kn.predict(test_set))  # kn.predict() ==> 새로운 데이터의 정답을 예측하는 메서드

array([0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1,0])

print(test_target)

array([0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1,0])

< 일치한다! >

위 코드는 테스트 세트의 예측 결과와 실제 정답을 확인하는 코드

 

 

 

 

'머신러닝 & 딥러닝 기초 > 2장 - 데이터다루기' 카테고리의 다른 글

2-2 데이터 전처리  (0) 2022.12.30

+ Recent posts