Hyppää sisältöön

Welcome to our weekly research support coffee hour on Zoom! Click here for more information.

Warning!

Puhti scratch disk is becoming very full (80+ % ) resulting in performance degradation. Everybody is advised to only keep actively processed data on scratch, all other data should be deleted, transferred to host institute or stored in Lumi-O. No new quota will be granted. Click here for a tool for examining your disk usage.

Hyperparametrien haku

Tässä oppaassa kerrotaan, miten koneoppimisen hyperparametrien haku tehdään CSC:n supertietokoneilla. Se on osa koneoppimisopastamme.

Johdanto

Koneoppimisessa (ML) yksi keskeinen osa mallinvalintaa on valita sopiva joukko mallin asetuksia tietyn tilastollisen ongelman ratkaisemiseksi. Näitä mallin asetuksia kutsutaan hyperparametreiksi.

Tämä ei ole missään nimessä helppo tehtävä. Tilastolliset estimointiongelmat olettavat, että optimaalinen ratkaisu on olemassa, mutta monissa todellisen maailman ongelmissa ei ole takeita siitä, että tällainen ratkaisu olisi olemassa. Esimerkiksi biologisissa ja lääketieteellisissä sovelluksissa havaintojen vaihtelu tekee optimaalisten, eroteltavien päätösrajojen löytämisestä lähes mahdotonta, kun taas (kanonisessa) meribassin ja lohen lajittelussa ratkaisut ovat enemmän tai vähemmän optimaalisesti määriteltävissä. Kielitieteessä taas voidaan ehkä löytää tilastollisesti optimaalisia ratkaisuja, mutta semanttisesti tulokset voivat olla ihmisille käsittämättömiä. Optimaalisen ratkaisun puute vaikeuttaa suositusten antamista siitä, miten hyperparametrit tulisi asettaa tiettyä ML-ongelmaa varten. Tästä syystä tässä dokumentissa käytetään termiä haku termin optimointi sijaan (vaikka optimointi esiintyy useammin ML-kirjallisuudessa).

Muutamia keskeisiä huomioita hyperparametrien hakua tehtäessä:

  • käytettävissä olevan datan määrä
  • häviöfunktion valinta (määrittää käytettävän estimaattorin tyypin)
  • ratkaisijan valinta

Nämä kohdat ovat riippuvaisia toisistaan. Hyperparametrit voivat olla numeerisia (diskreettejä tai jatkuvia) tai kategorisia (regularisoinnin tyyppi, aktivointifunktiot, ratkaisijat), ja lisäksi monilla hyperparametreilla voi olla sekä lineaarisia että epälineaarisia vaikutuksia toisiinsa. Koska ML-malleja sovelletaan tilastollisiin ongelmiin, käsillä olevan ongelman hyvä tilastollinen ymmärrys on korvaamatonta: se auttaa määrittämään mahdollisia hyperparametrivaihtoehtoja ja niiden vaihteluvälejä sekä valitsemaan oikean tyyppisen estimaattorin. Esimerkiksi jos kaikkia tai lähes kaikkia piirteitä pidetään ongelman kannalta tärkeinä, rinnakkaiset oppimismenetelmät ovat suositeltavia (kuten neuroverkot). Jos taas vain joitakin piirteitä pidetään tärkeinä, tulisi suosia peräkkäisiä tilastollisia menetelmiä. Sopivien hyperparametrien valinta voidaan tehdä joko käsin tai automaattisesti. Tämä dokumentaatio keskittyy automaattiseen hakuun.

Hyperparametrien hakua varten data jaetaan satunnaisesti kolmeen erilliseen joukkoon: opetus-, validointi- ja testijoukkoon (edellyttäen, että dataa on riittävästi; muuten validointijoukko voidaan jättää pois). Hyperparametreja haetaan opetusdatan avulla ja validoidaan validointijoukolla. Kun sopiva hyperparametrien joukko on löydetty, valmis malli arvioidaan testijoukkoa vasten.

On kuitenkin hyvä pitää mielessä, että hyperparametrin muuttaminen määrittää uuden mallin. Kaikki hyperparametrien hakumenetelmät valitsevat parhaan mallin annetun metriikan suhteen (esimerkiksi virhetodennäköisyyden), mikä on tilastollisesti kyseenalainen lähestymistapa. n mallin opettaminen samalla aineistolla aiheuttaa riippuvuuden, joka on otettava huomioon eri malleja vertailtaessa. Esimerkiksi ANOVA:a tai Bernoulli-kokeita voidaan harkita, kun verrataan eri malleja samalla datalla.

