Yuvalanmış çapraz doğrulamanın uygulanması


10

İç içe çapraz doğrulama anlayışımın doğru olup olmadığını anlamaya çalışıyorum, bu yüzden doğru olup olmadığımı görmek için bu oyuncak örneğini yazdım:

import operator
import numpy as np
from sklearn import cross_validation
from sklearn import ensemble
from sklearn.datasets import load_boston

# set random state
state = 1

# load boston dataset
boston = load_boston()

X = boston.data
y = boston.target

outer_scores = []

# outer cross-validation
outer = cross_validation.KFold(len(y), n_folds=3, shuffle=True, random_state=state)
for fold, (train_index_outer, test_index_outer) in enumerate(outer):
    X_train_outer, X_test_outer = X[train_index_outer], X[test_index_outer]
    y_train_outer, y_test_outer = y[train_index_outer], y[test_index_outer]

    inner_mean_scores = []

    # define explored parameter space.
    # procedure below should be equal to GridSearchCV
    tuned_parameter = [1000, 1100, 1200]
    for param in tuned_parameter:

        inner_scores = []

        # inner cross-validation
        inner = cross_validation.KFold(len(X_train_outer), n_folds=3, shuffle=True, random_state=state)
        for train_index_inner, test_index_inner in inner:
            # split the training data of outer CV
            X_train_inner, X_test_inner = X_train_outer[train_index_inner], X_train_outer[test_index_inner]
            y_train_inner, y_test_inner = y_train_outer[train_index_inner], y_train_outer[test_index_inner]

            # fit extremely randomized trees regressor to training data of inner CV
            clf = ensemble.ExtraTreesRegressor(param, n_jobs=-1, random_state=1)
            clf.fit(X_train_inner, y_train_inner)
            inner_scores.append(clf.score(X_test_inner, y_test_inner))

        # calculate mean score for inner folds
        inner_mean_scores.append(np.mean(inner_scores))

    # get maximum score index
    index, value = max(enumerate(inner_mean_scores), key=operator.itemgetter(1))

    print 'Best parameter of %i fold: %i' % (fold + 1, tuned_parameter[index])

    # fit the selected model to the training set of outer CV
    # for prediction error estimation
    clf2 = ensemble.ExtraTreesRegressor(tuned_parameter[index], n_jobs=-1, random_state=1)
    clf2.fit(X_train_outer, y_train_outer)
    outer_scores.append(clf2.score(X_test_outer, y_test_outer))

# show the prediction error estimate produced by nested CV
print 'Unbiased prediction error: %.4f' % (np.mean(outer_scores))

# finally, fit the selected model to the whole dataset
clf3 = ensemble.ExtraTreesRegressor(tuned_parameter[index], n_jobs=-1, random_state=1)
clf3.fit(X, y)

Herhangi bir düşünce takdir.


3
Ayrıca Python okumayanlar için metinde çapraz doğrulama anlayışınızın bir sürümünü de sağlayabilir misiniz?
gung - Monica'yı eski

Yanıtlar:


14

UPS, kod yanlış, ama çok ince bir şekilde!

a) tren setinin bir iç eğitim setine ve test setine ayrılması sorun yaratmaz.

b) sorun, iç içe geçmiş bir çapraz doğrulamanın amacı hakkındaki ince yanlış anlamaları yansıtan son iki satırdır . Yuvalanmış bir CV'nin amacı parametreleri seçmek değil , algoritmanızın beklenen doğruluğu hakkında tarafsız bir değerlendirme yapmaktır, bu durumda ensemble.ExtraTreesRegressorbu verilerde olabilecek en iyi hiperparametreyle .

Ve kodunuz hatta doğru şekilde hesaplar:

    print 'Unbiased prediction error: %.4f' % (np.mean(outer_scores))

