(Sono sicuro di aver già scritto la maggior parte di questo in qualche risposta, ma non riesco a trovarlo in questo momento. Se qualcuno si imbatte in quella risposta, si prega di collegarlo). Vedo 2 approcci leggermente diversi qui, che penso siano entrambi sensati.
Ma prima un po 'di terminologia:
- Proveniente da un campo applicato, un modello (montato / addestrato) per me è un modello pronto per l'uso. Vale a dire il modello contiene tutte le informazioni necessarie per generare previsioni per nuovi dati. Pertanto, il modello contiene anche gli iperparametri . Come vedrai, questo punto di vista è strettamente correlato all'approccio 2 di seguito.
- OTOH, l' algoritmo di allenamento secondo la mia esperienza non è ben definito nel senso seguente: per ottenere il modello (adattato), non è necessario solo fare - chiamiamolo "adattamento primario" - dei parametri del modello "normale", ma anche gli iperparametri devono essere riparati. Dal mio punto di vista applicativo, non c'è molta differenza tra parametri e iperparametri: entrambi fanno parte del modello e devono essere stimati / decisi durante l'allenamento.
Immagino che la differenza tra loro sia correlata alla differenza tra qualcuno che sviluppa nuovi algoritmi di allenamento che di solito descrivono una classe di algoritmi di allenamento insieme ad alcuni parametri di governo (gli iperparametri) che sono difficili / impossibe da correggere (o almeno per stabilire come dovrebbero essere decisi / stimati) senza conoscenza dell'applicazione / dominio.
Approccio 1: richiedono risultati di ottimizzazione stabili
Con questo approccio, "training del modello" è l'adattamento dei parametri "normali" del modello e vengono forniti iperparametri . Una validazione incrociata interna, ad esempio, si occupa dell'ottimizzazione dell'iperparametro.
Il passaggio / ipotesi cruciale qui per risolvere il dilemma del cui set di iperparametri dovrebbe essere scelto è di richiedere che l'ottimizzazione sia stabile . La convalida incrociata ai fini della convalida presuppone che tutti i modelli surrogati siano sufficientemente simili al modello finale (ottenuto dallo stesso algoritmo di addestramento applicato all'intero set di dati) per consentire di trattarli come uguali (tra di loro e al modello finale). Se questa ipotesi si interrompe e
i modelli surrogati sono ancora uguali (o equivalenti) tra loro ma non al modello finale, stiamo parlando del noto pregiudizio pessimistico della convalida incrociata.
Se anche il modello surrogato non è uguale / equivalente tra loro, abbiamo problemi di instabilità .
Per i risultati di ottimizzazione del circuito interno ciò significa che se l'ottimizzazione è stabile, non vi è alcun conflitto nella scelta degli iperparametri . E se si osservano notevoli variazioni attraverso i risultati della validazione incrociata interna, l'ottimizzazione non è stabile . Le situazioni di allenamento instabili hanno problemi di gran lunga peggiori rispetto alla sola decisione dell'iperparametro di scegliere, e consiglio vivamente di fare un passo indietro in quel caso e iniziare il processo di modellazione dappertutto.
C'è un'eccezione, qui, però: ci possono essere diversi minimi locali nell'ottimizzazione che producono prestazioni uguali a scopi pratici. Richiedere che la scelta tra loro sia stabile può essere un requisito forte non necessario - ma non so come uscire da questo dilemma.
Si noti che se non tutti i modelli producono lo stesso set di parametri vincenti, non è necessario utilizzare le stime del loop esterno come errore di generalizzazione qui:
- p
- Ma a meno che non vi sia alcuna decisione in quanto tutte le suddivisioni hanno prodotto gli stessi parametri, questo romperà l'indipendenza nel circuito esterno: i dati di test di ogni divisione hanno già inserito la decisione quale set di parametri vince poiché erano i dati di allenamento in tutte le altre suddivisioni e quindi utilizzati per ottimizzare i parametri.
Approccio 2: trattare l'accordatura dell'iperparametro come parte dell'allenamento del modello
Questo approccio collega le prospettive dello "sviluppatore dell'algoritmo di training" e applica l'utente dell'algoritmo di training.
Lo sviluppatore dell'algoritmo di training fornisce un algoritmo di training "nudo" model = train_naked (trainingdata, hyperparameters)
. Come ha bisogno l'utente applicato tunedmodel = train_tuned (trainingdata)
che si occupa anche di riparare gli iperparametri.
train_tuned
può essere implementato, ad esempio avvolgendo un ottimizzatore basato sulla convalida incrociata attorno all'algoritmo di training nudo train_naked
.
train_tuned
può quindi essere utilizzato come qualsiasi altro algoritmo di allenamento che non richiede input da iperparametro, ad esempio il suo output tunedmodel
può essere sottoposto a validazione incrociata. Ora gli iperparametri sono controllati per la loro stabilità proprio come i parametri "normali" dovrebbero essere controllati per stabilità come parte della valutazione della validazione incrociata.
Questo è in realtà ciò che fai e valuti nella validazione incrociata nidificata se esegui una media delle prestazioni di tutti i modelli vincenti, indipendentemente dai loro singoli set di parametri.
Qual è la differenza?
Probabilmente finiamo con diversi modelli finali che adottano questi 2 approcci:
- sarà il modello finale nell'approccio 1
train_naked (all data, hyperparameters from optimization)
- mentre l'approccio 2 utilizzerà
train_tuned (all data)
e, poiché esegue nuovamente l'ottimizzazione dell'iperparametro sul set di dati più grande, ciò potrebbe finire con un diverso set di iperparametri.
Ma di nuovo si applica la stessa logica: se troviamo che il modello finale ha parametri sostanzialmente diversi dai modelli surrogati di validazione incrociata, questo è un sintomo della violazione dell'ipotesi 1. Quindi, IMHO, ancora una volta non abbiamo un conflitto, ma piuttosto un controllo sulla legittimità delle nostre assunzioni (implicite). E se non lo sono, non dovremmo comunque scommettere troppo sull'avere una buona stima delle prestazioni di quel modello finale.
Ho l'impressione (anche dal vedere il numero di domande / confusioni simili qui sul CV) che molte persone pensano di convalida incrociata nidificata facendo l'approccio 1. Ma l'errore di generalizzazione è di solito stimato in base all'approccio 2, quindi questa è la strada da percorrere per anche modello finale.
Esempio di iris
Riepilogo: l'ottimizzazione è sostanzialmente inutile. La dimensione del campione disponibile non consente distinzioni tra le prestazioni di nessuno dei set di parametri qui.
Dal punto di vista dell'applicazione, tuttavia, la conclusione è che non importa quale dei 4 set di parametri si scelga, il che non è poi una brutta notizia: hai trovato un plateau relativamente stabile di parametri. Ecco il vantaggio della corretta validazione nidificata del modello ottimizzato: mentre non si è in grado di affermare che si tratta del modello ottimale, si è comunque in grado di affermare che il modello basato su tutti i dati utilizzando l'approccio 2 avrà precisione del 97% circa (intervallo di confidenza al 95% per 145 casi su 150 corretti: 92 - 99%)
Si noti che anche l'approccio 1 non è così lontano come sembra - vedi sotto: l'ottimizzazione ha accidentalmente mancato un "vincitore" relativamente chiaro a causa dei legami (che in realtà è un altro sintomo molto rivelatore del problema delle dimensioni del campione).
Mentre non sono abbastanza approfondito negli SVM per "vedere" che C = 1 dovrebbe essere una buona scelta qui, andrei con il kernel lineare più restrittivo. Inoltre, mentre hai fatto l'ottimizzazione, non c'è niente di sbagliato nella scelta del set di parametri vincente anche se sei consapevole che tutti i set di parametri portano a prestazioni praticamente uguali.
In futuro, tuttavia, considera se la tua esperienza produce stime approssimative di quali prestazioni puoi aspettarti e approssimativamente quale modello sarebbe una buona scelta. Quindi costruire quel modello (con iperparametri fissi manualmente) e calcolare un intervallo di confidenza per le sue prestazioni. Usa questo per decidere se cercare di ottimizzare sia sensato. (Posso aggiungere che sto lavorando principalmente con dati in cui non è facile ottenere altri 10 casi indipendenti - se ci si trova in un campo con campioni di grandi dimensioni indipendenti, le cose sembrano molto migliori per te)
versione lunga:
Per quanto riguarda i risultati di esempio sul iris
set di dati. iris
ha 150 casi, sono considerati SVM con una griglia di 2 x 2 parametri (2 kernel, 2 ordini di grandezza per la penalità C
).
Il ciclo interno ha divisioni di 129 (2x) e 132 (6x) casi. Il set di parametri "migliore" è indeciso tra kernel lineare o rbf, entrambi con C = 1. Tuttavia, le accuratezze del test interno sono tutte (compresa la C = 10 che perde sempre) entro un'accuratezza osservata del 94 - 98,5%. La differenza più grande che abbiamo in una delle divisioni è 3 contro 8 errori per rbf con C = 1 contro 10.
Non c'è modo che questa sia una differenza significativa. Non so come estrarre le previsioni per i singoli casi nel CV, ma anche supponendo che i 3 errori fossero condivisi e il modello C = 10 abbia fatto altri 5 errori:
> 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
Ricorda che ci sono 6 confronti a coppie nella griglia 2 x 2, quindi dovremmo correggere anche per confronti multipli.
Approccio 1
In 3 delle 4 divisioni esterne in cui rbf "ha vinto" sul kernel lineare, avevano effettivamente la stessa accuratezza stimata (suppongo che min in caso di pareggi restituisca il primo indice adatto).
Modifica della griglia in
params = {'kernel':['linear', 'rbf'],'C':[1,10]}
rese
({'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)
Approccio 2:
Ecco il clf
tuo modello finale. Con random_state = 2
, rbf con C = 1 vince:
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}]
(succede circa 1 su 5 volte, 1 su 6 volte linear
e rbf
con C = 1
sono legati al rango 1)