Estou tentando descobrir se meu entendimento da validação cruzada aninhada está correto, por isso escrevi este exemplo de brinquedo para verificar se estou certo:
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)
Quaisquer pensamentos apreciados.
cross-validation
python
scikit-learn
abudis
fonte
fonte
scikit-learn
versão própria: scikit-learn.org/stable/auto_examples/model_selection/…Respostas:
UPS, o código está errado, mas de uma maneira muito sutil !
a) a divisão do conjunto de trem em um conjunto de treinamento interno e conjunto de teste está correta.
b) o problema são as duas últimas linhas, que refletem o sutil mal-entendido sobre o objetivo de uma validação cruzada aninhada. O objetivo de um CV aninhado não é selecionar os parâmetros, mas ter uma avaliação imparcial da precisão esperada do seu algoritmo, neste caso
ensemble.ExtraTreesRegressor
nesses dados com o melhor hiperparâmetro, sejam eles quais forem .E é isso que seu código calcula corretamente até a linha:
Ele usou o CV aninhado para calcular uma previsão imparcial do classificador. Mas observe que cada passagem do loop externo pode gerar um melhor hiperparâmetro diferente, como você sabia quando escreveu a linha:
Então agora você precisa de um loop CV padrão para selecionar o melhor hiperparâmetro final, usando dobras:
qual é o seu código, mas com referências ao interno removido.
Agora, o melhor parâmetro é
tuned_parameter[index]
e agora você pode aprender o classificador finalclf3
como no seu código.fonte
best
parâmetros diferentes em dobras diferentes, mas não sabia como escolher os melhores. stats.stackexchange.com/questions/65128/… - aqui, na resposta é mencionado que é realmente indesejável selecionar o melhor modelo dentre os modelos k externos. Talvez ainda esteja entendendo mal alguma coisa, mas pensei que a idéia do loop interno do CV é selecionar o modelo com melhor desempenho e o loop externo do CV é estimar o desempenho. Você poderia fornecer o código completo modificado?Para resumir a resposta de Jacques,
O CV aninhado é necessário para a estimativa de erro imparcial de um modelo. Podemos comparar a pontuação de diferentes modelos dessa maneira. Usando essas informações, podemos executar um loop CV dobrável em K separado para o ajuste dos parâmetros dos modelos selecionados.
fonte