티스토리 뷰

이미 잘 구현되어 있는 소스코드와 데이터를 사용한 머신러닝의 경우에는 모델 내에 shuffle 자체가 구축되어 있는 반면에 데이터 수집과 정제, 모델 구축까지 밑바닥에서부터 쌓아 올리다보면 여러가지 난관에 봉착하게 된다. python 을 친숙하게 다루는 사람이라면 데이터를 다루는데 어려움이 없겠으나 수학적 지식이나 모델링쪽만 전문으로 했던 사람에게는 shuffle 자체도 쉬운게 아닐 것이다. random.shuffle 예제를 살펴보면 대부분 1차원 array 를 섞는것 뿐이라 우리의 (x, y) 데이터 쌍에서는 일반적인 방식으로는 사용할 수 없다. 여기서는 이런 상황에서 데이터셋을 shuffle 하는 방법 하나를 제시한다.

예를들어 손글씨 인식을 할 때 사용하는 대표적인 MNIST 의 데이터를 우리가 직접 수집한다고 생각해보자 ( 요즘은 프레임워크가 너무 잘 되어 있어서 x_train, y_train, x_test, y_test 모조리 다 뽑아주고 분리까지해 준다 ). 여러가지 경로로 이미지를 수집했고 다행스럽게 아래와 같은 형식으로 훈련데이터와 라벨을 array 에 잘 적재 했다고 치자.

>>> x_train = [1,2,3,4,5]
>>> y_train = [6,7,8,9,0]

실제로 사용하는 데이터의 구조는 더욱 복잡해질 수 있을 것이지만 여기서는 x_train 을 이미지 데이터, y_train 을 이미지에 해당하는 라벨 데이터로 생각하면 되겠다. 이제 데이터를 잘 수집 했으니 학습을 시켜야되는데 기본적으로 모델을 평가할 때 사용하는 데이터는 train 데이터와 분리하는 것이 좋다고 많은 논문과 글에서 소개되고 있기 때문에 나누도록 하자. 가만, 어떤 기준으로 나눠야하지? 애초에 잘 섞여있는 데이터였다면 상관없지만 그렇지 않은 경우에 8:2의 비율로 배열을 인덱스로 잘라버리면 train 데이터에는 손글씨 0~7까지, 라벨 데이터에는 8~9가 담겨버리게 된다. 이런 참사를 막으려면 훈련 데이터와 평가 데이터를 나누기 전에 데이터를 잘 섞어줘야 한다. 파이썬은 마침 random.shuffle 처럼 괜찮은 라이브러리를 지원하기 때문에 적극적으로 사용해주면 되겠다.

>>> random.shuffle(x_train)
>>> random.shuffle(y_train)

단순하게 이렇게 진행해도 될까? 안된다. x_trainy_train 는 훈련데이터와 라벨 관계로 인덱스가 묶여있다. 즉, x_train[0] 의 정답은 y_train[0] 이고 x_train[1] y_train[1] 과 관련이 있다. 이 인덱스 관계를 무시하고 막연하게 섞어버리면 훈련데이터와 라벨의 관계가 무너지게 된다. 이 글에서는 두 개의 관계를 유지하면서 섞을 수 있는 방법을 제시한다.

개념은 사실 굉장히 간단하다. x_trainy_train 을 배열로 묶어주고 그걸 shuffle 해준다. 그리고 그 결과를 다시 x_train, y_train 으로 나누면 끝. 코드는 다음과 같다.

>>> tmp = [[x,y] for x, y in zip(x_train, y_train)]
>>> tmp
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 0]]

잘 묶인 것을 확인하고, shuffle 시작.

>>> import random
>>> random.shuffle(tmp)
>>> tmp
[[3, 8], [5, 0], [2, 7], [1, 6], [4, 9]]
인덱스 관계가 유지되면서 잘 섞인 것을 확인했으니 다시 x_train, y_train 으로 나눠준다.
>>> x_train = [n[0] for n in tmp]
>>> y_train = [n[1] for n in tmp]
그리고 확인해보자.
>>> x_train
[3, 5, 2, 1, 4]
>>> y_train
[8, 0, 7, 6, 9]

잘 나누어진 것이 확인된다. 사실 이렇게 2차원 이상의 배열에서 인덱스 관계를 유지하면서 shuffle 하는 방법은 다양하게 제시되고 있지만 Beautiful is better than ugly 라는 ZEN 의 첫 항목을 떠올려보면 이건 꽤 괜찮은 방법이라고 생각된다. 누군가에게는 도움이 되었기를 바란다.


'개발 > python' 카테고리의 다른 글

[python] 사용자 데이터셋 셔플  (0) 2019.03.20
[python] The Zen of Python  (0) 2019.03.14
아나콘다 가상환경  (0) 2019.01.25
[3.6.2] numpy 맛보기  (0) 2017.10.02
가상환경(virtualenv)과 jupyter  (0) 2017.09.06
기상청 날씨 API 와 슬랙 연동  (0) 2017.06.14
댓글
댓글쓰기 폼