Sınıflandırıcının tarafsız bir tahminini hesaplamak için nested-CV'yi kullandı. Ancak, satırı yazdığınızda bildiğiniz gibi, dış halkanın her geçişinin farklı bir en iyi hiperparametre üretebileceğine dikkat edin:

   print 'Best parameter of %i fold: %i' % (fold + 1, tuned_parameter[index])

Şimdi , kıvrımları kullanarak son en iyi hiperparametreyi seçmek için standart bir CV döngüsüne ihtiyacınız var :

tuned_parameter = [1000, 1100, 1200]
for param in tuned_parameter:

    scores = []

    # normal cross-validation
    kfolds = cross_validation.KFold(len(y), n_folds=3, shuffle=True, random_state=state)
    for train_index, test_index in kfolds:
        # split the training data
        X_train, X_test = X[train_index], X[test_index]
        y_train, y_test = y[train_index], y[test_index]

        # fit extremely randomized trees regressor to training data
        clf2_5 = ensemble.ExtraTreesRegressor(param, n_jobs=-1, random_state=1)
        clf2_5.fit(X_train, y_train)
        scores.append(clf2_5.score(X_test, y_test))

    # calculate mean score for folds
    mean_scores.append(np.mean(scores))

# get maximum score index
index, value = max(enumerate(mean_scores), key=operator.itemgetter(1))

print 'Best parameter : %i' % (tuned_parameter[index])

ki bu sizin kodunuz ama referanslar kaldırıldı.

Şimdi en iyi parametre tuned_parameter[index]ve artık clf3kodunuzdaki gibi son sınıflandırıcıyı öğrenebilirsiniz .


Teşekkürler! bestFarklı kıvrımlarda farklı parametreler seçebileceğimi düşündüm , ancak en iyisini nasıl seçeceğimi bilmiyordum. stats.stackexchange.com/questions/65128/… - burada cevapta dış k modellerinden en iyi modeli seçmenin aslında istenmediği belirtiliyor. Belki hala bir şeyi yanlış anlıyorum, ama iç CV döngüsünün fikrinin en iyi performans gösteren modeli seçmek olduğunu ve dış CV döngüsünün performansı tahmin etmek olduğunu düşündüm. Lütfen değiştirilmiş kodun tamamını verebilir misiniz?
abudis

Tamam, sanırım anladım. Sadece emin olmak için tam değiştirilmiş kodu olsa görmek istiyorum. Teşekkürler.
abudis

1
Jacques Wainer'ın cevabı konusunda kafam karıştı ve bunun açıklığa kavuşturmaya değer olduğunu düşünüyorum. Peki, Wainer standart bir CV döngüsünün ilk soru tarafından sağlanan koda uymasını mı yoksa sadece ilk "iç" parça kodunun yerine geçmesini mi öneriyor? thanx

Standart CV döngüsü iç içe CV döngüsünü takip eder
Jacques Wainer

2
İlk bölüm, hatanın tarafsız bir tahminini hesaplamaktır. Birçok farklı algoritmayı test ediyorsanız, yalnızca 1. kısmı gerçekleştirmeli, ardından en düşük hataya sahip algoritmayı seçmelisiniz ve sadece bunun için hiperparametreleri seçmek için 2 parçayı gerçekleştirmelisiniz. Yalnızca bir algoritma kullanmaya ayarlıysanız, patronunuza veya müşterinize sınıflandırıcının gelecekteki hatasını en iyi tahmininizin x olduğunu belirtmek istemiyorsanız 1. bölüm daha az önemlidir ve 1'i kullanarak x'i hesaplamanız gerekir. iç içe CV.
Jacques Wainer

0

Jacques'ın cevabını özetlemek gerekirse,

İç içe CV, bir modelin tarafsız hata tahmini için gereklidir. Farklı modellerin skorlarını bu şekilde karşılaştırabiliriz. Bu bilgileri kullanarak, seçilen modellerin parametre ayarı için ayrı bir K-katlı CV döngüsü gerçekleştirebiliriz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.