scikit-learn에서 계층화 된 기차 / 테스트 분할


88

데이터를 훈련 세트 (75 %)와 테스트 세트 (25 %)로 분할해야합니다. 현재 아래 코드를 사용하여 수행합니다.

X, Xt, userInfo, userInfo_train = sklearn.cross_validation.train_test_split(X, userInfo)   

그러나 훈련 데이터 세트를 계층화하고 싶습니다. 어떻게하나요? 나는 StratifiedKFold방법을 조사해 왔지만 75 % / 25 % 분할을 지정하지 않고 훈련 데이터 세트 만 계층화하도록합니다.

답변:


153

[0.17 업데이트]

문서 참조 sklearn.model_selection.train_test_split:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    stratify=y, 
                                                    test_size=0.25)

[/0.17 업데이트]

여기에 pull 요청이 있습니다 . 그러나 train, test = next(iter(StratifiedKFold(...))) 원하는 경우 기차 및 테스트 인덱스를 간단히 수행 하고 사용할 수 있습니다 .


1
@AndreasMueller 회귀 데이터를 계층화하는 쉬운 방법이 있습니까?
요르단

3
@Jordan 아무것도 scikit-learn에서 구현되지 않습니다. 나는 표준적인 방법을 모른다. 백분위 수를 사용할 수 있습니다.
Andreas Mueller

@AndreasMueller이 방법이 StratifiedShuffleSplit보다 상당히 느린 동작을 본 적이 있습니까? MNIST 데이터 세트를 사용하고있었습니다.
snymkpr

train_test_split (... stratify =)는 StratifiedShuffleSplit을 호출하고 첫 번째 분할을 수행하므로 매우 이상해 보이는 @activatedgeek입니다. 재현 가능한 예제를 사용하여 추적기에서 문제를 자유롭게여십시오.
안드레아스 뮬러

@AndreasMueller 나는 내가 뭔가 잘못하고 있다는 강한 느낌을 가지고 있기 때문에 실제로 문제를 열지 않았습니다 (단지 2 줄이지 만). 하지만 오늘도 여러 번 재현 할 수 있다면 그렇게하겠습니다!
snymkpr

29

TL; DR : StratifiedShuffleSplit 사용test_size=0.25

Scikit-learn은 계층화 분할을위한 두 가지 모듈을 제공합니다.

  1. StratifiedKFold :이 모듈은 직접 k- 폴드 교차 검증 연산자로 유용 n_folds합니다. 클래스가 양쪽에서 균등하게 균형을 이루도록 훈련 / 테스트 세트를 설정합니다.

여기에 몇 가지 코드가 있습니다 (위 문서에서 직접)

>>> skf = cross_validation.StratifiedKFold(y, n_folds=2) #2-fold cross validation
>>> len(skf)
2
>>> 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]
...    #fit and predict with X_train/test. Use accuracy metrics to check validation performance
  1. StratifiedShuffleSplit :이 모듈은 균등하게 균형 잡힌 (계층화 된) 클래스를 갖는 단일 훈련 / 테스트 세트를 생성합니다. 기본적으로 이것은 n_iter=1. 여기에서 테스트 크기를 언급 할 수 있습니다.train_test_split

암호:

>>> sss = StratifiedShuffleSplit(y, n_iter=1, test_size=0.5, random_state=0)
>>> len(sss)
1
>>> for train_index, test_index in sss:
...    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]
>>> # fit and predict with your classifier using the above X/y train/test

5
주의 같은 것으로 0.18.x, n_iter해야 n_splits을 위해 StratifiedShuffleSplit - 그리고 그것은 그것에 대한 약간 다른 API있다 : scikit-learn.org/stable/modules/generated/...
lollercoaster

2
경우 y팬더 시리즈, 사용y.iloc[train_index], y.iloc[test_index]
Owlright

1
@Owlright 나는 팬더 데이터 프레임을 사용해 보았고 StratifiedShuffleSplit이 반환하는 인덱스는 데이터 프레임의 인덱스가 아닙니다. dataframe index: 2,3,5 the first split in sss:[(array([2, 1]), array([0]))]:(
Meghna Natraj

2
@tangy 왜 이것이 for 루프입니까? 그것은 줄 때하는 경우가 아니라 X_train, X_test = X[train_index], X[test_index]호출은 무시 X_train하고 X_test? 그렇다면 왜 단 하나가 next(sss)아닌가?
Bartek Wójcik

13

다음은 연속 / 회귀 데이터에 대한 예입니다 ( GitHub에서이 문제 가 해결 될 때까지 ).

min = np.amin(y)
max = np.amax(y)

# 5 bins may be too few for larger datasets.
bins     = np.linspace(start=min, stop=max, num=5)
y_binned = np.digitize(y, bins, right=True)

X_train, X_test, y_train, y_test = train_test_split(
    X, 
    y, 
    stratify=y_binned
)
  • 연속 목표의 start최소값과 stop최대 값은 어디에 있습니까 ?
  • 설정하지 않으면 right=True최대 값을 별도의 빈으로 만들고 해당 추가 빈에 너무 적은 샘플이 있기 때문에 분할이 항상 실패합니다.


6

@Andreas Mueller가 수락 한 답변 외에도 위에서 언급 한 @tangy로 추가하고 싶습니다.

StratifiedShuffleSplit 은 다음 기능이 추가 된 train_test_split ( stratify = y)와 가장 유사합니다 .

  1. 기본적으로 계층화
  2. n_splits 를 지정 하여 데이터를 반복적으로 분할합니다.

0
#train_size is 1 - tst_size - vld_size
tst_size=0.15
vld_size=0.15

X_train_test, X_valid, y_train_test, y_valid = train_test_split(df.drop(y, axis=1), df.y, test_size = vld_size, random_state=13903) 

X_train_test_V=pd.DataFrame(X_train_test)
X_valid=pd.DataFrame(X_valid)

X_train, X_test, y_train, y_test = train_test_split(X_train_test, y_train_test, test_size=tst_size, random_state=13903)

0

위에서 @tangy 답변을 scikit-learn의 현재 버전으로 업데이트 : 0.23.2 ( StratifiedShuffleSplit 문서 ).

from sklearn.model_selection import StratifiedShuffleSplit

n_splits = 1  # We only want a single split in this case
sss = StratifiedShuffleSplit(n_splits=n_splits, test_size=0.25, random_state=0)

for train_index, test_index in sss.split(X, y):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.