Post

[머신러닝] 2-2. 데이터 전처리

[머신러닝] 2-2. 데이터 전처리

올바른 결과 도출을 위해서 데이터를 사용하기 전에 데이터 전처리 과정을 거친다. 전처리 과정을 거친 데이터로 훈련했을 때의 차이를 알고 표준점수로 특성의 스케일을 변환하는 방법 알기

넘파이로 데이터 준비하기

넘파이의 column_stack() 함수로 전달받은 리스트를 일렬로 세운 다음 차례대로 나란히 연결한다. 연결할 리스트는 파이썬 튜플로 전달한다

튜플
리스트처럼 원소에 순서가 있지만 튜플은 수정할 수 없다. 함수로 전달한 값이 바뀌지 않기 때문에 매개변수 값으로 많이 사용한다

저번에는 타깃 데이터를 만들 때 원소가 하나인 리스트 [1], [0]을 여러 번 곱해서 만들었다. 넘파이를 사용하면 더 쉽게 만들 수 있다. np.ones() 와 np.zeros() 함수를 사용한다. 이 두 함수는 각각 원하는 개수의 1과 0을 채운 배열을 만들어 준다.

1
2
print(np.ones(5)) 
#[1. 1. 1. 1. 1.]

두 함수를 이용해 1이 35개인 배열 과 0이 14개인 배열을 간단히 만들 수 있다. 두 배열을 다음에 연결하면 된다. 여기에서는 np.column_stack() 함수를 사용하지 않고 np.concatenate()함수를 사용한다.

alt concatenate

연결할 리스트나 배열을 튜플로 전달한다

1
fish_target=np.concatenate((np.ones(35),np.zeros(14)))

데이터가 클수록 수동으로 만드는 파이썬 리스트는 비효율적이므로 넘파이 배열을 사용하는 것이 좋다

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

저번에 넘파이 배열의 인덱스를 직접 섞어서 훈련 세트와 테스트 세트로 나누었다. 좀 더 쉬운 방법이 있다.

사이킷런의 train_test_split() 함수이다. 이는 전달되는 리스트나 배열을 섞고 비율에 맞게 훈련 세트와 테스트 세트로 나눠준다.

나누고 싶은 리스트나 배열을 원하는 만큼 전달하면 된다.

1
2
3
train_input, test_input, train_target, test_target=train_test_split(
    fish_data, fish_target, random_state=42
)

alt split

기본적으로 25%를 테스트 세트로 떼어 낸다. 잘 나누었는지 넘파이 배열의 shape 속성으로 입력 데이터의 크기를 출력해볼 수 있다

무작위로 데이터를 나누기 때문에 샘플이 골고루 섞이지 않을 수 있다. 일부 클래스의 개수가 적을 때 이렇게 될 수 있다. 훈련 세트와 테스트 세트에 샘플 클래스의 비율이 일정하지 않다면 모델이 일부 샘플을 올바르게 학습하기 어렵다.

하지만 또 해결 방법이 있다

startify 매개변수에 타깃 데이터를 전달하면 클래스 비율에 맞게 데이터를 나눠준다. 훈련 데이터가 작거나 특정 클래스의 샘플 개수가 적을 때 유용하다

1
2
3
train_input, test_input, train_target, test_target=train_test_split(
    fish_data, fish_target, stratify=fish_target, random_state=42
)

수상한 도미 한 마리

alt 수상

이 세모는 무엇일까? 우리는 위에 있는 것들과 비슷하다고 예측할 것이다. 하지만 모델은 왼쪽 아래에 깔린 빙어 데이터에 가깝다고 판단한다.

k-최근접 이웃은 주변 샘플을 바탕으로 예측한다고 했다 여기서 문제가 생기는 것이다. 가까운 이웃이 하나만 도미이고 3개가 빙어이기 때문에 빙어로 예측하는 것이다.

왜 빙어가 가깝다고 생각했을까?

기준을 맞춰라

alt 거리

