To timer senere og stadig kører? Sådan holder du din sklearn.fit under kontrol.

Skrevet af Gabriel Lerner og Nathan Toubiana

Alt hvad du ønskede at gøre var at teste din kode, men to timer senere viser din Scikit-learning pasform intet tegn på nogensinde efterbehandling. Scitime er en pakke, der forudsiger køretid for maskinlæringsalgoritmer, så du ikke bliver fanget af en uendelig pasform.

Uanset om du er i færd med at opbygge en maskinlæringsmodel eller implementere din kode til produktion, er viden om, hvor lang tid din algoritme tager at passe, nøglen til at strømline din arbejdsgang. Med Scitime vil du i løbet af få sekunder kunne estimere, hvor lang tid pasformen skal tage for de mest anvendte Scikit Learn-algoritmer.

Der er blevet offentliggjort et par forskningsartikler (som denne) om dette emne. Så vidt vi ved, er der imidlertid ingen praktisk implementering af det. Målet her er ikke at forudsige algoritmens nøjagtige driftstid, men mere at give en grov tilnærmelse.

Hvad er Scitime?

Scitime er en pythonpakke, der mindst kræver python 3.6 med pandaer, scikit-learning, psutil og joblib afhængigheder. Du finder Scitime repo her.

Hovedfunktionen i denne pakke kaldes " tid ". Givet en matrixvektor X, den estimerede vektor Y sammen med den Scikit Learn-model, du vælger, vil tiden udsende både den estimerede tid og dens konfidensinterval. Pakken understøtter i øjeblikket følgende Scikit Learn-algoritmer med planer om at tilføje flere i den nærmeste fremtid:

  • KMeans
  • RandomForestRegressor
  • SVC
  • RandomForestClassifier

Hurtig start

Lad os installere pakken og køre det grundlæggende.

Opret først en ny virtualenv (dette er valgfrit for at undgå enhver versionskonflikt!)

❱ virtualenv env❱ source env/bin/activate

og løb derefter:

❱ (env) pip install scitime

eller med conda:

❱ (env) conda install -c conda-forge scitime

Når installationen er lykkedes, er du klar til at estimere tidspunktet for din første algoritme.

Lad os sige, at du for eksempel ønskede at træne en kmeans-klynge. Du bliver først nødt til at importere scikit-learning-pakken, indstille kmeans-parametrene og også vælge input (også kaldet X) , her genereret tilfældigt for enkelhedens skyld.

At køre dette, før du udfører den egentlige pasform, vil give en tilnærmelse af køretiden:

Som du kan se, kan du kun få denne info i en ekstra kodelinje! Indgangene på tid funktion er præcis, hvad der er nødvendigt for at køre pasform (som er den algo selv, og X), hvilket gør det endnu nemmere at bruge.

Når man ser nærmere på den sidste linje i ovenstående kode, er den første output ( estimering: 15 sekunder i dette tilfælde) den forudsagte køretid, du leder efter. Scitime vil også sende det med et konfidensinterval ( nedre og øvre: 10 og 30 sekunder i dette tilfælde). Du kan altid sammenligne det med den faktiske træningstid ved at løbe:

I dette tilfælde er estimatet på vores lokale maskine 15 sekunder, mens den faktiske træningstid er 20 sekunder (men du får muligvis ikke de samme resultater, som vi vil forklare senere).

Som en hurtig brugsanvisning:

Estimator (meta_algo, detaljeret, tillid) klasse:

  • meta_algo : Estimatoren bruges til at forudsige klokkeslættet, enten 'RF' eller 'NN' (se detaljer i næste afsnit) - som standard 'RF'
  • verbose : Kontrol af mængden af ​​logoutput (enten 0, 1, 2 eller 3) - er som standard 0
  • tillid : Tillid til intervaller - standard er 95%

estimator.time (algo, X, y) funktion:

  • algo : algo hvis køretid brugeren ønsker at forudsige
  • X : følelsesløs række af input, der skal trænes
  • y : følelsesløs række af output, der skal trænes (indstillet til Ingen, hvis algo ikke overvåges)

