Реалізація вкладеної перехресної перевірки


10

Я намагаюся зрозуміти, чи правильно я розумію вкладені перехресні перевірки, тому я написав цей приклад іграшки, щоб побачити, чи маю рацію:

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)

Будь-які думки оцінені.


3
Чи можете ви також надати версію свого розуміння перехресної перевірки в тексті для тих, хто не читає Python?
gung - Відновіть Моніку

scikit-learnвласна версія: scikit-learn.org/stable/auto_examples/model_selection/…
ayorgo

Відповіді:


14

UPS, код невірний, але дуже тонко !

а) розбиття поїздів на внутрішній тренувальний комплект і тестовий комплект добре.

б) проблема полягає у двох останніх рядках, які відображають тонкі нерозуміння щодо мети вкладеної перехресної перевірки. Мета вкладеного резюме - не вибір параметрів, а неупереджена оцінка того, яка очікувана точність вашого алгоритму, в цьому випадку ensemble.ExtraTreesRegressorв цих даних найкращий гіперпараметр, яким би вони не були .

Ось що ваш код правильно обчислює до рядка:

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

Він використовував вкладений CV для обчислення об'єктивного передбачення класифікатора. Але зауважте, що кожен прохід зовнішньої петлі може генерувати найкращий гіперпараметр, як ви знали, коли ви писали рядок:

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

Отже, зараз вам потрібна стандартна цикл CV, щоб вибрати остаточний найкращий гіперпараметр, використовуючи складки:

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])

який ваш код, але з посиланнями на внутрішню видалено.

Зараз найкращий параметр tuned_parameter[index], і тепер ви можете дізнатися остаточний класифікатор, clf3як у своєму коді.


Дякую! Я вважав, що я можу вибрати різні bestпараметри в різних складках, але не знав, як вибрати найкращі. stats.stackexchange.com/questions/65128/… - тут, у відповіді зазначається, що насправді небажано вибирати кращу модель із зовнішніх k моделей. Можливо, я все ще щось розумію, але я подумав, що ідея внутрішнього циклу резюме полягає у виборі найкращої моделі, а зовнішній цикл резюме - в оцінці продуктивності. Чи можете ви надати повний модифікований код?
abudis

Гаразд, я думаю, що я це зрозумів. Я хотів би побачити повний модифікований код, просто щоб бути впевненим. Дякую.
abudis

1
Я розгублений щодо відповіді Жак Вайнера, і я вважаю, що це варто уточнити. Отже, чи пропонує Вайнер, щоб стандартний цикл резюме дотримувався коду, передбаченого початковим запитанням, або що він повинен просто замінити початковий "внутрішній" код частини? thanx

Стандартний цикл CV відповідає вкладеному циклу CV
Жак Вайнер

2
Перша частина полягає в обчисленні неупередженого прогнозу помилки. Якщо ви тестуєте безліч різних алгоритмів, вам слід виконати лише 1-ю частину, потім виберіть алгоритм з найменшою помилкою, і лише для цього виконайте 2 частини, щоб вибрати гіперпараметри. Якщо ви налаштовані на використання лише одного алгоритму, то перша частина є менш важливою, якщо ви не хочете заявити своєму начальнику чи клієнту, що ваш найкращий прогноз майбутньої помилки класифікатора - x, і ви повинні обчислити х за допомогою 1-го. вкладене резюме.
Жак Вайнер

0

Щоб узагальнити відповідь Жак,

Вкладене резюме потрібно для об'єктивного оцінювання помилок моделі. Ми можемо порівняти оцінку різних моделей таким чином. Використовуючи цю інформацію, ми можемо виконати окремий цикл резюме для K-параметрів для настройки параметрів вибраних моделей.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.