관리 메뉴

클라이언트/ 서버/ 엔지니어 " 게임 개발자"를 향한 매일의 공부일지

데이터 다루기 6 - 데이터 전처리 심화 학습 본문

인공지능/머신러닝

데이터 다루기 6 - 데이터 전처리 심화 학습

huenuri 2024. 10. 1. 21:36

2장의 두번째 단원 실습을 한번 더 진행해보려고 한다. 지난번에 실습할 때는 시간에 쫓겨 실습일지를 쓸 때는 설명을 거의 쓰지 않았다. 이번에는 이해할 수 있는 만큼 충분히 기록하고 있다.


 

 

 

데이터 전처리 실습해보기

 

 

튜플은 리스트와 매우 비슷하다. 리스트처럼 원소에 순서가 있지만 한 번 만들어진 튜플은 수정할 수 없다. 튜플을 사용하면 함수로 전달한 값이 바뀌지 않는다는 것을 믿을 수 있기 때문에 매개변수 값으로 많이 사용한다.


 

 

 

 

넘파이 배열로 출력하면 리스트처럼 한 줄로 길게 출력되지 않고 행과 열을 맞추어 가지런히 정리된다. 2개의 열에 길이와 무게가 잘 들어있음을 확인할 수 있다.

이제 동일한 방법으로 타깃 데이터도 만들어본다. np.one()와 np.zeros() 함수를 사용하여 각각 원하는 개수의 1과 0을 채운 배열을 만든다.

 

 

데이터가 잘 전달되었다. 이제 훈련 세트와 테스트 세트로 나누어볼 것이다.


 

 

 

 

훈련 세트와 테스트 세트를 나누는 방법으로 train_test_split() 함수를 사용한다. 나누고 싶은 리스트나 배열을 원하는 만큼 전달하면 된다. 앞에서 훈련 세트와 테스트 세트 데이터를 무작위로 섞기 전에 np.random.seed() 함수를 사용해 출력 결과와 원본 내용이 같아지도록 만들었다.

train_test_split() 함수에는 자체적으로 랜덤 시드를 지정할 수 있는 random_state 매개변수가 있다. fish_data와 fish_target 2개 배열을 전달했으므로 2개씩 나뉘어 총 4개의 배열이 반환된다. input에는 입력 데이터를 target에는 타깃 데이터를 넣었다.

 

 

지난번에 공부할 때는 train_input, test_input이 무슨 말인지 몰랐는데 이번에 알게 되었다. 그리고 잘못 쓴 코드도 발견했는데 전에는 입력 데이터의 테스트만 2번 출력했었다.

13개의 테스트 세트 중에 10개가 도미이고 3개가 빙어이다. 잘 섞인 것 같지만 빙어의 비율이 조금 모자란다. 원래 도미와 빙어의 개수는 35개와 14개로 두 생선의 비율은 2.5:1이다. 하지만 이 테스트 세트의 도미와 빙어 비율은 3.3:1이다. 

 

이처럼 무작위로 데이터를 나누었을 때 샘플이 골고루 섞이지 않을 수 있다. 이 문제를 해결할 수 있는 방법은 다음과 같다. train_test_split() 함수에서 stratify 매개변수에 타깃 데이터를 전달하면 클래스 비율에 맞게 데이터를 나눈다. 훈련 데이터가 작거나 특정 클래스의 샘플 개수가 적을 때 특히 유용하다.

 

이제 테스트 세트 비율이 2.25:1이 되었다. 


 

 

 

 

앞서 준비한 데이터로 k-최근접 이웃을 훈련했다. 그리고 평가를 진행했는데 수상한 도미가 빙어로 예측한 것이다. 이 샘플을 다른 데이터와 함께 산점도로 그려보겠다.


 

 

 

 

이 샘플은 분면 오른쪽 위로 뻗어있는 다른 도미 데이터에 가깝다. 하지만 왜 왼쪽 아래에 깔린 빙어 데이터에 더 가깝다고 판단한 것일까? 최근접 이웃으로 어느 쪽에 더 가까이 있는지 판단해보자.


 

 

 

 

 

 

 

가까운 이웃을 보니 빙어가 압도적으로 많았다. 산저도를 보면 직관적으로 도미와 가까워 보이는데 말이다. 거리를 확인해보면 이상한 점을 눈치챌 수 있다.


 

 

 

 

 

x축의 범위를 y축과 동일하게 설정한 결과, 모든 데이터가 수직으로 늘어선 형태가 되었다. 이런 데이터라면 생선의 길이(x축)는 가장 가까운 이웃을 찾는데 크게 영향을 미치지 못할 것이다. 오로지 생선의 무게(y축)만 고려 대상이 된다.

두 특성의 값이 놓인 범위가 매우 다른데 이를 스캐일이 다르다고 한다. 데이터를 표현하는 기준이 다르면 알고리즘이 올바르게 예측할 수 없다. 제대로 사용하려면 특성값을 일정한 기준으로 맞춰 주어야 한다.


 

 

 

평균과 표준편차를 구해서 표준점수로 변환해주었다. 표준점수는 각 특성값이 평균에서 표준편차의 몇 배만큼 떨어져 있는지를 나타낸다. 이를 통해 실제 특성값의 크기와 상관없이 동일한 조건으로 비교할 수 있다. 특성마다 스케일이 다르므로 평균과 표준편차는 각 특성별로 계산해야 한다. 이를 뒤해 axis=0으로 지정했다.


 

 

 

 

훈련 세트를 mean(평균)으로 빼고 std(표준편차)로 나누어 주었기 때문에 값의 범위가 크게 달라졌다. 샘플을 동일한 비율로 변환하지 않으면 이런 현상이 발생한다. 이제 훈련 세트의 mean, std를 이용해서 변환해야 한다.


 

 

 

앞선 그래프와 같지만 크게 달라진 점은 x축과 y축의 범위가 -1.5~1.5 사이로 바뀐 것이다. 이제 이 데이터셋으로 k-최근즙 이웃 모델을 다시 훈련해본다.

 

 

이제 도미로 잘 예측이 된 것을 볼 수 있다. 마지막으로 완성된 그래프를 그려보기로 하자.


 

 

 

 

데이터 전처리를 할 때 주의할 점은 훈련 세트를 변환한 방식 그대로 테스트 세트를 변환해야 한다는 것이다. 그렇지 않으면 특성값이 엉뚱하게 변환될 것이고 훈련세트로 훈련한 모델이 제대로 동작하지 않는다.

 


 

 

 

학습을 마치고

이 실습도 제대로 공부하면서 해보니 그동안 잘 몰랐던 것 놓친 것들이 꽤 많았다. 그냥 코드가 이렇게 되는구나 확인만 하고 실행하고 넘어가서는 아무것도 배울 수 없다.

이제 다음 포스트에서 회귀 모델에 대해서도 공부해볼 것이다.