Hakustrategiat

Hyperparametrien haulle on viisi pääluokkaa.

Ruudukkohauissa mallin hyperparametrien ajatellaan muodostavan ruudukon. Jokainen ruudukon piste vastaa yhtä hyperparametrien joukkoa, ja sitten ruudukko käydään läpi ja arvioidaan annetun metriikan suhteen. Tämä lähestymistapa soveltuu paremmin tilanteisiin, joissa hyperparametrien määrä on pieni ja niiden vaihteluvälit rajallisia. Tämä johtuu siitä, että ruudukkohaku tekee tyhjentävän haun koko hakuavaruudesta, mikä voi olla aikaa vievää suuren hakuavaruuden tapauksessa. Siksi ruudukkohaku sopii paremmin, jos haet pientä määrää hyperparametreja tai sopivia kategorisia hyperparametreja, kuten regularisoijan tyyppiä ja ratkaisijan tyyppiä. Ruudukkohaku on helposti rinnakkaistettavissa.

Satunnaishaku mahdollistaa hyperparametrien haun suuremmasta hakuavaruudesta. Kun käytössä on joukko hyperparametreja sekä niiden ala- ja ylärajat, arvot valitaan satunnaisesti annetuista vaihteluväleistä. Teoriassa suuren hakuavaruuden tapauksessa satunnaishaku pystyy löytämään sopivamman hyperparametrien joukon. Samoin kuin ruudukkohaku, myös satunnaishaku on helposti rinnakkaistettavissa.

Ruudukko- ja satunnaishaku eivät ota huomioon aiemmin arvioituja hyperparametriehdokkaita, kun taas mukautuva haku eli Bayes-optimointi hyödyntää aiemmin arvioituja hyperparametreja ohjatakseen uuden hyperparametrien joukon hakua. Haku tehdään opettamalla korvikemalli (surrogate model), joka sisältää joukon alkuperäisiä hyperparametreja. Kun korvikemalli on opetettu, hankintafunktiota (acquisition function) käytetään ohjaamaan uusien hyperparametrien hakua. Tämä lähestymistapa on luonteeltaan peräkkäinen: haku etenee vasta sen jälkeen, kun hankintafunktio on arvioinut hyperparametrien joukon, mikä tekee mukautuvan haun rinnakkaistamisesta vaikeaa.

Monitarkkuushaku ratkaisee suurten hyperparametriavaruuksien haun ongelmaa erityisesti suurissa neuroverkkmalleissa. Haku jaetaan matalan ja korkean tarkkuuden arviointeihin: matalan tarkkuuden arviointi käyttää pientä osajoukkoa opetusdatasta, kun taas korkean tarkkuuden arviointi käyttää suurta osajoukkoa opetusdatasta. Kunkin hyperparametriasetuksen suorituskyky matalan ja korkean tarkkuuden arvioinneissa tallennetaan, ja parhaiten suoriutuneet valitaan seuraavaan arviointiin. Kaksi suosittua monitarkkuuslähestymistapaa ovat successive halving ja hyperband. Successive halving -menetelmässä jokainen arviointikierros hylkää puolet heikoimmin suoriutuvista hyperparametriasetuksista, joilla on staattinen budjetti, ja säilyttää paremman puoliskon hyperparametriasetuksista. Tätä prosessia jatketaan, kunnes jäljellä on paras hyperparametrien joukko. Hyperband ratkaisee successive halving -menetelmän staattisen luonteen jakamalla budjettia dynaamisesti hyperparametreille iteraatioiden aikana ja käyttämällä successive halvingia aliohjelmana sopivien hyperparametrien valintaan.

Metaheuristiikat

Metaheuristiikat ovat joukko hakumenetelmiä, jotka pystyvät käsittelemään vaikeita rajoitteita, kuten epäkonveksisuutta sekä epäjatkuvia ja epäsileitä funktioita. Teoriassa metaheuristiikat voivat tuottaa parempia approksimaatioita globaalista optimista (jos todellinen optimi on olemassa) suurimittakaavaisille malleille. Hyperparametrien haussa suosittuja metaheuristisia lähestymistapoja ovat evolutionary computation ja particle swarm -menetelmät: evolutionaarisessa laskennassa joukko alkuperäisiä, satunnaisia hyperparametreja arvioidaan, minkä jälkeen niitä mutatoidaan ja valitaan soveltuvuusfunktion perusteella. Particle swarm -menetelmät toimivat samankaltaisesti, mutta hyperparametrien haku tehdään puolikollektiivisesti: jokainen hyperparametri arvioidaan yksilöllisesti, minkä jälkeen tietoa jaetaan kaikkien hyperparametrien välillä uuden hyperparametrien joukon haun ohjaamiseksi.

