Cross-Validation

Rainy Night for Sapientia·2023년 5월 13일
0

Cross-Validation

Cross-Validation(이하 CV)는 트레이닝셋을 여러 개의 폴드로 분할하여 트레이닝 하는 것이며 CV를 하는 이유 모델의 트레이닝 셋에 대한 Overfitting을 막기 위함이다.

1. Ways of Cross-Validation

데이터의 형태에 따라 cv를 처리하는 방법이 조금씩 다르다.

  • K-fold cross-validation
  • Stratified k-fold cross-validation
  • Hold-out based validation
  • Leave-one-out cross-validation
  • Group k-fold cross-validation

2. K-fold cross-validation

가장 대표적인 cv방법으로 k-fold가 있는데 트레이닝 셋을 여러개(k)개의 블럭으로 분할한 뒤 k-1개를 트레이닝셋으로, 1개를 검증셋으로 할당한다.

또한 이러한 분할을 총 k번 배타적으로 수행하기 때문에 모든 이벤트샘플은 하나의 검증 셋 인덱스에 속하게 된다.

다음 코드에서 보면 한번의 분할 결과마다 다른 폴드별 인덱스 (trn_, val_)을 리턴하는 것을 확인할 수 있다.

검증 세트 인덱스부분을 제외하면 모두 훈련세트 파트이므로 for문을 돌며 검증세트 파트에만 fold 인덱스 값을 입력해주면 모든 kfold컬럼에 해당하는 자신이 validation set일 경우의 fold index가 입력되게 된다.

이러한 심플 k-fold는 통상 회귀(regression) 문제에 사용한다.

#k-fold cv
from sklearn import model_selection

X["kfold"] = -1
X = X.sample(frac=1).reset_index(drop=True) # randomize the row of the data

kf = model_selection.KFold(n_splits=5)

# fill the validation set kfold column as kfold index num
for fold, (trn_, val_) in enumerate(kf.split(X=X)): # fold : index of fold
    X.loc[val_, 'kfold'] = fold # trn_ : index of training set row, val_ : index of validation set row

X

2. Stratified K-fold cross-validation

skewed 데이터셋을 가진 분류 문제에서는 일부 fold에서 아예 타겟데이터가 없는 경우가 발생하게 된다. 이를 방지하기 위해 모든 폴드 블럭이 일정 비율의 타겟 데이터 비율을 유지하며 분할하게 하는 것이 Stratified K-fold cv이다. 통상 분류(classification)에 사용된다.

#Stratified k-fold cv
from sklearn import model_selection

X["kfold"] = -1
X = X.sample(frac=1).reset_index(drop=True) # Randomize the row of the data

kf = model_selection.StratifiedKFold(n_splits=5)

# fill the validation set kfold column as kfold index num
for fold, (trn_, val_) in enumerate(kf.split(X=X, y=y)): # fold : index of fold
    X.loc[val_, 'kfold'] = fold # trn_ : index of training set row, val_ : index of validation set row

X

3. Stratified k-fold for regression problem

If you want to apply stratified k-fold to regression, it is first to divide the target(numerical data) to bins(categorical data). There are severral choices for selecting appropriate numbers for bins. If you have a lot of samples( > 10k, > 100k), then you don't need to care about it. If you do not have a lot of samples, you can use Sturge's Rule to calculate the apprpriate number of bins.

  • Sturge's rule : Number of Bins = 1+log2(N)1 + log_2(N)
#Stratified k-fold cv with binning 
from sklearn import model_selection

def create_folds_with_binned(data):
    data["kfold"] = -1

    data = data.sample(frac=1).reset_index(drop=True) # randomize

    num_bins = int(np.floor(1+np.log2(len(data)))) # sturge'rule

    data.loc[:, "bins"] = pd.cut(data['target'], bins=num_bins, labels=False) # bin target
    kf = model_selection.StratifiedKFold(n_splits=5)

    for fold, (trn_, val_) in enumerate(kf.split(X=data, y=data.bins.values)):
        data.loc[val_, 'kfold'] = fold
    
    #data = data.drop("bins", axis=1)
    print(num_bins)
    return data
data_binned = create_folds_with_binned(data)
b = sns.countplot(x='kfold', hue='bins', data=data_binned)

4. Baseline model using cv

간단하게 베이스라인 모델을 만들때 사용하는 코드 샘플이다.

# baseline model - linear regression
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

evals = []

for fold in range(5): 
    X_train_folded = X_train[X_train['kfold'] != fold].reset_index(drop=True)
    X_valid_folded = X_train[X_train['kfold'] == fold].reset_index(drop=True)
    
    y_train = X_train_folded[target_col]
    y_valid = X_valid_folded[target_col]
    X_train_folded = X_train_folded.drop(target_col, axis=1)
    X_valid_folded = X_valid_folded.drop(target_col, axis=1)
    
    model = LinearRegression()
    model.fit(X_train_folded, y_train)
    pred = model.predict(X_valid_folded)
    mse = mean_squared_error(y_valid, pred, squared=False)
    
    print(f'{fold} : {mse}')
    
    evals.append(mse)
    
print(np.array(evals).mean())

References

  1. Approaching (Almost) Any Machine Learning Problem, Abhishek Thakur
profile
Artificial Intelligence study note

0개의 댓글