교차 검증을 위해 데이터 세트를 훈련 및 테스트 데이터 세트로 분할 / 분할하는 방법은 무엇입니까?


99

NumPy 배열을 훈련 및 테스트 / 검증 데이터 세트로 무작위로 분할하는 좋은 방법은 무엇입니까? Matlab 의 cvpartition또는 crossvalind함수 와 유사한 것 .

답변:


125

데이터 세트를 두 개로 한 번 분할하려면을 사용 numpy.random.shuffle하거나 numpy.random.permutation인덱스를 추적해야하는 경우 :

import numpy
# x is your dataset
x = numpy.random.rand(100, 5)
numpy.random.shuffle(x)
training, test = x[:80,:], x[80:,:]

또는

import numpy
# x is your dataset
x = numpy.random.rand(100, 5)
indices = numpy.random.permutation(x.shape[0])
training_idx, test_idx = indices[:80], indices[80:]
training, test = x[training_idx,:], x[test_idx,:]

교차 검증을 위해 동일한 데이터 세트반복적으로 분할하는 방법에는 여러 가지가 있습니다 . 한 가지 전략은 반복하여 데이터 세트에서 리샘플링하는 것입니다.

import numpy
# x is your dataset
x = numpy.random.rand(100, 5)
training_idx = numpy.random.randint(x.shape[0], size=80)
test_idx = numpy.random.randint(x.shape[0], size=20)
training, test = x[training_idx,:], x[test_idx,:]

마지막으로 sklearn 에는 여러 교차 검증 방법 (k-fold, leave-n-out, ...)이 포함되어 있습니다. 또한 학습 및 테스트 세트에 동일한 비율의 긍정 및 부정 예제가 있는지 확인하기 위해 일부 기능과 관련하여 균형 잡힌 데이터 분할을 생성하는 고급 "층화 된 샘플링" 방법 도 포함 됩니다.


13
이러한 솔루션에 감사드립니다. 그러나 randint를 사용하는 마지막 방법은 테스트 및 학습 세트 모두에 대해 동일한 인덱스를 제공 할 수있는 좋은 기회가 없습니까?
ggauravr 2013

3
두 번째 솔루션은 유효한 답변이지만 첫 번째와 세 번째 솔루션은 그렇지 않습니다. 첫 번째 솔루션의 경우 데이터 세트를 섞는 것이 항상 옵션은 아니며 데이터 입력 순서를 유지해야하는 경우가 많습니다. 그리고 세 번째는 테스트 및 훈련에 대해 동일한 인덱스를 생성 할 수 있습니다 (@ggauravr이 지적한대로).
pedram bashiri

교차 검증 세트를 위해 리샘플링 해서는 안됩니다 . 전체 아이디어는 이전에 알고있는 CV 세트를 본 적이 없다는 것입니다. 훈련 및 테스트 세트는 데이터를 맞추는 데 사용되므로 물론 CV 세트에 포함하면 좋은 결과를 얻을 수 있습니다. 두 번째 해결책이 필요한 것이기 때문에이 답변을 찬성하고 싶지만이 답변에는 문제가 있습니다.
RubberDuck

55

scikit-learn을 사용하는 또 다른 옵션이 있습니다. 으로 scikit의 위키 설명 , 당신은 다음과 같은 지침을 사용할 수 있습니다 :

from sklearn.model_selection import train_test_split

data, labels = np.arange(10).reshape((5, 2)), range(5)

data_train, data_test, labels_train, labels_test = train_test_split(data, labels, test_size=0.20, random_state=42)

이렇게하면 학습 및 테스트로 분할하려는 데이터의 레이블을 동기화 상태로 유지할 수 있습니다.


1
이것은 기차 세트와 레이블을 모두 사실적으로 처리하기 때문에 매우 실용적인 대답입니다.
chinnychinchin

38

메모입니다. 학습, 테스트 및 유효성 검사 세트를 원하는 경우 다음을 수행 할 수 있습니다.

from sklearn.cross_validation import train_test_split

X = get_my_X()
y = get_my_y()
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
x_test, x_val, y_test, y_val = train_test_split(x_test, y_test, test_size=0.5)