Tämä dokumentaatio painottuu Python-ohjelmointikieleen. Esittelemme tässä ohjelmistopaketteja, joilla on selkeämpi API, dokumentaatio ja jotka soveltuvat käyttöön CSC:n laskentaympäristössä.

Pakettiriippuvuuksien vuoksi sinun tulee ladata python-data-moduuli uusimmalla Python-versiolla:

module load python-data/3.9-1

Scikit-learn

Kun ruudukko- tai satunnaishaku on sopiva vaihtoehto hyperparametrien hakuun, Scikit-learn sisältää toteutukset sekä ruudukko- että satunnaishaulle ristivalidoinnilla. Ristivalidointi on oma mallinvalintaprosessinsa, ja se riippuu voimakkaasti käytettävissä olevan datan määrästä ja esimerkiksi käytettävien jakojen määrästä (jakojen määrä ja opetus-/testidatan jako ovat riippuvia muuttujia). Huomaa, että jos testaat suurta määrää mahdollisia malleja, vaarana on ylisovitettu malli.

# Scikit-learn 
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
hyperparams = { ... } # list of hyperparameters with their ranges and options

gridsearch   = GridSearchCV( model, hyperparams, ... )

... = # Define data splits

gridsearch.fit( Xtrain, ytrain )

Optuna

Optuna on mallista riippumaton kirjasto hyperparametrien hakuun. Ruudukko- ja satunnaishaun lisäksi Optuna toteuttaa Tree-structured Parzen estimator- ja CMA-ES-näytteenottomenetelmät hyperparametrien hakuun, ja lisäksi voit toteuttaa omia mukautettuja näytteenottomenetelmiäsi. Haun tehostamiseksi Optunalla voidaan tehdä monitarkkuushakua, jossa Median tai Threshold toimii lisäkarsintavaihtoehtona hakuavaruudessa.

# Optuna
import optuna
model       = ... # Define model
hyperparams = { ... }

gridsearch = optuna.create_study( sampler = optuna.samplers.GridSampler( params ) )
gridsearch.optimize( model )

Scikit-optimize

Scikit-optimize toteuttaa mukautuvia hakustrategioita ja on rakennettu scikit-learnin päälle. Tämä tekee siitä helpon toteuttaa suoraan scikit-learnilla rakennettujen mallien yhteyteen.

# Scikit-optimize using Scikit-learn models
from sklearn.ensemble import GradientBoostingClassifier
model = GradientBoostingClassifier()  # Define GradientBoosting

from skopt.space import Real, Integer
from skopt.utils import use_name_args

hyperparams = [ Integer( 1, 5, name = 'max_depth' ),
                Real( 10 ** -5, 10 ** 0, 'log-uniform', name = 'learning_rate' ) 
              ]

