Scikit-Learn Tutorial: Hvordan installere og Scikit-Learn eksempler
โก Smart oppsummering
Scikit-learn er รฅpen kildekode Python bibliotek som dekker forprosessering, klassifisering, regresjon, klynging og modellvalg bak et enkelt konsistent estimatorgrensesnitt, som holder en komplett maskinlรฆringsarbeidsflyt kort, lesbar og reproduserbar fra rรฅdata til scorede prediksjoner.
Hva er Scikit-learn?
Scikit lรฆre er en รฅpen kildekode Python bibliotek for maskinlรฆringDen stรธtter veletablerte algoritmer som KNN, gradient boosting, random forest og SVM, og den er bygget pรฅ toppen av nusset og SciPy. Scikit-learn er mye brukt i Kaggle-konkurranser sรฅ vel som i fremtredende teknologiselskaper. Det dekker forprosessering, dimensjonalitetsreduksjon, klassifisering, regresjon, klynging og modellvalg.
Scikit-learn har noe av den beste dokumentasjonen av alle รฅpen kildekode-biblioteker. Det tilbyr til og med et interaktivt estimatordiagram, Velge riktig estimator, som veileder deg fra stรธrrelsen pรฅ datasettet ditt til en kortliste over algoritmer som er verdt รฅ prรธve.
Figuren nedenfor illustrerer hvordan Scikit-learn fungerer.
Scikit-learn er ikke vanskelig รฅ bruke og gir utmerkede resultater. Den trener imidlertid pรฅ CPU-en: arbeidet paralleliseres pรฅ tvers av kjerner med n_jobs-argumentet i stedet for pรฅ et GPU. ร kjรธre en dyp lรฆringsalgoritme med den er mulig, men sjelden optimalt, spesielt hvis du allerede vet hvordan du bruker den. tensorflow.
Hvordan laste ned og installere Scikit-learn
Nรฅ i dette Python Scikit-learn-veiledningen, du lรฆrer hvordan du laster ned og installerer Scikit-learn:
Alternativ 1: AWS
Scikit-learn kan brukes over AWS. Et Docker-image med scikit-learn forhรฅndsinstallert sparer oppsettarbeidet fullstendig.
For รฅ installere utviklerversjonen, kjรธr kommandoen nedenfor Jupyter:
import sys !{sys.executable} -m pip install git+git://github.com/scikit-learn/scikit-learn.git
Alternativ 2: Mac eller Windows bruker Anaconda
For รฅ lรฆre mer om installasjon av Anaconda, se hvordan laste ned og installere TensorFlow.
Da denne gjennomgangen ble skrevet, hadde utviklerne av scikit gitt ut en utviklingsversjon som lรธste problemer som var tilstede i den davรฆrende gjeldende utgivelsen, sรฅ trinnene nedenfor bruker den utviklerversjonen. Pรฅ en ny maskin i dag inneholder den nรฅvรฆrende stabile utgivelsen allerede alle transformatorene som brukes her, og pip install -U scikit-learn er nok.
Hvordan installere scikit-learn med Conda Environment
Hvis du installerte scikit-learn med conda-miljรธet, fรธlg trinnene nedenfor for รฅ oppdatere til versjon 0.20.
Trinn 1) Aktiver tensorflow-miljรธet
source activate hello-tf
Trinn 2) Fjern scikit-learn ved hjelp av conda-kommandoen
conda remove scikit-learn
Trinn 3) Installer utviklerversjonen
Installer utviklerversjonen av scikit-learn sammen med de nรธdvendige bibliotekene.
conda install -c anaconda git
pip install Cython
pip install h5py
pip install git+git://github.com/scikit-learn/scikit-learn.git
NOTAT: Windows brukerne trenger Microsoft Visual C++ 14. Du kan fรฅ det her..
Scikit-Learn-eksempel med maskinlรฆring
Denne Scikit-opplรฆringen er delt inn i to deler:
- Maskinlรฆring med scikit-learn
- Hvordan stole pรฅ modellen din med LIME
Den fรธrste delen beskriver hvordan man bygger en pipeline, lager en modell og finjusterer hyperparametrene, mens den andre delen dekker modelltolkning.
Trinn 1) Importer dataene
I lรธpet av denne Scikit Learn-opplรฆringen skal du bruke datasettet for voksne.
Filen leses direkte fra UCI Machine Learning Repository i koden nedenfor, sรฅ ingen manuell nedlasting er nรธdvendig. Hvis du er interessert i beskrivende statistikk, er Dive- og Overview-verktรธyene verdt รฅ ta en titt pรฅ. Se denne opplรฆringen for รฅ lรฆre mer om Dykk og Oversikt.
Du importerer datasettet med pandas. Merk at du mรฅ konvertere de kontinuerlige variablene til flyttallformat.
Dette datasettet inneholder รฅtte kategoriske variabler, oppfรธrt i CATE_FEATURES:
- arbeidsklasse
- utdanning
- ekteskapelig
- okkupasjon
- forholdet
- rase
- kjรธnn
- native_country
Den inkluderer ogsรฅ seks kontinuerlige variabler, oppfรธrt i CONTI_FEATURES:
- alder
- fnlwgt
- utdanning_nummer
- kapitalgevinst
- kapitaltap
- timer_uke
Listene fylles ut for hรฅnd her, slik at du fรฅr en klarere oversikt over hvilke kolonner som er i spill. En raskere mรฅte รฅ bygge en liste med kategoriske eller kontinuerlige kolonner pรฅ er:
## List Categorical CATE_FEATURES = df_train.iloc[:,:-1].select_dtypes('object').columns print(CATE_FEATURES) ## List continuous CONTI_FEATURES = df_train._get_numeric_data() print(CONTI_FEATURES)
Her er koden for รฅ importere dataene:
# Import dataset import pandas as pd ## Define path data COLUMNS = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country', 'label'] ### Define continuous list CONTI_FEATURES = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week'] ### Define categorical list CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country'] ## Prepare the data features = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country'] PATH = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data" df_train = pd.read_csv(PATH, skipinitialspace=True, names = COLUMNS, index_col=False) df_train[CONTI_FEATURES] =df_train[CONTI_FEATURES].astype('float64') df_train.describe()
ร kalle describe() pรฅ rammen returnerer sammendragsstatistikken for de seks sammenhengende kolonnene:
| alder | fnlwgt | utdanning_nummer | kapitalgevinst | kapitaltap | timer_uke | |
|---|---|---|---|---|---|---|
| telle | 32561.000000 | 3.256100e + 04 | 32561.000000 | 32561.000000 | 32561.000000 | 32561.000000 |
| bety | 38.581647 | 1.897784e + 05 | 10.080679 | 1077.648844 | 87.303830 | 40.437456 |
| std | 13.640433 | 1.055500e + 05 | 2.572720 | 7385.292085 | 402.960219 | 12.347429 |
| minutter | 17.000000 | 1.228500e + 04 | 1.000000 | 0.000000 | 0.000000 | 1.000000 |
| 25% | 28.000000 | 1.178270e + 05 | 9.000000 | 0.000000 | 0.000000 | 40.000000 |
| 50% | 37.000000 | 1.783560e + 05 | 10.000000 | 0.000000 | 0.000000 | 40.000000 |
| 75% | 48.000000 | 2.370510e + 05 | 12.000000 | 0.000000 | 0.000000 | 45.000000 |
| max | 90.000000 | 1.484705e + 06 | 16.000000 | 99999.000000 | 4356.000000 | 99.000000 |
Du kan sjekke antallet unike verdier for native_country-funksjonen. Bare รฉn husstand kommer fra Holland, Nederland. Den husstanden gir ingen informasjon og vil gi en feilmelding under trening.
df_train.native_country.value_counts()
United-States 29170 Mexico 643 ? 583 Philippines 198 Germany 137 Canada 121 Puerto-Rico 114 El-Salvador 106 India 100 Cuba 95 England 90 Jamaica 81 South 80 China 75 Italy 73 Dominican-Republic 70 Vietnam 67 Guatemala 64 Japan 62 Poland 60 Columbia 59 Taiwan 51 Haiti 44 Iran 43 Portugal 37 Nicaragua 34 Peru 31 France 29 Greece 29 Ecuador 28 Ireland 24 Hong 20 Cambodia 19 Trinadad&Tobago 19 Thailand 18 Laos 18 Yugoslavia 16 Outlying-US(Guam-USVI-etc) 14 Honduras 13 Hungary 13 Scotland 12 Holand-Netherlands 1 Name: native_country, dtype: int64
Du kan ekskludere denne uinformative raden fra datasettet:
## Drop Netherland, because only one row df_train = df_train[df_train.native_country != "Holand-Netherlands"]
Deretter lagrer du posisjonen til de kontinuerlige funksjonene i en liste. Du trenger det i neste trinn for รฅ bygge rรธrledningen.
Koden nedenfor gรฅr over alle kolonnenavnene i CONTI_FEATURES, leser hver plassering (det vil si kolonnenummeret) og legger den til i en liste kalt conti_features.
## Get the column index of the categorical features conti_features = [] for i in CONTI_FEATURES: position = df_train.columns.get_loc(i) conti_features.append(position) print(conti_features)
[0, 2, 10, 4, 11, 12]
Den neste blokken gjรธr den samme jobben for de kategoriske variablene.
## Get the column index of the categorical features categorical_features = [] for i in CATE_FEATURES: position = df_train.columns.get_loc(i) categorical_features.append(position) print(categorical_features)
[1, 3, 5, 6, 7, 8, 9, 13]
Se nรฅ pรฅ selve datasettet. Hvert kategorisk trekk er en streng, og en modell kan ikke mates med en strengverdi, sรฅ datasettet mรฅ transformeres med dummyvariabler.
df_train.head(5)
Faktisk trenger du รฉn kolonne for hver gruppe i hver funksjon. Kjรธr fรธrst koden nedenfor for รฅ beregne det totale antallet kolonner som trengs.
print(df_train[CATE_FEATURES].nunique(), 'There are',sum(df_train[CATE_FEATURES].nunique()), 'groups in the whole dataset')
workclass 9
education 16
marital 7
occupation 15
relationship 6
race 5
sex 2
native_country 41
dtype: int64 There are 101 groups in the whole dataset
Hele datasettet inneholder 101 grupper, som vist ovenfor. Arbeidsklassefunksjonen alene har ni grupper. Du kan liste opp navnene pรฅ gruppene med koden nedenfor; unique() returnerer de distinkte verdiene for hver kategoriske funksjon.
for i in CATE_FEATURES: print(df_train[i].unique())
['State-gov' 'Self-emp-not-inc' 'Private' 'Federal-gov' 'Local-gov' '?' 'Self-emp-inc' 'Without-pay' 'Never-worked'] ['Bachelors' 'HS-grad' '11th' 'Masters' '9th' 'Some-college' 'Assoc-acdm' 'Assoc-voc' '7th-8th' 'Doctorate' 'Prof-school' '5th-6th' '10th' '1st-4th' 'Preschool' '12th'] ['Never-married' 'Married-civ-spouse' 'Divorced' 'Married-spouse-absent' 'Separated' 'Married-AF-spouse' 'Widowed'] ['Adm-clerical' 'Exec-managerial' 'Handlers-cleaners' 'Prof-specialty' 'Other-service' 'Sales' 'Craft-repair' 'Transport-moving' 'Farming-fishing' 'Machine-op-inspct' 'Tech-support' '?' 'Protective-serv' 'Armed-Forces' 'Priv-house-serv'] ['Not-in-family' 'Husband' 'Wife' 'Own-child' 'Unmarried' 'Other-relative'] ['White' 'Black' 'Asian-Pac-Islander' 'Amer-Indian-Eskimo' 'Other'] ['Male' 'Female'] ['United-States' 'Cuba' 'Jamaica' 'India' '?' 'Mexico' 'South' 'Puerto-Rico' 'Honduras' 'England' 'Canada' 'Germany' 'Iran' 'Philippines' 'Italy' 'Poland' 'Columbia' 'Cambodia' 'Thailand' 'Ecuador' 'Laos' 'Taiwan' 'Haiti' 'Portugal' 'Dominican-Republic' 'El-Salvador' 'France' 'Guatemala' 'China' 'Japan' 'Yugoslavia' 'Peru' 'Outlying-US(Guam-USVI-etc)' 'Scotland' 'Trinadad&Tobago' 'Greece' 'Nicaragua' 'Vietnam' 'Hong' 'Ireland' 'Hungary']
Treningsdatasettet vil derfor inneholde 101 + 6 kolonner: gruppene med รฉn aktiv funksjon pluss de seks kontinuerlige funksjonene.
Scikit-learn kan ta seg av konverteringen i to trinn:
- Konverter strengen til en ID. State-gov blir ID 1, Self-emp-not-inc blir ID 2 og sรฅ videre. LabelEncoder gjรธr dette for deg.
- Transponer hver ID til en ny kolonne. Datasettet har 101 gruppe-ID-er, sรฅ det vil vรฆre 101 kolonner som fanger opp hver kategoriske funksjonsgruppe. Scikit-learn tilbyr OneHotEncoder for denne operasjonen.
Trinn 2) Lag toget/testsettet
Nรฅ som datasettet er klart, del det 80/20: 80 prosent for treningssettet og 20 prosent for testsettet.
Du kan bruke train_test_split. Det fรธrste argumentet er datarammen til funksjonene, og det andre er etiketten. Du angir stรธrrelsen pรฅ testsettet med test_size.
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(df_train[features], df_train.label, test_size = 0.2, random_state=0) X_train.head(5) print(X_train.shape, X_test.shape)
(26048, 14) (6512, 14)
Trinn 3) Bygg rรธrledningen
Pipelinen gjรธr det enklere รฅ mate modellen med konsistente data. Tanken er รฅ sende rรฅdataene gjennom ett objekt som utfรธrer hver operasjon i rekkefรธlge.
Med dette datasettet mรฅ du standardisere de kontinuerlige variablene og konvertere de kategoriske. Enhver operasjon kan ligge i en pipeline: manglende verdier kan erstattes med gjennomsnittet eller medianen, og nye variabler kan opprettes.
Du har et valg: hardkode de to prosessene, eller bygge en pipeline. Hardkoding kan lekke testdata inn i den tilpassede statistikken og skape inkonsekvenser over tid, sรฅ pipeline er det bedre alternativet.
from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoder from sklearn.compose import ColumnTransformer, make_column_transformer from sklearn.pipeline import make_pipeline from sklearn.linear_model import LogisticRegression
Rรธrledningen utfรธrer to operasjoner fรธr den mater den logistiske klassifikatoren:
- Standardiser variabelen: StandardScaler()
- Konverter de kategoriske funksjonene: OneHotEncoder(sparse=False)
Du utfรธrer begge trinnene med make_column_transformer. Da denne gjennomgangen ble skrevet, var ikke funksjonen i den utgitte versjonen av scikit-learn (0.19), og det er derfor utviklerversjonen ble brukt; den har blitt levert i alle stabile utgivelser siden 0.20.
make_column_transformer er enkel: du deklarerer hvilke kolonner som skal transformeres og hvilken transformasjon som skal brukes. For รฅ standardisere de kontinuerlige funksjonene sender du:
- conti_features, StandardScaler() inni make_column_transformer
- conti_features: listen over kontinuerlige kolonner
- StandardScaler: standardiserer disse kolonnene
OneHotEncoder-objektet i make_column_transformer koder etikettene automatisk.
preprocess = make_column_transformer(
(conti_features, StandardScaler()),
### Need to be numeric not string to specify columns name
(categorical_features, OneHotEncoder(sparse=False))
)
Versjonsmerknad: to argumenter i blokken ovenfor har flyttet seg. Nรฅvรฆrende utgivelser forventer transformatoren fรธrst og kolonnene deretter, og sparsom ble omdรธpt sparse_output i scikit-learn 1.2 og fjernet i 1.4, sรฅ nyere kode leses OneHotEncoder(sparse_output=False).
Du kan teste om pipelinen fungerer med fit_transform. Utdataene skal ha formen 26048, 107.
preprocess.fit_transform(X_train).shape
(26048, 107)
Datatransformatoren er klar. Du oppretter pipelinen med make_pipeline, og nรฅr dataene er transformert, mater du den logistiske regresjonen.
model = make_pipeline(
preprocess,
LogisticRegression())
Det er da trivielt รฅ trene en modell med scikit-learn: kall tilpasning pรฅ pipelinen. Du kan skrive ut nรธyaktigheten med score-metoden.
model.fit(X_train, y_train) print("logistic regression score: %f" % model.score(X_test, y_test))
logistic regression score: 0.850891
Til slutt kan du forutsi klassene med predict_proba, som returnerer sannsynligheten for hver klasse. Merk at de to sannsynlighetene summerer seg til รฉn.
model.predict_proba(X_test)
array([[0.83576663, 0.16423337],
[0.94582765, 0.05417235],
[0.64760587, 0.35239413],
...,
[0.99639252, 0.00360748],
[0.02072181, 0.97927819],
[0.56781353, 0.43218647]])
Trinn 4) Bruk av rรธrledningen vรฅr i et rutenettsรธk
ร justere hyperparametrene, verdiene som fikserer modellens struktur, kan vรฆre kjedelig og utmattende.
En mรฅte รฅ evaluere modellen pรฅ ville vรฆre รฅ endre stรธrrelsen pรฅ treningssettet og mรฅle ytelsen, og gjenta รธvelsen ti ganger for รฅ se spredningen av poengsummen. Det er mye manuelt arbeid.
I stedet tilbyr scikit-learn funksjoner som utfรธrer parameterjustering og kryssvalidering for deg.
Kryssvalidering
Kryssvalidering betyr at treningssettet deles n ganger i folder under trening, og modellen evalueres n ganger. Hvis cv settes til 10, trenes og evalueres modellen ti ganger. I hver runde trener klassifikatoren pรฅ ni tilfeldig valgte folder, og den tiende folden beholdes for evaluering.
Rutenettsรธk
Hver klassifikator har hyperparametere som skal finjusteres. Du kan prรธve verdier รฉn om gangen, eller angi et parameternett. Dokumentasjonen for scikit-learn viser alle parameterne den logistiske klassifikatoren godtar. For รฅ holde treningen rask, finjusterer dette eksemplet bare C-parameteren, som kontrollerer regularisering. Den mรฅ vรฆre positiv, og en liten verdi gir mer vekt til regularisatoren.
Du bruker GridSearchCV-objektet, som tar en ordbok med hyperparametrene for รฅ finjustere. List opp hver hyperparameter etterfulgt av verdiene du vil prรธve. For รฅ finjustere C skriver du:
- 'logisticregression__C': [0.001, 0.01, 0.1, 1.0] โ parameternavnet innledes av klassifikatornavnet med smรฅ bokstaver og to understrekninger.
Modellen vil prรธve fire forskjellige verdier: 0.001, 0.01, 0.1 og 1. Den er trent med 10 folder, det vil si cv=10.
from sklearn.model_selection import GridSearchCV # Construct the parameter grid param_grid = { 'logisticregression__C': [0.001, 0.01,0.1, 1.0], }
Du kan nรฅ trene modellen ved hjelp av GridSearchCV med parameterne grid og cv.
# Train the model grid_clf = GridSearchCV(model, param_grid, cv=10, iid=False) grid_clf.fit(X_train, y_train)
Utgang:
GridSearchCV(cv=10, error_score='raise-deprecating', estimator=Pipeline(memory=None, steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None, transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,...ty='l2', random_state=None, solver='liblinear', tol=0.0001, verbose=0, warm_start=False))]), fit_params=None, iid=False, n_jobs=1, param_grid={'logisticregression__C': [0.001, 0.01, 0.1, 1.0]}, pre_dispatch='2*n_jobs', refit=True, return_train_score='warn', scoring=None, verbose=0)
Versjonsmerknad: de iid Argumentet som er synlig i denne utdataen ble avskrevet i scikit-learn 0.22 og fjernet i 0.24, sรฅ det bรธr ganske enkelt fjernes fra GridSearchCV-kallet pรฅ nรฅvรฆrende versjoner.
For รฅ fรฅ tilgang til de beste parameterne bruker du best_params_.
grid_clf.best_params_
Utgang:
{'logisticregression__C': 1.0}
Etter รฅ ha trent modellen med fire forskjellige regulariseringsverdier, gir den optimale parameteren:
print("best logistic regression from grid search: %f" % grid_clf.best_estimator_.score(X_test, y_test))
beste logistiske regresjon fra rutenettsรธk: 0.850891
For รฅ fรฅ tilgang til de anslรฅtte sannsynlighetene:
grid_clf.best_estimator_.predict_proba(X_test)
array([[0.83576677, 0.16423323],
[0.9458291 , 0.0541709 ],
[0.64760416, 0.35239584],
...,
[0.99639224, 0.00360776],
[0.02072033, 0.97927967],
[0.56782222, 0.43217778]])
XGBoost-modell med scikit-learn
Prรธv nรฅ en av de sterkeste klassifikatorene pรฅ markedet. XGBoost er en gradientforsterkende forbedring av den tilfeldige skogen. Den teoretiske bakgrunnen er utenfor rammen av dette. Python Scikit-opplรฆringen, men husk at XGBoost har vunnet mange Kaggle-konkurranser. Pรฅ et datasett av gjennomsnittlig stรธrrelse kan den prestere like bra som en dyp lรฆringsalgoritme, eller bedre.
Klassifikatoren er utfordrende รฅ trene fordi den eksponerer et stort antall parametere. Du kan selvfรธlgelig bruke GridSearchCV til รฅ velge dem for deg.
Et bedre alternativ her er RandomizedSearchCV. GridSearchCV blir treg nรฅr rutenettet er stort, fordi sรธkeomrรฅdet vokser med hver parameter som legges til. RandomizedSearchCV sampler i stedet verdiene til hver hyperparameter tilfeldig pรฅ hver iterasjon, slik at 1,000 iterasjoner evaluerer 1,000 kombinasjoner. Det fungerer ellers omtrent som GridSearchCV.
Du mรฅ importere xgboost. Hvis biblioteket ikke er installert, kjรธr pip3 install xgboost, eller installer det fra innsiden av en Jupyter notatbok med:
use import sys
!{sys.executable} -m pip install xgboost
Importer deretter klassifikatoren og de to sรธkehjelperne:
import xgboost from sklearn.model_selection import RandomizedSearchCV from sklearn.model_selection import StratifiedKFold
Det neste trinnet i denne Scikit Python veiledningen gรฅr ut pรฅ รฅ spesifisere parameterne som skal finjusteres. Den offisielle XGBoost-dokumentasjonen lister dem alle opp. Av hensyn til dette Python I Sklearn-opplรฆringen velger du bare to hyperparametere med to verdier hver, fordi XGBoost tar lang tid รฅ trene og hvert ekstra gridpunkt รธker ventetiden.
params = {
'xgbclassifier__gamma': [0.5, 1],
'xgbclassifier__max_depth': [3, 4]
}
Deretter konstruerer du en ny pipeline med XGBoost-klassifikatoren og 600 estimatorer. n_estimators er i seg selv justerbar, og en hรธy verdi kan fรธre til overtilpasning. Du kan prรธve andre verdier, men vรฆr oppmerksom pรฅ at det kan ta timer. Alle andre parametere beholder standardverdien.
model_xgb = make_pipeline(
preprocess,
xgboost.XGBClassifier(
n_estimators=600,
objective='binary:logistic',
silent=True,
nthread=1)
)
Du kan forbedre kryssvalideringen med kryssvalidatoren Stratified K-Folds. Bare tre folder brukes her for รฅ รธke hastigheten pรฅ beregningen, noe som gรฅr utover kvaliteten. รk dette til 5 eller 10 pรฅ din egen maskin for bedre resultater. Modellen trenes over fire iterasjoner.
skf = StratifiedKFold(n_splits=3,
shuffle = True,
random_state = 1001)
random_search = RandomizedSearchCV(model_xgb,
param_distributions=params,
n_iter=4,
scoring='accuracy',
n_jobs=4,
cv=skf.split(X_train, y_train),
verbose=3,
random_state=1001)
Det randomiserte sรธket er klart, slik at du kan trene modellen.
#grid_xgb = GridSearchCV(model_xgb, params, cv=10, iid=False)
random_search.fit(X_train, y_train)
Fitting 3 folds for each of 4 candidates, totalling 12 fits
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8759645283888057, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8729701715996775, total= 1.0min
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8706519235199263, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8735460094437406, total= 1.3min
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8722791661868018, total= 57.7s
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8753886905447426, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8697304768486523, total= 1.3min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8740066797189912, total= 1.4min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8707671043538355, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8729701715996775, total= 1.2min
[Parallel(n_jobs=4)]: Done 10 out of 12 | elapsed: 3.6min remaining: 43.5s
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8736611770125533, total= 1.2min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8692697535130154, total= 1.2min
[Parallel(n_jobs=4)]: Done 12 out of 12 | elapsed: 3.6min finished /Users/Thomas/anaconda3/envs/hello-tf/lib/python3.6/site-packages/sklearn/model_selection/_search.py:737: DeprecationWarning: The default of the `iid` parameter will change from True to False in version 0.22 and will be removed in 0.24. This will change numeric results when test-set sizes are unequal. DeprecationWarning)
RandomizedSearchCV(cv=<generator object _BaseKFold.split at 0x1101eb830>,
error_score='raise-deprecating',
estimator=Pipeline(memory=None,
steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None,
transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,...
reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
silent=True, subsample=1))]),
fit_params=None, iid='warn', n_iter=4, n_jobs=4,
param_distributions={'xgbclassifier__gamma': [0.5, 1], 'xgbclassifier__max_depth': [3, 4]},
pre_dispatch='2*n_jobs', random_state=1001, refit=True,
return_train_score='warn', scoring='accuracy', verbose=3)
Som du kan se, scorer XGBoost bedre enn den tidligere logistiske regresjonen.
print("Best parameter", random_search.best_params_) print("best logistic regression from grid search: %f" % random_search.best_estimator_.score(X_test, y_test))
Best parameter {'xgbclassifier__max_depth': 3, 'xgbclassifier__gamma': 0.5}
best logistic regression from grid search: 0.873157
random_search.best_estimator_.predict(X_test)
array(['<=50K', '<=50K', '<=50K', ..., '<=50K', '>50K', '<=50K'], dtype=object)
Lag DNN med MLPClassifier i scikit-learn
Til slutt kan du trene et nevralt nettverk med scikit-learn. Metoden er den samme som for alle andre klassifikatorer, og estimatoren er MLPClassifier.
from sklearn.neural_network import MLPClassifier
Nettverket nedenfor er definert med:
- Adam lรธser
- ReLU aktiveringsfunksjon
- Alfa = 0.0001
- Batchstรธrrelse pรฅ 150
- To skjulte lag med henholdsvis 200 og 100 nevroner
model_dnn = make_pipeline(
preprocess,
MLPClassifier(solver='adam',
alpha=0.0001,
activation='relu',
batch_size=150,
hidden_layer_sizes=(200, 100),
random_state=1))
Du kan endre antall lag for รฅ forbedre modellen.
model_dnn.fit(X_train, y_train) print("DNN regression score: %f" % model_dnn.score(X_test, y_test))
DNN regresjonsscore: 0.821253
LIME: Stol pรฅ modellen din
Nรฅ som du har en god modell, trenger du en mรฅte รฅ stole pรฅ den. Maskinlรฆringsalgoritmer, spesielt tilfeldige skoger og nevrale nettverk, er kjent som svartboksmodeller: de fungerer, men ingen kan se hvorfor.
Tre forskere har laget et verktรธy som viser hvordan datamaskinen kommer frem til en prediksjon. Artikkelen deres er ยซHvorfor skulle jeg stole pรฅ deg?ยป, og algoritmen de publiserte kalles Local Interpretable Model-Agnostic Explanations (LIME).
Ta et eksempel. Noen ganger vet du ikke om en maskinlรฆringsprediksjon kan stoles pรฅ. En lege kan ikke godta en diagnose bare fordi en datamaskin produserte den, og du mรฅ vite om en modell er pรฅlitelig fรธr du setter den i produksjon.
Tenk deg รฅ kunne se hvorfor en klassifikator kom med en prediksjon, selv for modeller sรฅ kompliserte som nevrale nettverk, tilfeldige skoger eller SVM-er med en vilkรฅrlig kjerne. Det blir mye enklere รฅ stole pรฅ en prediksjon nรฅr รฅrsakene bak den er synlige, og like enklere รฅ avgjรธre nรฅr en modell ikke bรธr stoles pรฅ. LIME forteller deg hvilke funksjoner som drev klassifikatorens beslutning.
Dataklargjรธring
Det er et par ting du mรฅ endre for รฅ kjรธre LIME med PythonFรธrst installerer du lime i terminalen med pip install lime.
Lime bruker et LimeTabularExplainer-objekt for รฅ tilnรฆrme modellen lokalt. Dette objektet krever:
- et datasett i nusset format
- Navnet pรฅ funksjonene: funksjonsnavn
- Navnet pรฅ klassene: klassenavn
- Indeksen til kolonnen med kategoriske funksjoner: categorical_features
- Navnet pรฅ gruppen for hvert kategoriske trekk: kategoriske_navn
Lag NumPy-togsettet
Du kan kopiere og konvertere df_train fra pandas til NumPy veldig enkelt.
df_train.head(5)
# Create numpy data
df_lime = df_train
df_lime.head(3)
Fรฅ klassenavnet
Etiketten er tilgjengelig via unique(). Du skal se:
- '<= 50 XNUMX'
- '> 50K'
# Get the class name
class_names = df_lime.label.unique()
class_names
array(['<=50K', '>50K'], dtype=object)
Indekser de kategoriske funksjonskolonnene
Bruk metoden du lรฆrte tidligere for รฅ fรฅ navnet pรฅ hver gruppe. Du koder etiketten med LabelEncoder og gjentar operasjonen pรฅ hvert kategoriske trekk.
## import sklearn.preprocessing as preprocessing categorical_names = {} for feature in CATE_FEATURES: le = preprocessing.LabelEncoder() le.fit(df_lime[feature]) df_lime[feature] = le.transform(df_lime[feature]) categorical_names[feature] = le.classes_ print(categorical_names)
{'workclass': array(['?', 'Federal-gov', 'Local-gov', 'Never-worked', 'Private',
'Self-emp-inc', 'Self-emp-not-inc', 'State-gov', 'Without-pay'],
dtype=object), 'education': array(['10th', '11th', '12th', '1st-4th', '5th-6th', '7th-8th', '9th',
'Assoc-acdm', 'Assoc-voc', 'Bachelors', 'Doctorate', 'HS-grad',
'Masters', 'Preschool', 'Prof-school', 'Some-college'],
dtype=object), 'marital': array(['Divorced', 'Married-AF-spouse', 'Married-civ-spouse',
'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed'],
dtype=object), 'occupation': array(['?', 'Adm-clerical', 'Armed-Forces', 'Craft-repair',
'Exec-managerial', 'Farming-fishing', 'Handlers-cleaners',
'Machine-op-inspct', 'Other-service', 'Priv-house-serv',
'Prof-specialty', 'Protective-serv', 'Sales', 'Tech-support',
'Transport-moving'], dtype=object), 'relationship': array(['Husband', 'Not-in-family', 'Other-relative', 'Own-child',
'Unmarried', 'Wife'], dtype=object), 'race': array(['Amer-Indian-Eskimo', 'Asian-Pac-Islander', 'Black', 'Other',
'White'], dtype=object), 'sex': array(['Female', 'Male'], dtype=object), 'native_country': array(['?', 'Cambodia', 'Canada', 'China', 'Columbia', 'Cuba',
'Dominican-Republic', 'Ecuador', 'El-Salvador', 'England',
'France', 'Germany', 'Greece', 'Guatemala', 'Haiti', 'Honduras',
'Hong', 'Hungary', 'India', 'Iran', 'Ireland', 'Italy', 'Jamaica',
'Japan', 'Laos', 'Mexico', 'Nicaragua',
'Outlying-US(Guam-USVI-etc)', 'Peru', 'Philippines', 'Poland',
'Portugal', 'Puerto-Rico', 'Scotland', 'South', 'Taiwan',
'Thailand', 'Trinadad&Tobago', 'United-States', 'Vietnam',
'Yugoslavia'], dtype=object)}
df_lime.dtypes
age float64 workclass int64 fnlwgt float64 education int64 education_num float64 marital int64 occupation int64 relationship int64 race int64 sex int64 capital_gain float64 capital_loss float64 hours_week float64 native_country int64 label object dtype: object
Nรฅ som datasettet er klart, kan du bygge de forskjellige datasettene som vises i Scikit-lรฆringseksemplene nedenfor. Dataene transformeres utenfor pipelinen her for รฅ unngรฅ feil med LIME: treningssettet som sendes til LimeTabularExplainer mรฅ vรฆre en NumPy-matrise uten strenger, og metoden ovenfor har allerede produsert en.
from sklearn.model_selection import train_test_split X_train_lime, X_test_lime, y_train_lime, y_test_lime = train_test_split(df_lime[features], df_lime.label, test_size = 0.2, random_state=0) X_train_lime.head(5)
Du kan lage pipelinen med de optimale parametrene som XGBoost finner.
model_xgb = make_pipeline(
preprocess,
xgboost.XGBClassifier(max_depth = 3,
gamma = 0.5,
n_estimators=600,
objective='binary:logistic',
silent=True,
nthread=1))
model_xgb.fit(X_train_lime, y_train_lime)
/Users/Thomas/anaconda3/envs/hello-tf/lib/python3.6/site-packages/sklearn/preprocessing/_encoders.py:351: FutureWarning: The handling of integer data will change in version 0.22. Currently, the categories are determined based on the range [0, max(values)], while in the future they will be determined based on the unique values. If you want the future behavior and silence this warning, you can specify "categories='auto'."In case you used a LabelEncoder before this OneHotEncoder to convert the categories to integers, then you can now use the OneHotEncoder directly. warnings.warn(msg, FutureWarning)
Pipeline(memory=None, steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None, transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,... reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None, silent=True, subsample=1))])
Du fรฅr en advarsel. Den forklarer at du ikke trenger รฅ opprette en label-koder fรธr pipelinen. Hvis du ikke bruker LIME, er metoden fra den fรธrste delen av denne veiledningen for maskinlรฆring med Scikit-learn grei. Ellers behold denne tilnรฆrmingen: fรธrst opprett et kodet datasett, og bruk deretter one-hot-koderen inne i pipelinen.
print("best logistic regression from grid search: %f" % model_xgb.score(X_test_lime, y_test_lime))
best logistic regression from grid search: 0.873157
model_xgb.predict_proba(X_test_lime)
array([[7.9646105e-01, 2.0353897e-01],
[9.5173013e-01, 4.8269872e-02],
[7.9344827e-01, 2.0655173e-01],
...,
[9.9031430e-01, 9.6856682e-03],
[6.4581633e-04, 9.9935418e-01],
[9.7104281e-01, 2.8957171e-02]], dtype=float32)
Fรธr du tar LIME i bruk, bรธr du opprette en NumPy-matrise som inneholder funksjonene til de feilklassifiserte radene. Du kan bruke den listen senere for รฅ fรฅ en idรฉ om hva som villedet klassifikatoren.
temp = pd.concat([X_test_lime, y_test_lime], axis= 1) temp['predicted'] = model_xgb.predict(X_test_lime) temp['wrong']= temp['label'] != temp['predicted'] temp = temp.query('wrong==True').drop('wrong', axis=1) temp= temp.sort_values(by=['label']) temp.shape
(826, 16)
Deretter oppretter du en lambda-funksjon som henter prediksjonen fra modellen for nye data. Du vil trenge den snart.
predict_fn = lambda x: model_xgb.predict_proba(x).astype(float)
X_test_lime.dtypes
age float64 workclass int64 fnlwgt float64 education int64 education_num float64 marital int64 occupation int64 relationship int64 race int64 sex int64 capital_gain float64 capital_loss float64 hours_week float64 native_country int64 dtype: object
predict_fn(X_test_lime)
array([[7.96461046e-01, 2.03538969e-01],
[9.51730132e-01, 4.82698716e-02],
[7.93448269e-01, 2.06551731e-01],
...,
[9.90314305e-01, 9.68566816e-03],
[6.45816326e-04, 9.99354184e-01],
[9.71042812e-01, 2.89571714e-02]])
Du konverterer pandas-datarammen til en NumPy-array.
X_train_lime = X_train_lime.values X_test_lime = X_test_lime.values X_test_lime
array([[4.00000e+01, 5.00000e+00, 1.93524e+05, ..., 0.00000e+00,
4.00000e+01, 3.80000e+01],
[2.70000e+01, 4.00000e+00, 2.16481e+05, ..., 0.00000e+00,
4.00000e+01, 3.80000e+01],
[2.50000e+01, 4.00000e+00, 2.56263e+05, ..., 0.00000e+00,
4.00000e+01, 3.80000e+01],
...,
[2.80000e+01, 6.00000e+00, 2.11032e+05, ..., 0.00000e+00,
4.00000e+01, 2.50000e+01],
[4.40000e+01, 4.00000e+00, 1.67005e+05, ..., 0.00000e+00,
6.00000e+01, 3.80000e+01],
[5.30000e+01, 4.00000e+00, 2.57940e+05, ..., 0.00000e+00,
4.00000e+01, 3.80000e+01]])
model_xgb.predict_proba(X_test_lime)
array([[7.9646105e-01, 2.0353897e-01],
[9.5173013e-01, 4.8269872e-02],
[7.9344827e-01, 2.0655173e-01],
...,
[9.9031430e-01, 9.6856682e-03],
[6.4581633e-04, 9.9935418e-01],
[9.7104281e-01, 2.8957171e-02]], dtype=float32)
print(features,
class_names,
categorical_features,
categorical_names)
['age', 'workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country'] ['<=50K' '>50K'] [1, 3, 5, 6, 7, 8, 9, 13] {'workclass': array(['?', 'Federal-gov', 'Local-gov', 'Never-worked', 'Private', 'Self-emp-inc', 'Self-emp-not-inc', 'State-gov', 'Without-pay'], dtype=object), 'education': array(['10th', '11th', '12th', '1st-4th', '5th-6th', '7th-8th', '9th', 'Assoc-acdm', 'Assoc-voc', 'Bachelors', 'Doctorate', 'HS-grad', 'Masters', 'Preschool', 'Prof-school', 'Some-college'], dtype=object), 'marital': array(['Divorced', 'Married-AF-spouse', 'Married-civ-spouse', 'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed'], dtype=object), 'occupation': array(['?', 'Adm-clerical', 'Armed-Forces', 'Craft-repair', 'Exec-managerial', 'Farming-fishing', 'Handlers-cleaners', 'Machine-op-inspct', 'Other-service', 'Priv-house-serv', 'Prof-specialty', 'Protective-serv', 'Sales', 'Tech-support', 'Transport-moving'], dtype=object), 'relationship': array(['Husband', 'Not-in-family', 'Other-relative', 'Own-child', 'Unmarried', 'Wife'], dtype=object), 'race': array(['Amer-Indian-Eskimo', 'Asian-Pac-Islander', 'Black', 'Other', 'White'], dtype=object), 'sex': array(['Female', 'Male'], dtype=object), 'native_country': array(['?', 'Cambodia', 'Canada', 'China', 'Columbia', 'Cuba', 'Dominican-Republic', 'Ecuador', 'El-Salvador', 'England', 'France', 'Germany', 'Greece', 'Guatemala', 'Haiti', 'Honduras', 'Hong', 'Hungary', 'India', 'Iran', 'Ireland', 'Italy', 'Jamaica', 'Japan', 'Laos', 'Mexico', 'Nicaragua', 'Outlying-US(Guam-USVI-etc)', 'Peru', 'Philippines', 'Poland', 'Portugal', 'Puerto-Rico', 'Scotland', 'South', 'Taiwan', 'Thailand', 'Trinadad&Tobago', 'United-States', 'Vietnam', 'Yugoslavia'], dtype=object)}
import lime import lime.lime_tabular ### Train should be label encoded not one hot encoded explainer = lime.lime_tabular.LimeTabularExplainer(X_train_lime , feature_names = features, class_names=class_names, categorical_features=categorical_features, categorical_names=categorical_names, kernel_width=3)
Velg nรฅ en tilfeldig husstand fra testsettet og se bรฅde prediksjonen og hvordan datamaskinen kom frem til den.
import numpy as np np.random.seed(1) i = 100 print(y_test_lime.iloc[i]) >50K
X_test_lime[i]
array([4.20000e+01, 4.00000e+00, 1.76286e+05, 7.00000e+00, 1.20000e+01,
2.00000e+00, 4.00000e+00, 0.00000e+00, 4.00000e+00, 1.00000e+00,
0.00000e+00, 0.00000e+00, 4.00000e+01, 3.80000e+01])
Du kan bruke explainer-funksjonen med explain_instance for รฅ undersรธke resonnementet bak modellen. Diagrammet den gjengir vises nedenfor.
exp = explainer.explain_instance(X_test_lime[i], predict_fn, num_features=6)
exp.show_in_notebook(show_all=False)
Klassifikatoren forutsรฅ denne husstanden riktig: inntekten er faktisk over 50 000.
Det fรธrste man mรฅ merke seg er at klassifikatoren ikke er veldig sikker pรฅ seg selv. Den forutsier en inntekt over 50 000 med en sannsynlighet pรฅ 64 %, og at 64 % er drevet av kapitalgevinst og sivilstatus. Den blรฅ fargen bidrar negativt til den positive klassen og den oransje linjen positivt.
Klassifikatoren er nรธlende fordi kapitalgevinsten til denne husholdningen er null, mens kapitalgevinst vanligvis er en god prediktor for formue. Husholdningen jobber ogsรฅ fรฆrre enn 40 timer per uke. Alder, yrke og kjรธnn bidrar alle positivt.
Hvis sivilstatusen var singel, ville klassifikatoren ha predikert en inntekt under 50 000 (0.64 โ 0.18 = 0.46).
Prรธv nรฅ en annen husholdning, en som ble feilklassifisert. Forklaringstabellen for den fรธlger koden.
temp.head(3) temp.iloc[1,:-2]
age 58 workclass 4 fnlwgt 68624 education 11 education_num 9 marital 2 occupation 4 relationship 0 race 4 sex 1 capital_gain 0 capital_loss 0 hours_week 45 native_country 38 Name: 20931, dtype: object
i = 1 print('This observation is', temp.iloc[i,-2:])
This observation is label <=50K
predicted >50K
Name: 20931, dtype: object
exp = explainer.explain_instance(temp.iloc[1,:-2], predict_fn, num_features=6)
exp.show_in_notebook(show_all=False)
Klassifikatoren forutsรฅ en inntekt under 50 000, noe som er feil. Denne husholdningen er uvanlig: den har verken kapitalgevinst eller kapitaltap, personen er skilt, nรฆr 60 รฅr gammel og utdannet, det vil si at utdanningsnummer > 12. Klassifikatoren fulgte det overordnede mรธnsteret og plasserte husholdningen under 50 000.
Lek deg med LIME selv, og du vil legge merke til mange grove feil fra klassifikatoren. GitHub-arkivet til bibliotekforfatteren inneholder ekstra dokumentasjon for klassifisering av bilder og tekst.
Scikit-learn-kommandoreferanse
Nedenfor er en liste over nyttige kommandoer som gjelder for scikit-learn versjon 0.20 og nyere.
| Oppgave | Funksjon eller klasse |
|---|---|
| Opprett tog-/testdatasettet | train_test_split |
| Bygg en rรธrledning | |
| Merk kolonnene og bruk transformasjonen | make_column_transformator |
| Type transformasjon | |
| Standardiser | Standard Scaler |
| Min-maks skalering | MinMaxScaler |
| Normaliser | Normalisering |
| Imputer manglende verdier | SimpleImputer |
| Konverter kategorisk | OneHotEncoder |
| Tilpass og transformer dataene | passe_transform |
| Lag rรธrledningen | make_pipeline |
| Grunnmodell | |
| Logistisk regresjon | Logistisk regresjon |
| Xgboost | XGBClassifier |
| Nevralt nett | MLPClassifier |
| Rutenettsรธk | GridSearchCV |
| Randomisert sรธk | RandomizedSearchCV |