Hurtig note: For at undgå enhver forvirring er det værd at fremhæve, at algo og meta_algo er to forskellige ting her: algo er den algoritme, hvis kørselstid vi vil estimere, meta_algo er den algoritme, som Scitime bruger til at forudsige kørselstiden.

Hvordan Scitime fungerer

Vi er i stand til at forudsige kørselstiden ved at bruge vores egen estimator, vi kalder det metaalgoritme ( meta_algo ), hvis vægte er gemt i en dedikeret pickle-fil i pakkens metadata. For hver Scikit Learn-model finder du en tilsvarende meta algo pickle-fil i Scitimes kodebase.

Du tænker måske:

Hvorfor ikke manuelt estimere tidskompleksiteten med store O-notationer?

Det er et rimeligt punkt. Det er en gyldig måde at nærme sig problemet på og noget, vi tænkte på i starten af ​​projektet. En ting er dog, at vi bliver nødt til at formulere kompleksiteten eksplicit for hver algo og sæt af parametre, hvilket i nogle tilfælde er ret udfordrende i betragtning af antallet af faktorer, der spiller en rolle i løbetiden. Meta_algo gør stort set alt arbejdet for dig, og vi forklarer hvordan.

To typer metaalger er blevet trænet til at estimere den tid, der passer (begge fra Scikit Learn):

  • Den RF meta algo, en RandomForestRegressor estimator.
  • Den NN meta algo, en grundlæggende MLPRegressor estimator.

Disse meta algos estimerer den tid, det passer til, ved hjælp af en række 'meta'-funktioner. Her er et resumé af, hvordan vi bygger disse funktioner:

For det første henter vi formen på din inputmatrix X og outputvektoren y. For det andet tages de parametre, du tilfører til Scikit Learn-modellen, i betragtning, da de også vil påvirke træningstiden. Endelig overvejes også din specifikke hardware, unik for din maskine, såsom tilgængelig hukommelse og cpu-tællinger.

Som vist tidligere giver vi også tillidsintervaller på tidsforudsigelsen. Den måde, hvorpå disse beregnes, afhænger af den valgte meta algo:

  • For RF , da enhver tilfældig skovregressor er en kombination af flere træer (også kaldet estimatorer ), vil konfidensintervallet være baseret på fordelingen af ​​det sæt forudsigelser, der beregnes af hver estimator.
  • For NN er processen lidt mindre ligetil: vi beregner først et sæt MSE'er sammen med antallet af observationer på et testsæt, grupperet efter forudsagte varighedskasser (det vil sige fra 0 til 1 sekund, 1 til 5 sekunder og så on), og vi beregner derefter en t-stat for at få estimeringens nedre og øvre grænse. Da vi ikke har mange data for meget lange modeller, kan konfidensintervallet for sådanne data blive meget bredt.

Hvordan vi byggede det

Du tænker måske:

Hvordan fik du nok data om træningstiden for alle disse sciki-læringspasninger over forskellige parametre og hardwarekonfigurationer?

Det (ikke-glamourøse) svar er, at vi selv genererede dataene ved hjælp af en kombination af computere og VM-hardwares til at simulere, hvad træningstiden ville være på de forskellige systemer. Vi monterede derefter vores metaalger på disse tilfældigt genererede datapunkter for at opbygge en estimator, der var beregnet til at være pålidelig uanset dit system.

Mens estimatet.py-filen håndterer forudsigelsen af ​​runtime, hjalp filen _model.py os med at generere data til at træne vores meta algos ved hjælp af vores dedikerede modelklasse . Her er en tilsvarende kodeeksempel for kmeans:

Bemærk, at du også kan bruge filen _data.py direkte med kommandolinjen til at generere data eller træne en ny model. Relaterede instruktioner kan findes i repo-Readme-filen.

Når du genererer datapunkter, kan du redigere parametrene for de Scikit Learn-modeller, du vil træne på. Du kan gå til scitime / _config.json og redigere parametrene for modellerne samt antallet af rækker og kolonner, du gerne vil træne med.

Vi bruger en itertool-funktion til at løbe igennem alle mulige kombinationer sammen med en faldhastighed indstillet mellem 0 og 1 for at kontrollere, hvor hurtigt sløjfen springer gennem de forskellige mulige iterationer.