@used_named_args( space )
def objective( **hyperparams ):
    model.set_params( **hyperparams )
    return -( np.mean( cross_val_score( model, X, y, cv = 3, n_jobs = -1, scoring = 'neg_mean_absolute_error' ) )

# Execute Gaussian Process
from skopt import gp_minimize

model_gp = gp_minimize( objective, hyperparams, n_class = 50, random_state = 123 )

Ray

Jos haluat mahdollistaa rinnakkaisen mallinvalinnan, Ray tarjoaa tehokkaita kääreitä useille Python-paketeille. Jos tarvitset paketteja, jotka eivät sisälly python-data-moduuliin, käytä komentoa

pip install --user <package-name>
Jos haluat käyttää Rayta scikit-learnilla rakennettujen mallien rinnakkaistamiseen, helpoin tapa on käyttää tune-sklearn-pakettia. Tune-sklearnilla saat paremman rinnakkaistussuorituskyvyn Rayn avulla sen sijaan, että käyttäisit n_jobs = -1 -argumenttia GridSearchCV- tai RandomizedSearchCV-funktioissa. Tässä on esimerkki TuneGridSearchCV:n käytöstä scikit-learnilla rakennettujen mallien kanssa:

from ray.tune.sklearn import TuneGridSearchCV

from sklearn.linear_model import SGDClassifier


model               = SGDClassifier()
hyperparameter_grid = { "loss": [ 'hinge', 'log', 'modified_huber', 'squared_hinge', 'perceptron' ],
                        "max_iter": [ 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 ],
                        "n_iter_no_change": [ 5, 10, 15, 25, 40, 60 ] 
                      }

tune_search = TuneGridSearchCV( model, hyperparameter_grid, early_stopping = True, max_iters = 10, 
                                use_gpu = False, n_jobs = -1 )

... # Do your data split into train, validation and test sets
tune_search.fit( Xtrain, ytrain )
print( tune_search.best_params_ )
On suositeltavaa käyttää ruudukossa paljon hyperparametrivaihtoehtoja, jotta Rayn rinnakkaisuudesta saadaan hyöty irti. Jos kokeiltavia hyperparametreja on vain pieni joukko, käytä scikit-learnin tarjoamia menetelmiä.

TuneSearchCV-funktio mahdollistaa satunnais- ja mukautuvan haun käytön. Vaihtaaksesi mukautuvaan hakuun muuta search_optimization-argumenttia. Oletuksena TuneSearchCV käyttää satunnaishakua. Kiinteän hyperparametrijoukon sijaan käytä sopivia vaihteluvälejä Numpyn tai Scipyn funktioilla. Huomaa, että eri search_optimization-argumentit voivat aiheuttaa pakettiriippuvuuksia, jotka sinun on asennettava, jos ne puuttuvat.

from ray.tune.sklearn import TuneSearchCV 
hyperparameter_grid = { ... } # Set hyperparameter ranges

# Randomized search
tune_randomized = TuneSearchCV( model, hyperparameter_grid, early_stopping = True, 
                                    search_optimization = 'random',
                                    max_iters = 10, use_gpu = False, n_jobs = -1 )

tune_bayes      = TuneSearchCV( model, hyperparameter_grid, early_stopping = True, 
                                    search_optimization = 'bayesian',
                                    max_iters = 10, use_gpu = False, n_jobs = -1 )

Esimerkki CSC:n supertietokoneilla

Tässä on esimerkkitapauksia mallinvalinnan tekemisestä Puhdissa ja Mahdissa. Muista määrittää CPU-ytimien määrä eksplisiittisesti Puhdissa. Mahdissa, kun varaat solmun, varaat automaattisesti CPU-ytimien enimmäismäärän. Tarkista myös dokumentaatiosta käytettävät osionimet sekä Puhdissa että Mahdissa.

# example-slurm.sh
#!/bin/bash
#SBATCH --partition=small
#SBATCH --nodes=1
#SBATCH --time=10:00:00
#SBATCH --ntasks=1
#SBATCH --mem=64G
#SBATCH --cpus-per-task=40
#SBATCH --account=projectname

module load python-data/3.9-1

set -xv
python3 $*
# hyperparameter_example.py
from ray.tune.sklearn import TuneGridSearchCV
from sklearn.linear_model import SGDClassifier


model               = SGDClassifier()
hyperparameter_grid = { "loss": [ 'hinge', 'log', 'modified_huber', 'squared_hinge', 'perceptron' ],
                        "max_iter": [ 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 ],
                        "n_iter_no_change": [ 5, 10, 15, 25, 40, 60 ] 
                      }

tune_search = TuneGridSearchCV( model, hyperparameter_grid, early_stopping = True, max_iters = 10, 
                                use_gpu = False, n_jobs = -1 )

X, y = load_digits(n_class=10, return_X_y=True)

Xtrain, Xtest, ytrain, ytest = train_test_split( X, y, train_size = 0.90, test_size = .1, random_state = 0 ) # Split chosen arbitrarily

tune_search.fit( Xtrain, ytrain )
print( tune_search.best_params_ )
print( tune_search.best_score_ )
print( tune_search.score( Xtest, ytest ) )
sbatch example-slurm.sh hyperparameter_example.py 

Lisää esimerkkejä

Lisää esimerkkejä löytyy osoitteesta https://github.com/bilbrait/ml-guide-examples.

Suomenkielinen tekoälykäännös

Sisällössä voi esiintyä virheellistä tietoa tekoälykäännöksestä johtuen.

Klikkaa tästä antaaksesi palautetta