92의 거리보다 몇 배는 되는 것 같은데 거리가 130 이다. 왜일까? 왜냐면 x축은 범위가 좁고 y축은 볌위가 넓기 때문이다. y축으로 조금만 멀어져도 거리가 큰 값으로 계산 되기 때문에 위에 도미가 이웃으로 선택되지 못했던 것이다

xlim()함수와 ylim()함수로 범위를 동일하게 할 수 있다.

두 특성(길이와 무게)의 값이 놓인 범위가 다른다. 이를 두 특성의 스케일이 다르다고 한다. 데이터 표현 기준이 다르면 알고리즘이 올바르게 예측할 수 없다. 이를 위해 특성값을 일정한 기준으로 맞추는 데이터 전처리를 한다

가장 널리 사용되는 전처리 방법은 표준점수이다. 이는 각 특성값이 0에서 표준편차의 몇 배만큼 떨어져 있는지를 나타낸다. 이를 통해 실제 특성값의 크기와 상관없이 동일한 조건으로 비교할 수 있다

표준 점수: 각 데이터가 원점에서 몇 표준편차만큼 떨어져 있는지를 나타낸다
분산=(데이터-평균)^2/데이터수
표준편차=&radic 분산

np.mean():평균
np.std(): 함수의 표준편차

axis=0: 행을 따라 열의 통계값을 계산

alt 통계

브로드캐스팅: train_input의 모든 행에서 mean에 있는 두 평균값을 빼준다. 그 다음 std에 있는 두 표준편차를 다시 모든 행에 적용한다.

alt bro

전처리 데이터로 모델 훈련하기

훈련 세트를 평균으로 빼고 표준편차로 나누었기 때문에 값의 범위가 달라졌다. 따라서 샘플도 훈련세트의 mean, std를 이용하여 변환해야 한다.

훈련 후 테스트 세트를 평가할 때는 테스트 세트의 기준으로 훈련 세트를 변환해야 같은 스케일로 산점도를 그릴 수 있다.

샘플을 훈련 세트의 평균과 표준편차로 변환해야 같은 비율로 산점도를 그릴 수 있다. 또한 테스트 세트도 훈련 세트의 평균과 표준편차로 변환해야 한다.

alt tada

Ta-da!

수상한 샘플을 도미로 예측하게 되었다!

마무리

핵심 포인트

데이터 전처리는 머신러닝 모델에 훈련 데이터를 주입하기 전에 가공하는 것이다.

표준점수는 훈련 세트의 스케일을 바꾸는 대표적인 방법이다. 표준점수=(데이터-특성의 평균)/표준편차 훈련세트의 평균과 표준편차로 데스트 세트도 바꿔야 한다!

브로드캐스팅 크기가 다른 넘파이 배열에서 자동으로 사칙연산을 모든 행이나 열로 확장하여 수행하는 기능이다.

핵심 패키지와 함수

scikit-learn

train_test_split()은 훈련 데이터를 훈련 세트와 테스트 세트로 나누는 함수이다. 여러 개의 배열을 전달할 수 있다. test_size 매개변수에서 테스트 세트로 나눌 비율을 지정할 수 있다. 기본값은 25%이다.
shuffle 매개변수로 훈련 세트와 테스트 세트로 나누기 전에 무작위로 섞을지 여부를 결정할 수 있다. 기본 값은 true이다. stratify 매개변수에 클래스 레이블이 담긴 배열(일반적으로 타깃 데이터)을 전달하면 클래스 비율에 맞게 훈련 세트와 테스트 세트를 나눈다

kneighbors() k- 최근접 이웃 객체의 메서드 이다. 입력한 데이터에 가장 가까운 이웃을 찾아 거리와 이웃 샘플의 인덱스를 반환한다. 기본적으로 이웃의 개수는 KNeighborsClassifier 클래스의 객체를 생성할 때 지정한 개수를 사용한다. n_neighbors 매개변수에서 다르게 지정할 수도 있다
return_distance 매개변수를 false로 지정하면 이웃 샘플의 인덱스만 반환하고 거리는 반환하지 않는다.


참고: 혼자 공부하는 머신러닝+딥러닝

This post is licensed under CC BY 4.0 by the author.