이러한 매개 변수는 훈련에 70 %를 제공하고 테스트 및 값 세트에 각각 15 %를 제공합니다. 도움이 되었기를 바랍니다.


5
코드에 다음 from sklearn.cross_validation import train_test_split을 추가해야합니다. 사용중인 모듈을 명확히하기 위해
Radix

무작위 여야합니까?
liang

즉, X와 y의 주어진 순서에 따라 분할 할 수 있습니까?
liang

1
@ liang 아니 그것은 무작위 일 필요가 없습니다. 훈련, 테스트 및 유효성 검사 세트 크기가 전체 데이터 세트 크기의 a, b 및 c 퍼센트라고 말할 수 있습니다. 의 말을하자 a=0.7, b=0.15, c=0.15,과 d = dataset, N=len(dataset)다음 x_train = dataset[0:int(a*N)], x_test = dataset[int(a*N):int((a+b)*N)]x_val = dataset[int((a+b)*N):].
offwhitelotus

1
지원 중단됨 : stackoverflow.com/a/34844352/4237080 , 사용from sklearn.model_selection import train_test_split
briennakh

14

으로 sklearn.cross_validation모듈이 사용되지 않습니다, 당신은 사용할 수 있습니다 :

import numpy as np
from sklearn.model_selection import train_test_split
X, y = np.arange(10).reshape((5, 2)), range(5)

X_trn, X_tst, y_trn, y_tst = train_test_split(X, y, test_size=0.2, random_state=42)

5

훈련 및 테스트 세트로 계층화 된 분할을 고려할 수도 있습니다. Startified Division은 훈련 및 테스트 세트를 무작위로 생성하지만 원래 클래스 비율이 유지되는 방식으로 생성됩니다. 이렇게하면 학습 및 테스트 세트가 원본 데이터 세트의 속성을 더 잘 반영합니다.

import numpy as np  

def get_train_test_inds(y,train_proportion=0.7):
    '''Generates indices, making random stratified split into training set and testing sets
    with proportions train_proportion and (1-train_proportion) of initial sample.
    y is any iterable indicating classes of each observation in the sample.
    Initial proportions of classes inside training and 
    testing sets are preserved (stratified sampling).
    '''

    y=np.array(y)
    train_inds = np.zeros(len(y),dtype=bool)
    test_inds = np.zeros(len(y),dtype=bool)
    values = np.unique(y)
    for value in values:
        value_inds = np.nonzero(y==value)[0]
        np.random.shuffle(value_inds)
        n = int(train_proportion*len(value_inds))

        train_inds[value_inds[:n]]=True
        test_inds[value_inds[n:]]=True

    return train_inds,test_inds

y = np.array([1,1,2,2,3,3])
train_inds,test_inds = get_train_test_inds(y,train_proportion=0.5)
print y[train_inds]
print y[test_inds]

이 코드는 다음을 출력합니다.

[1 2 3]
[1 2 3]

감사합니다! 이름 지정은 다소 오해의 소지가 value_inds있으며 실제 인덱스이지만 출력은 인덱스가 아니라 마스크 일뿐입니다.
greenoldman

1

이 작업을 수행하기 위해 내 프로젝트에 대한 함수를 작성했습니다 (하지만 numpy를 사용하지 않음).

def partition(seq, chunks):
    """Splits the sequence into equal sized chunks and them as a list"""
    result = []
    for i in range(chunks):
        chunk = []
        for element in seq[i:len(seq):chunks]:
            chunk.append(element)
        result.append(chunk)
    return result

청크를 무작위로 만들려면 목록을 전달하기 전에 섞으십시오.


0

다음은 계층화 된 방식으로 데이터를 n = 5 접기로 분할하는 코드입니다.

% X = data array
% y = Class_label
from sklearn.cross_validation import StratifiedKFold
skf = StratifiedKFold(y, n_folds=5)
for train_index, test_index in skf:
    print("TRAIN:", train_index, "TEST:", test_index)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

0

귀하의 답변에 감사드립니다. (1) 샘플링하는 동안 교체 (2) 훈련과 테스트 모두에서 중복 된 인스턴스가 발생하지 않도록 수정했습니다.