Hvor nøjagtig er Scitime?

Nedenfor fremhæver vi, hvordan vores forudsigelser fungerer for det specifikke tilfælde af kmeans. Vores genererede datasæt indeholder ~ 100.000 datapunkter, som vi deler i et tog og testsæt (75% - 25%).

Vi grupperede træningsprognoser med forskellige tidsspande og beregnet MAPE og RMSE over hver af disse spande til alle vores estimatorer ved hjælp af RF meta-algo og NN meta-algo.

Bemærk, at disse resultater blev udført på et begrænset datasæt, så de kan være forskellige på uudforskede datapunkter (såsom andre systemer / ekstreme værdier for visse modelparametre). For dette specifikke træningssæt er R-kvadratet omkring 80% for NN og 90% for RF.

Som vi kan se, er det ikke overraskende, at nøjagtigheden konstant er højere på togsættet end på testen for både NN og RF. Vi ser også, at RF ser ud til at fungere bedre end NN generelt. MAPE for RF er omkring 20% ​​på togsættet og 40% på testsættet. NN MAPE er overraskende meget høj.

Lad os skære MAPE (på testsæt) efter antallet af forudsagte sekunder:

En vigtig ting at huske på er, at tidsforudsigelsen i nogle tilfælde er følsom over for den valgte meta algo (RF eller NN). Efter vores erfaring har RF klaret sig meget godt inden for datasættets inputområder som vist ovenfor. For punkter uden for rækkevidde kan NN dog klare sig bedre, som foreslået i slutningen af ​​ovenstående diagram. Dette ville forklare, hvorfor NN MAPE er ret høj, mens RMSE er anstændigt: det fungerer dårligt på små værdier.

For eksempel, hvis du forsøger at forudsige kørselstiden for en kmeans med standardparametre og med en inputmatrix på et par tusinde linjer, vil RF-meta algo være præcis, fordi vores træningsdatasæt indeholder lignende datapunkter. For at forudsige meget specifikke parametre (for eksempel et meget højt antal klynger) fungerer NN muligvis bedre, fordi det ekstrapolerer fra træningssættet, mens RF ikke gør det. NN klarer sig dårligere på ovenstående diagrammer, fordi disse plot kun er baseret på data tæt på sæt af input til træningsdataene.

Som vist i denne graf ekstrapoleres værdierne uden for området (tynde linjer) imidlertid af NN-estimatoren, mens RF-estimatoren forudsiger output trinvis.

Lad os nu se på de vigtigste 'meta'-funktioner til eksemplet på kmeans:

Som vi kan se, tegner kun 6 funktioner sig for mere end 80% af modelvariansen. Blandt dem er det vigtigste en parameter i selve scikit-lær kmeans-klassen (antal klynger), men mange eksterne faktorer har stor indflydelse på køretiden, såsom antal rækker / kolonner og tilgængelig hukommelse.

Begrænsninger

Som nævnt tidligere er den første begrænsning relateret til konfidensintervallerne: de kan være meget brede, især for NN og for tunge modeller (det ville tage mindst en time).

Derudover fungerer NN muligvis dårligt på små til mellemstore forudsigelser. Nogle gange forudsiger NN endda i små varigheder endda en negativ varighed, i hvilket tilfælde vi automatisk skifter tilbage til RF.

En anden begrænsning af estimatoren opstår, når der anvendes 'specielle' algo-parameterværdier. For eksempel i et RandomForest-scenarie, når max_depth er indstillet til Ingen , kan dybden tage enhver værdi. Dette kan resultere i en meget længere tid til at passe, hvilket er sværere for meta algo at hente, selvom vi gjorde vores bedste for at redegøre for dem.

