(Tenho certeza de que já escrevi a maior parte disso em alguma resposta - mas não consigo encontrá-la agora. Se alguém se deparar com essa resposta, vincule-a). Eu vejo duas abordagens ligeiramente diferentes aqui, que eu acho que são sensatas.
Mas primeiro alguma terminologia:
- Vindo de um campo aplicado, um modelo (equipado / treinado) para mim é um pronto para uso. Ou seja, o modelo contém todas as informações necessárias para gerar previsões para novos dados. Assim, o modelo também contém os hiperparâmetros . Como você verá, esse ponto de vista está intimamente relacionado à abordagem 2 abaixo.
- OTOH, na minha experiência , o algoritmo de treinamento não está bem definido no seguinte sentido: para obter o modelo (ajustado), não apenas o - vamos chamá-lo de "ajuste primário" - dos parâmetros do modelo "normal" precisa ser feito, mas também os hiperparâmetros precisam ser corrigidos. Do meu ponto de vista da aplicação, não há realmente muita diferença entre parâmetros e hiperparâmetros: ambos fazem parte do modelo e precisam ser estimados / decididos durante o treinamento.
Eu acho que a diferença entre eles está relacionada à diferença entre alguém que desenvolve novos algoritmos de treinamento que normalmente descrevem uma classe de algoritmos de treinamento junto com alguns parâmetros de direção (os hiperparâmetros) que são difíceis / impossíveis de corrigir (ou pelo menos para corrigir como devem ser decididos / estimados) sem o conhecimento do aplicativo / domínio.
Abordagem 1: exigir resultados de otimização estáveis
Com essa abordagem, o "treinamento do modelo" é o ajuste dos parâmetros do modelo "normal" e são fornecidos hiperparâmetros . Uma validação cruzada interna, por exemplo, cuida da otimização do hiperparâmetro.
A etapa / suposição crucial aqui para resolver o dilema cujo conjunto de hiperparâmetros deve ser escolhido é exigir que a otimização seja estável . A validação cruzada para fins de validação pressupõe que todos os modelos substitutos sejam suficientemente semelhantes ao modelo final (obtido pelo mesmo algoritmo de treinamento aplicado a todo o conjunto de dados) para permitir tratá-los como iguais (entre si e com o modelo final). Se essa suposição se quebrar e
Como os modelos substitutos ainda são iguais (ou equivalentes) entre si, mas não ao modelo final, estamos falando do conhecido viés pessimista da validação cruzada.
Se também o modelo substituto não é igual / equivalente um ao outro, temos problemas com instabilidade .
Para os resultados de otimização do loop interno, isso significa que, se a otimização for estável, não haverá conflito na escolha de hiperparâmetros . E se uma variação considerável for observada nos resultados da validação cruzada interna, a otimização não será estável . As situações instáveis de treinamento têm problemas muito piores do que apenas a decisão de qual parâmetro é escolhido, e eu realmente recomendo dar um passo atrás nesse caso e iniciar o processo de modelagem novamente.
Há uma exceção aqui: porém, pode haver vários mínimos locais na otimização, produzindo desempenho igual para fins práticos. Exigir também que a escolha entre eles seja estável pode ser um forte requisito desnecessário - mas não sei como sair desse dilema.
Observe que se nem todos os modelos produzirem o mesmo conjunto de parâmetros vencedor, você não deve usar estimativas de loop externo como erro de generalização aqui:
- p
- Mas, a menos que não haja decisão envolvida, pois todas as divisões produziram os mesmos parâmetros, isso quebrará a independência no loop externo: os dados de teste de cada divisão já entraram na decisão de qual conjunto de parâmetros vence, pois treinavam dados em todas as outras divisões e, portanto, utilizados para otimizar os parâmetros.
Abordagem 2: trate o ajuste do hiperparâmetro como parte do treinamento do modelo
Essa abordagem une as perspectivas do "desenvolvedor do algoritmo de treinamento" e do usuário aplicado do algoritmo de treinamento.
O desenvolvedor do algoritmo de treinamento fornece um algoritmo de treinamento "nu" model = train_naked (trainingdata, hyperparameters)
. Como o usuário aplicado precisa, tunedmodel = train_tuned (trainingdata)
ele também cuida da fixação dos hiperparâmetros.
train_tuned
pode ser implementado, por exemplo, envolvendo um otimizador baseado em validação cruzada em torno do algoritmo de treinamento nu train_naked
.
train_tuned
pode então ser usado como qualquer outro algoritmo de treinamento que não exija entrada de hiperparâmetro, por exemplo, sua saída tunedmodel
pode ser submetida a validação cruzada. Agora, os hiperparâmetros são verificados quanto à estabilidade, assim como os parâmetros "normais" devem ser verificados quanto à estabilidade como parte da avaliação da validação cruzada.
Na verdade, é isso que você faz e avalia na validação cruzada aninhada se você mediar o desempenho de todos os modelos vencedores, independentemente de seus conjuntos de parâmetros individuais.
Qual é a diferença?
Possivelmente, acabamos com diferentes modelos finais seguindo essas 2 abordagens:
- o modelo final na abordagem 1 será
train_naked (all data, hyperparameters from optimization)
- enquanto a abordagem 2 usará
train_tuned (all data)
e - conforme isso executa a otimização do hiperparâmetro novamente no conjunto de dados maior - isso pode acabar com um conjunto diferente de hiperparâmetros.
Mas, novamente, a mesma lógica se aplica: se acharmos que o modelo final possui parâmetros substancialmente diferentes dos modelos substitutos de validação cruzada, esse é um sintoma da suposição 1 sendo violada. Então, IMHO, novamente não temos um conflito, mas sim uma verificação se nossas suposições (implícitas) são justificadas. E, se não estiverem, não devemos apostar demais em ter uma boa estimativa do desempenho desse modelo final.
Tenho a impressão (também de ver o número de perguntas / confusões semelhantes aqui no CV) que muitas pessoas pensam em validação cruzada aninhada fazendo a abordagem 1. Mas o erro de generalização geralmente é estimado de acordo com a abordagem 2, então esse é o caminho a seguir. modelo final também.
Exemplo de íris
Resumo: a otimização é basicamente inútil. O tamanho da amostra disponível não permite distinções entre o desempenho de qualquer um dos conjuntos de parâmetros aqui.
Do ponto de vista da aplicação, no entanto, a conclusão é que não importa qual dos quatro conjuntos de parâmetros você escolhe - o que não é uma má notícia: você encontrou um platô de parâmetros comparativamente estável. Aí vem a vantagem da validação aninhada adequada do modelo ajustado: enquanto você não é capaz de afirmar que é o modelo ideal, você ainda pode afirmar que o modelo construído em todos os dados usando a abordagem 2 terá aproximadamente 97% de precisão (intervalo de confiança de 95% para 145 casos corretos em 150 testes: 92 - 99%)
Observe que a abordagem 1 também não está tão longe quanto parece - veja abaixo: sua otimização acidentalmente perdeu um "vencedor" relativamente claro por causa de laços (na verdade, esse é outro sintoma muito revelador do problema do tamanho da amostra).
Embora eu não tenha profundidade suficiente nos SVMs para "ver" que C = 1 deve ser uma boa opção aqui, eu usaria o kernel linear mais restritivo. Além disso, como você fez a otimização, não há nada errado em escolher o conjunto de parâmetros vencedor, mesmo que você saiba que todos os conjuntos de parâmetros levam a um desempenho praticamente igual.
No futuro, no entanto, considere se sua experiência gera estimativas aproximadas de qual desempenho você pode esperar e aproximadamente qual modelo seria uma boa escolha. Em seguida, construa esse modelo (com hiperparâmetros corrigidos manualmente) e calcule um intervalo de confiança para seu desempenho. Use isso para decidir se a tentativa de otimizar é sensata. (Devo acrescentar que estou trabalhando principalmente com dados em que não é fácil obter mais 10 casos independentes - se você estiver em um campo com grandes tamanhos de amostras independentes, as coisas parecerão muito melhores para você)
versão longa:
Quanto aos resultados de exemplo no iris
conjunto de dados. iris
tem 150 casos, é considerado o SVM com uma grade de 2 x 2 parâmetros (2 núcleos, 2 ordens de grandeza para a penalidade C
).
O loop interno possui divisões de 129 (2x) e 132 (6x) casos. O "melhor" conjunto de parâmetros é indeciso entre o kernel linear ou rbf, ambos com C = 1. No entanto, as exatidões do teste interno são todas (incluindo o C = 10 sempre perdedor) dentro de 94 - 98,5% da precisão observada. A maior diferença que temos em uma das divisões é de 3 vs. 8 erros para rbf com C = 1 vs. 10.
Não há como essa diferença significativa. Não sei como extrair as previsões para casos individuais no currículo, mas mesmo assumindo que os 3 erros foram compartilhados, e o modelo C = 10 cometeu 5 erros adicionais:
> table (rbf1, rbf10)
rbf10
rbf1 correct wrong
correct 124 5
wrong 0 3
> mcnemar.exact(rbf1, rbf10)
Exact McNemar test (with central confidence intervals)
data: rbf1 and rbf10
b = 5, c = 0, p-value = 0.0625
alternative hypothesis: true odds ratio is not equal to 1
Lembre-se de que existem 6 comparações pareadas na grade 2 x 2; portanto, precisamos corrigir várias comparações também.
Abordagem 1
Em 3 das 4 divisões externas em que rbf "venceu" o kernel linear, elas realmente tinham a mesma precisão estimada (acho que min em caso de empate retorna o primeiro índice adequado).
Alterando a grade para
params = {'kernel':['linear', 'rbf'],'C':[1,10]}
rendimentos
({'kernel': 'linear', 'C': 1}, 0.95238095238095233, 0.97674418604651159)
({'kernel': 'rbf', 'C': 1}, 0.95238095238095233, 0.98449612403100772)
({'kernel': 'linear', 'C': 1}, 1.0, 0.97727272727272729)
({'kernel': 'linear', 'C': 1}, 0.94444444444444442, 0.98484848484848486)
({'kernel': 'linear', 'C': 1}, 0.94444444444444442, 0.98484848484848486)
({'kernel': 'linear', 'C': 1}, 1.0, 0.98484848484848486)
({'kernel': 'linear', 'C': 1}, 1.0, 0.96212121212121215)
Abordagem 2:
Aqui clf
está o seu modelo final. Com random_state = 2
, rbf com C = 1 ganha:
In [310]: clf.grid_scores_
[...snip warning...]
Out[310]:
[mean: 0.97333, std: 0.00897, params: {'kernel': 'linear', 'C': 1},
mean: 0.98000, std: 0.02773, params: {'kernel': 'rbf', 'C': 1},
mean: 0.96000, std: 0.03202, params: {'kernel': 'linear', 'C': 10},
mean: 0.95333, std: 0.01791, params: {'kernel': 'rbf', 'C': 10}]
(acontece cerca de 1 em 5 vezes, 1 em 6 vezes linear
e rbf
com C = 1
empate no ranking 1)