training_idx = np.random.choice(X.shape[0], int(np.round(X.shape[0] * 0.8)),replace=False)
training_idx = np.random.permutation(np.arange(X.shape[0]))[:np.round(X.shape[0] * 0.8)]
    test_idx = np.setdiff1d( np.arange(0,X.shape[0]), training_idx)

0

약간의 읽기를하고 훈련과 테스트를 위해 데이터를 분할하는 (많은 ..) 다른 방법을 고려한 후, 시간을 맞추기로 결정했습니다!

나는 4 가지 다른 방법을 사용했다 (그 중 어떤 것도 sklearn 라이브러리를 사용하지 않고 있으며, 이것이 잘 설계되고 테스트 된 코드임을 제공하는 최상의 결과를 제공 할 것이라고 확신한다) :

  1. 전체 행렬 arr을 섞은 다음 데이터를 분할하여 훈련하고 테스트합니다.
  2. 인덱스를 섞은 다음 x와 y를 할당하여 데이터를 분할합니다.
  3. 방법 2와 동일하지만 더 효율적인 방법으로
  4. 팬더 데이터 프레임을 사용하여 분할

방법 3은 그 방법 1과 방법 2, 4가 정말 비효율적이라는 것을 발견 한 후 가장 짧은 시간에 승리했습니다.

시간을 설정 한 4 가지 방법에 대한 코드 :

import numpy as np
arr = np.random.rand(100, 3)
X = arr[:,:2]
Y = arr[:,2]
spl = 0.7
N = len(arr)
sample = int(spl*N)

#%% Method 1:  shuffle the whole matrix arr and then split
np.random.shuffle(arr)
x_train, x_test, y_train, y_test = X[:sample,:], X[sample:, :], Y[:sample, ], Y[sample:,]

#%% Method 2: shuffle the indecies and then shuffle and apply to X and Y
train_idx = np.random.choice(N, sample)
Xtrain = X[train_idx]
Ytrain = Y[train_idx]

test_idx = [idx for idx in range(N) if idx not in train_idx]
Xtest = X[test_idx]
Ytest = Y[test_idx]

#%% Method 3: shuffle indicies without a for loop
idx = np.random.permutation(arr.shape[0])  # can also use random.shuffle
train_idx, test_idx = idx[:sample], idx[sample:]
x_train, x_test, y_train, y_test = X[train_idx,:], X[test_idx,:], Y[train_idx,], Y[test_idx,]

#%% Method 4: using pandas dataframe to split
import pandas as pd
df = pd.read_csv(file_path, header=None) # Some csv file (I used some file with 3 columns)

train = df.sample(frac=0.7, random_state=200)
test = df.drop(train.index)

그리고 시간 동안, 1000 개의 루프를 3 번 ​​반복 실행하는 데 필요한 최소 시간은 다음과 같습니다.

  • 방법 1 : 0.35883826200006297 초
  • 방법 2 : 1.7157016959999964 초
  • 방법 3 : 1.7876616719995582 초
  • 방법 4 : 0.07562861499991413 초

도움이 되었기를 바랍니다.


0

아마도 학습과 테스트로 나눠야 할뿐만 아니라 모델이 일반화되는지 확인하기 위해 교차 검증도해야 할 것입니다. 여기서는 훈련 데이터 70 %, 검증 20 %, 홀드 아웃 / 테스트 데이터 10 %를 가정합니다.

np.split을 확인하십시오 .

indices_or_sections가 정렬 된 정수의 1 차원 배열 인 경우 항목은 배열이 축을 따라 분할되는 위치를 나타냅니다. 예를 들어 [2, 3]은 축 = 0 인 경우

아리 [: 2] 아리 [2 : 3] 아리 [3 :]

t, v, h = np.split(df.sample(frac=1, random_state=1), [int(0.7*len(df)), int(0.9*len(df))]) 

0

기차 테스트로 분할하고 유효한

x =np.expand_dims(np.arange(100), -1)


print(x)

indices = np.random.permutation(x.shape[0])

training_idx, test_idx, val_idx = indices[:int(x.shape[0]*.9)], indices[int(x.shape[0]*.9):int(x.shape[0]*.95)],  indices[int(x.shape[0]*.9):int(x.shape[0]*.95)]


training, test, val = x[training_idx,:], x[test_idx,:], x[val_idx,:]

print(training, test, val)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.