Når du kører estimator.time (algo, X, y) , kræver vi, at brugeren indtaster den faktiske X- og y-vektor, som synes unødvendig, da vi simpelthen kunne anmode formen på dataene for at estimere træningstiden. Årsagen til dette er, at vi faktisk prøver at tilpasse modellen, inden vi forudsiger kørselstiden, for at rejse øjeblikkelige fejl. Vi kører algo.fit (X, y) i et underproces i et sekund for at kontrollere, om der er en fit-up, hvorefter vi går videre til forudsigelsesdelen. Der er dog tidspunkter, hvor algo (og / eller inputmatrixen) er så store, at kørsel af algo.fit (X, y) i sidste ende vil kaste en hukommelsesfejl, som vi ikke kan tage højde for.

Fremtidige forbedringer

Den mest effektive og åbenlyse måde at forbedre ydeevnen på vores nuværende forudsigelser på ville være at generere flere datapunkter på forskellige systemer for bedre at understøtte en bred vifte af hardware / parametre.

Vi vil se på at tilføje flere understøttede Scikit Learn algos i den nærmeste fremtid. Vi kunne også implementere andre algos som lightGBM eller xgboost. Du er velkommen til at kontakte os, hvis der er en algoritme, som du gerne vil have os til at implementere i de næste iterationer af Scitime!

Andre interessante veje til forbedring af estimatorens ydeevne ville være at inkludere mere detaljeret information om inputmatrixen, såsom varians eller korrelation med output. Vi genererer i øjeblikket data helt tilfældigt, for hvilke tilpasningstiden kan være højere end for datasæt i den virkelige verden. Så i nogle tilfælde overvurderer det måske træningstiden.

Derudover kunne vi spore finere hardwarespecifikke oplysninger, såsom frekvensen af ​​cpu'en eller den aktuelle cpu-brug.

Ideelt set, da algoritmen kan skifte fra en scikit-lær-version til en anden og således have en indvirkning på køretiden, ville vi også tage højde for den, for eksempel ved at bruge versionen som en 'meta'-funktion.

Efterhånden som vi erhverver flere data, der passer til vores meta algos, kan vi tænke på at bruge mere komplekse meta algos, såsom sofistikerede neurale netværk (ved hjælp af reguleringsteknikker som dropout eller batch normalisering). Vi kunne endda overveje at bruge tensorflow til at passe til meta algo (og tilføje det som valgfrit): det ville ikke kun hjælpe os med at få en bedre nøjagtighed, men også opbygge mere robuste tillidsintervaller ved hjælp af dropout.

Bidrage til Scitime og sende os din feedback

For det første værdsættes enhver form for feedback, især om udførelsen af ​​forudsigelserne og ideer til at forbedre denne proces til generering af data!

Som diskuteret før kan du bruge vores repo til at generere dine egne datapunkter for at træne din egen meta-algoritme. Når du gør det, kan du hjælpe med at gøre Scitime bedre ved at dele dine datapunkter, der findes i resultatet csv ( ~ / scitime / scitime / [algo] _results.csv ), så vi kan integrere det i vores model.

For at generere dine egne data kan du køre en kommando svarende til denne (fra pakken repokilde):

❱ python _data.py --verbose 3 --algo KMeans --drop_rate 0.99

Bemærk: Hvis køres direkte med koden kilde (med model klasse), så glem ikke at sæt write_csv til sand, ellers de genererede datapunkter vil ikke blive gemt.

Vi bruger GitHub-problemer til at spore alle fejl og funktionsanmodninger. Du er velkommen til at åbne et problem, hvis du har fundet en fejl eller ønsker at se en ny funktion implementeret. Mere info kan findes om, hvordan man bidrager i den scitime repo.

For problemer med forudsigelse af træningstiden, når du sender feedback, inklusive den fulde ordbog over parametre, du passer ind i din model, kan det hjælpe, så vi kan diagnosticere, hvorfor ydeevnen er mindre end din specifikke brugssag. For at gøre det skal du blot indstille den detaljerede parameter til 3 og kopiere og indsætte loggen for parameter dic i beskrivelsen af ​​problemet.

Find kodekilden

Find dokumentationen

Kreditter

  • Gabriel Lerner & Nathan Toubiana er de vigtigste bidragydere til denne pakke og medforfattere til denne artikel
  • Særlig tak til Philippe Mizrahi for at hjælpe på vejen
  • Tak for al den hjælp, vi fik fra tidlige anmeldelser / beta-test