train_test_split
사용하기.¶
ML에서 Test set은 training이 끝난 모델의 generalization error가 어느정도인지를 가늠하기 위해 반드시 필요함.
- overfitting이 쉽게 되는 high capacity를 가진 model일수록 test-set에 의한 검증결과가 반드시 필요.
- overfitting이 되기 쉬운 model은 training dataset에서는 매우 높은 performance를 보임.
- population의 특징을 잘 나타내는 training dataset과 test dataset이 필요함.
- imbalanced class등의 dataset에서는 stratified sampling 등을 수행해야함.
Scikit-Learn 라이브러리의 model_selection
모듈에서 train_test_split
함수를 제공함으로서 training dataset과 test dataset을 쉽게 나눌 수 있도록 도와줌.
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(
X_data,
y_data,
test_size = 0.25, # the ratio of test dataset
train_size = 0.75, # the ratio of training dataset
shuffle = True, # 데이터를 분리하기 전에 섞을지(shuffle)를 결정
random_state = 23, # int. the seed value of the pseudo random shuffling.
stratify = y_data, # array-like. 각 stratum 의 비율이 일정하도록
# test와 train을 나누는데, strata를 나누기 위한 기준이 되는 array.
)
다음 코드는 iris dataset을 7:3으로 training dataset과 test dataset으로 나누고, training dataset으로 Decision Tree Classifier로 훈련을 하고, test dataset으로 훈련된 model의 generalization performance를 accuracy로 살펴본다.
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
full_data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(full_data.data.values,
full_data.target.values,
test_size=0.3,
shuffle=True,
random_state = 23
)
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
pred = clf.predict(X_test)
print(f'The accuracy of classifier : {accuracy_score(y_test, pred)}')
- Decision Tree를 사용하기 때문에 쉽게 overfitting됨.
- predict 의 경우 성능이 train에 비해 매우 떨어짐.
Stratified Sampling¶
training dataset이나 test dataset은 모두 population 의 특징을 잘 반영하고 있어야 한다.
- 전체 집합을 population이라고 부름.
- 원래는 모든 sample을 가진 population으로 훈련을 해야하지만 (전수조사 등을 생각해보라)
- 그것은 불가능하므로 해당 특성을 충분히 반영한 representative subset을 뽑아서 훈련 및 검증을 하게 됨
iris dataset에서 population을 sklearn에서 제공하는 150개라고 가정을 하자 (가용한 sample의 전체집합 = population).
살펴보면 이들은 크게 3가지 종류의 target을 가지고 있고, 각 target에 속한 sample수가 50개로 모두 같다.
population을 나누는 같은 성질의 subgroup들을 strata
라고 부르는데, 각각의 stratum
이 전체 갯수에 대해 차지하고 있는 비율은 population, training dataset, test dataset 모두에서 일정 해야 한다.
- 일반적으로 데이터의 수가 매우 많고, 실제 각 stratum의 수가 같은 경우에는 random sampling을 해도 각 stratum의 수가 비슷하게 유지된다.
- 하지만, 특정 stratum의 수가 매우 적은 imbalanced data인 경우나, sample의 수가 매우 적은 경우에는 random sampling으로는 이들 비율을 일정하게 유지하지 못한다.
- 운이 나쁘면, test set에 특정 stratum이 전혀 없는 경우 가 발생할 수도 있다.
이를 방지하기 위해서 각각의 stratum의 비율이 유지되도록 training dataset과 test dataset을 나누는 방법을 sklearn.model_selection
모듈의 train_test_split
에서 제공하며, 이를 가르켜 stratified sampling 이라고 부른다.
iris dataset에서 각 target (붓꽃의 종류)을 stratum이라고 보고, 이들의 비율이 원래 full dataset과 같게 training dataset과 test dataset이 나누어지게 하려면, train_test_split
함수의 stratified
파라메터에 target
의 정보를 가진 array를 argument로 넘겨주면 된다.
X_train, X_test, y_train, y_test = train_test_split(
full_data.data,
full_data.target,
test_size = 0.3,
stratify=full_data.target,
shuffle=True,
random_state=23
)
전체 150개 sample의 30%는 45개이므로, test dataset은 45개의 sample로 구성되며, 3종류 target에 각각 속하는 샘플들 15개씩으로 test dataset이 구성된다.
주의할 점은 지나치게 많은 strata로 나뉘게 될 경우, 특정 stratum에 속한 sample의 갯수가 지나치게 작아지게 될 수 있기 때문에 피해야 한다. 즉, 각 stratum에 적절한 수의 샘플이 놓이도록 처리해야 한다.
주의사항¶
- test dataset이나 training dataset이나 모두 population의 representative subset이어야 한다.
- ML의 특징상 어느 정도 이상의 training dataset이 없으면 제대로 훈련이 되지 않으므로 training dataset이 훈련에 지장이 없을 정도의 sample 수를 갖추어야 한다.
- 하지만, test의 결과인 generalization error의 신뢰도를 확보하기 위해서는 test dataset도 지나치게 적은 수가 되서는 안된다.
- imbalanced dataset에서는 가급적 stratified sampling을 수행해서 test dataset과 training dataset을 나누어야 한다.
- 지나치게 많은 수의 strata를 가지도록 해선 안된다.
Test dataset은 나누고 난 이후에는 마지막으로 generalization performance를 측정하는 경우 외에는 접근할 필요가 없다. 우선 이렇게 나누고 난 이후, training dataset에 대해 Exploratory Data Analysis (EDA)를 수행하는게 일반적이다.
Stratified sampling은 classification에서 기본으로 사용되어야 함(cross validation의 경우도 마찬가지). 하지만, regression의 경우에는 그 중요도가 떨어진다. (반드시 사용해야할 필요는 없다) 연속된 변수 자체를 맞추어야 하기 때문에 label값에 대한 분포가 training에 미치는 영향이 classification보다는 떨어지기 때문이다.
- Exploratory Data Analysis (EDA)
- 적절한 모델 등을 선택하기 위해서 data에 대한 이해가 필요하기 때문에 data를 살펴보는 과정임.
model training 등의 과정 전에 data에 대한 insight를 얻기 위해 수행되는 과정.
split
객체 사용하기.¶
train_test_split
함수와 달리, split
객체들로 처리하는 방법은 다음에 소개하는 cross validation과 연계가 가능함.
sklearn.model_selection.StratifiedKFold
n_splits
에 할당하는 argument로 CV에서 사용할 number of folds를 결정한다. 만약 1을 사용하면,train_test_split
함수와 같은 역할을 수행하게 된다(물론 이후split
를 호출). k-Fold기법을 구현한 것으로 test dataset으로 지정된 index들이 겹쳐지지 않는다.sklearn.model_selection.StratifiedShuffleSplit
n_splits
에 할당하는 argument에 따라 CV에서 이루어질 evaluation이 몇 번 이루어질지를 결정한다. k-Fold와 달리 램덤하게 test dataset이 결정되며 test에 선택된 index들이 겹칠 수 있다. k-Fold에서는 subset이 나누어지는 구조이기때문에 test dataset이 겹칠 수가 없다(모든 샘플은 test dataset이 될 수 있는 것은 오직 하나의 fold로만 한정됨).