Scikit-Learn Tutorial: Hvordan installere og Scikit-Learn eksempler
Hva er Scikit-learn?
Scikit lære er en åpen kildekode Python bibliotek for maskinlæring. Den støtter state-of-the-art algoritmer som KNN, XGBoost, random forest og SVM. Den er bygget på toppen av NumPy. Scikit-learn er mye brukt i Kaggle-konkurranse så vel som fremtredende teknologiselskaper. Det hjelper med forbehandling, dimensjonalitetsreduksjon (parametervalg), klassifisering, regresjon, gruppering og modellvalg.
Scikit-learn har den beste dokumentasjonen av alle åpen kildekode-biblioteker. Det gir deg et interaktivt diagram på https://scikit-learn.org/stable/tutorial/machine_learning_map/index.html.
Scikit-learn er ikke veldig vanskelig å bruke og gir utmerkede resultater. Scikit learning støtter imidlertid ikke parallelle beregninger. Det er mulig å kjøre en dyp læringsalgoritme med det, men det er ikke en optimal løsning, spesielt hvis du vet hvordan du bruker TensorFlow.
Hvordan laste ned og installere Scikit-learn
Nå i dette Python Scikit-learn tutorial, vi vil lære hvordan du laster ned og installerer Scikit-learn:
Alternativ 1: AWS
scikit-learn kan brukes over AWS. Vennligst referere Docker-bildet som har scikit-learn forhåndsinstallert.
For å bruke utviklerversjonen, bruk kommandoen i 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 om Anaconda-installasjon, se https://www.guru99.com/download-install-tensorflow.html
Nylig har utviklerne av scikit gitt ut en utviklingsversjon som takler vanlige problemer med den nåværende versjonen. Vi fant det mer praktisk å bruke utviklerversjonen i stedet for den nåværende versjonen.
Hvordan installere scikit-learn med Conda Environment
Hvis du installerte scikit-learn med conda-miljøet, følg trinnet for å oppdatere til versjon 0.20
Trinn 1) Aktiver tensorflow-miljøet
source activate hello-tf
Trinn 2) Fjern scikit lean ved å bruke conda-kommandoen
conda remove scikit-learn
Trinn 3) Installer utviklerversjon.
Installer scikit learn utviklerversjon sammen med nødvendige biblioteker.
conda install -c anaconda git pip install Cython pip install h5py pip install git+git://github.com/scikit-learn/scikit-learn.git
NOTAT: Windows brukeren må installere Microsoft Visual C++ 14. Du kan få det fra 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 du bygger en rørledning, lager en modell og justerer hyperparametrene, mens den andre delen gir toppmoderne når det gjelder modellvalg.
Trinn 1) Importer dataene
I løpet av denne Scikit-læringsopplæringen vil du bruke voksendatasettet.
For en bakgrunn i dette datasettet, se Hvis du er interessert i å vite mer om den beskrivende statistikken, vennligst bruk Dive og Overview-verktøy.
Henvis denne opplæringen lær mer om dykk og oversikt
Du importerer datasettet med Pandas. Merk at du må konvertere typen av de kontinuerlige variablene i flyteformat.
Dette datasettet inkluderer åtte kategoriske variabler:
De kategoriske variablene er oppført i CATE_FEATURES
- arbeidsklasse
- utdanning
- ekteskapelig
- okkupasjon
- forholdet
- rase
- kjønn
- native_country
dessuten seks kontinuerlige variabler:
De kontinuerlige variablene er oppført i CONTI_FEATURES
- alder
- fnlwgt
- utdanning_nummer
- kapitalgevinst
- kapitaltap
- timer_uke
Merk at vi fyller listen for hånd slik at du har en bedre oversikt over hvilke kolonner vi bruker. En raskere måte å konstruere en liste over kategoriske eller kontinuerlige er å bruke:
## 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()
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-funksjonene. Du kan se at kun én husstand kommer fra Holand-Nederland. Denne husstanden vil ikke gi oss noen informasjon, men vil gjennom en feil under treningen.
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 vil gå over alle kolonnenavnene i CONTI_FEATURES og hente plasseringen (dvs. nummeret) og deretter legge den til 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]
Koden nedenfor gjør samme jobb som ovenfor, men for den kategoriske variabelen. Koden nedenfor gjentar det du har gjort tidligere, bortsett fra med de kategoriske funksjonene.
## 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]
Du kan ta en titt på datasettet. Merk at hvert kategorisk trekk er en streng. Du kan ikke mate en modell med en strengverdi. Du må transformere datasettet ved å bruke en dummy-variabel.
df_train.head(5)
Faktisk må du opprette én kolonne for hver gruppe i funksjonen. Først kan du kjøre 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. For eksempel har arbeidsklassens funksjoner ni grupper. Du kan visualisere navnet på gruppene med følgende koder
unique() returnerer de unike verdiene til de kategoriske funksjonene.
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']
Derfor vil opplæringsdatasettet inneholde 101 + 7 kolonner. De siste syv kolonnene er de kontinuerlige funksjonene.
Scikit-learn kan ta seg av konverteringen. Det gjøres i to trinn:
- Først må du konvertere strengen til ID. For eksempel vil State-gov ha ID 1, Self-emp-not-inc ID 2 og så videre. Funksjonen LabelEncoder gjør dette for deg
- Transponer hver ID til en ny kolonne. Som nevnt tidligere har datasettet 101-gruppens ID. Derfor vil det være 101 kolonner som fanger opp alle kategoriske funksjoners grupper. Scikit-learn har en funksjon kalt OneHotEncoder som utfører denne operasjonen
Trinn 2) Lag toget/testsettet
Nå som datasettet er klart, kan vi dele det 80/20.
80 prosent for treningssettet og 20 prosent for testsettet.
Du kan bruke train_test_split. Det første argumentet er datarammen er funksjonene og det andre argumentet er etiketten datarammen. Du kan spesifisere 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
Rørledningen gjør det enklere å mate modellen med konsistente data.
Tanken bak er å sette rådataene inn i en "pipeline" for å utføre operasjoner.
For eksempel, med det gjeldende datasettet, må du standardisere de kontinuerlige variablene og konvertere de kategoriske dataene. Merk at du kan utføre alle operasjoner inne i rørledningen. For eksempel, hvis du har 'NA'er' i datasettet, kan du erstatte dem med gjennomsnittet eller medianen. Du kan også opprette nye variabler.
Du har valget; hardkode de to prosessene eller lag en pipeline. Førstevalget kan føre til datalekkasje og skape inkonsekvenser over tid. Et bedre alternativ er å bruke rørledningen.
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 vil utføre to operasjoner før den mater den logistiske klassifisereren:
- Standardiser variabelen: `StandardScaler()“
- Konverter de kategoriske funksjonene: OneHotEncoder(sparse=False)
Du kan utføre de to trinnene ved å bruke make_column_transformer. Denne funksjonen er ikke tilgjengelig i gjeldende versjon av scikit-learn (0.19). Det er ikke mulig med gjeldende versjon å utføre etikettkoderen og én varmkoder i rørledningen. Det er en grunn til at vi bestemte oss for å bruke utviklerversjonen.
make_column_transformer er enkel å bruke. Du må definere hvilke kolonner som skal brukes transformasjonen og hvilken transformasjon som skal brukes. For å standardisere den kontinuerlige funksjonen kan du for eksempel gjøre:
- conti_features, StandardScaler() inne i make_column_transformer.
- conti_features: liste med den kontinuerlige variabelen
- StandardScaler: standardiser variabelen
Objektet OneHotEncoder inne i make_column_transformer koder automatisk etiketten.
preprocess = make_column_transformer( (conti_features, StandardScaler()), ### Need to be numeric not string to specify columns name (categorical_features, OneHotEncoder(sparse=False)) )
Du kan teste om rørledningen fungerer med fit_transform. Datasettet skal ha følgende form: 26048, 107
preprocess.fit_transform(X_train).shape
(26048, 107)
Datatransformatoren er klar til bruk. Du kan lage pipeline med make_pipeline. Når dataene er transformert, kan du mate den logistiske regresjonen.
model = make_pipeline( preprocess, LogisticRegression())
Å trene en modell med scikit-learn er trivielt. Du må bruke objekttilpasningen innledet av rørledningen, dvs. modellen. Du kan skrive ut nøyaktigheten med partiturobjektet fra scikit-learn-biblioteket
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. Den returnerer sannsynligheten for hver klasse. Merk at det summerer 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
Justering av hyperparameteren (variabler som bestemmer nettverksstruktur som skjulte enheter) kan være kjedelig og utmattende.
En måte å evaluere modellen på kan være å endre størrelsen på treningssettet og evaluere prestasjonene.
Du kan gjenta denne metoden ti ganger for å se poengsummene. Det er imidlertid for mye arbeid.
I stedet gir scikit-learn en funksjon for å utføre parameterinnstilling og kryssvalidering.
Kryssvalidering
Cross-Validation betyr under treningen, treningssettet er slip n antall ganger i folder og deretter evaluerer modellen n gang. For eksempel, hvis cv er satt til 10, trenes treningssettet og evalueres ti ganger. Ved hver runde velger klassifisereren tilfeldig ni fold for å trene modellen, og den 10. folden er ment for evaluering.
Rutenettsøk
Hver klassifikator har hyperparametre for å stille inn. Du kan prøve forskjellige verdier, eller du kan angi et parameterrutenett. Hvis du går til det offisielle nettstedet for scikit-learn, kan du se at den logistiske klassifikatoren har forskjellige parametere å justere. For å gjøre treningen raskere velger du å stille inn C-parameteren. Den kontrollerer for regulariseringsparameteren. Det skal være positivt. En liten verdi gir mer vekt til regularizeren.
Du kan bruke objektet GridSearchCV. Du må lage en ordbok som inneholder hyperparametrene for å stille inn.
Du lister opp hyperparametrene etterfulgt av verdiene du vil prøve. For å stille inn C-parameteren bruker du for eksempel:
- 'logisticregression__C': [0.1, 1.0, 1.0]: Parameteren innledes med navnet, med små bokstaver, på klassifikatoren og to understrekinger.
Modellen vil prøve fire forskjellige verdier: 0.001, 0.01, 0.1 og 1.
Du trener modellen ved å bruke 10 folder: 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 trene modellen ved å bruke GridSearchCV med parameterne gri 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)
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, er 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
La oss prøve Scikit-learn-eksempler for å trene en av de beste klassifisere på markedet. XGBoost er en forbedring i forhold til den tilfeldige skogen. Klassifisererens teoretiske bakgrunn utenfor rammen av dette Python Scikit opplæring. Husk at XGBoost har vunnet mange kaggle-konkurranser. Med en gjennomsnittlig datasettstørrelse kan den yte like bra som en dyplæringsalgoritme eller enda bedre.
Klassifisereren er utfordrende å trene fordi den har et stort antall parametere å stille inn. Du kan selvfølgelig bruke GridSearchCV til å velge parameteren for deg.
La oss i stedet se hvordan du bruker en bedre måte å finne de optimale parameterne på. GridSearchCV kan være kjedelig og veldig lang å trene hvis du passerer mange verdier. Søkeområdet vokser sammen med antall parametere. En foretrukket løsning er å bruke RandomizedSearchCV. Denne metoden består i å velge verdiene til hver hyperparameter etter hver iterasjon tilfeldig. For eksempel, hvis klassifisereren trenes over 1000 iterasjoner, blir 1000 kombinasjoner evaluert. Det fungerer mer eller mindre som. GridSearchCV
Du må importere xgboost. Hvis biblioteket ikke er installert, vennligst bruk pip3 install xgboost eller
use import sys !{sys.executable} -m pip install xgboost
In Jupyter miljø
Neste,
import xgboost from sklearn.model_selection import RandomizedSearchCV from sklearn.model_selection import StratifiedKFold
Det neste trinnet i denne Scikit Python opplæringen inkluderer å spesifisere parametrene som skal stilles inn. Du kan referere til den offisielle dokumentasjonen for å se alle parameterne som skal justeres. Av hensyn til Python Sklearn tutorial, du velger bare to hyperparametre med to verdier hver. XGBoost tar mye tid å trene, jo flere hyperparametre i rutenettet, jo lengre tid trenger du å vente.
params = { 'xgbclassifier__gamma': [0.5, 1], 'xgbclassifier__max_depth': [3, 4] }
Du konstruerer en ny pipeline med XGBoost-klassifiserer. Du velger å definere 600 estimatorer. Merk at n_estimators er en parameter du kan justere. En høy verdi kan føre til overmontering. Du kan prøve forskjellige verdier selv, men vær oppmerksom på at det kan ta timer. Du bruker standardverdien for de andre parameterne
model_xgb = make_pipeline( preprocess, xgboost.XGBClassifier( n_estimators=600, objective='binary:logistic', silent=True, nthread=1) )
Du kan forbedre kryssvalideringen med den Stratified K-Folds kryssvalidatoren. Du konstruerer bare tre folder her for å raskere beregningen, men redusere kvaliteten. Øk denne verdien til 5 eller 10 hjemme for å forbedre resultatene.
Du velger å trene modellen 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 til bruk, 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, har XGBoost en bedre poengsum enn den forrige 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 en dyp læringsalgoritme med scikit-learn. Metoden er den samme som den andre klassifisereren. Klassifisereren er tilgjengelig på MLPClassifier.
from sklearn.neural_network import MLPClassifier
Du definerer følgende dyplæringsalgoritme:
- Adam løser
- Relu aktiveringsfunksjon
- Alfa = 0.0001
- batchstørrelse på 150
- To skjulte lag med henholdsvis 100 og 50 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 et verktøy for å stole på den. Maskinlæring algoritmer, spesielt tilfeldig skog og nevrale nettverk, er kjent for å være black-box-algoritme. Si annerledes, det fungerer, men ingen vet hvorfor.
Tre forskere har kommet opp med et flott verktøy for å se hvordan datamaskinen gir en spådom. Avisen heter Why Should I Trust You?
De utviklet en algoritme kalt Lokale tolkbare modell-agnostiske forklaringer (LIME).
Ta et eksempel:
noen ganger vet du ikke om du kan stole på en maskinlæringsprediksjon:
En lege kan for eksempel ikke stole på en diagnose bare fordi en datamaskin sa det. Du må også vite om du kan stole på modellen før du setter den i produksjon.
Tenk deg at vi kan forstå hvorfor en klassifikator lager en prediksjon selv utrolig kompliserte modeller som nevrale nettverk, tilfeldige skoger eller svms med hvilken som helst kjerne
vil bli mer tilgjengelig for å stole på en prediksjon hvis vi kan forstå årsakene bak den. Fra eksemplet med legen, hvis modellen fortalte ham hvilke symptomer som er viktige du ville stole på, er det også lettere å finne ut om du ikke bør stole på modellen.
Lime kan fortelle deg hvilke funksjoner som påvirker avgjørelsene til klassifisereren
Dataklargjøring
De er et par ting du må endre for å kjøre LIME med python. Først av alt må du installere kalk i terminalen. Du kan bruke pip install lime
Lime bruker LimeTabularExplainer-objektet for å tilnærme modellen lokalt. Dette objektet krever:
- et datasett i numpy-format
- Navnet på funksjonene: funksjonsnavn
- Navnet på klassene: klassenavn
- Indeksen til kolonnen med kategoriske funksjoner: categorical_features
- Navnet på gruppen for hver kategoriske funksjoner: categorical_names
Lag numpy togsett
Du kan kopiere og konvertere df_train fra pandaer til følelsesløs veldig lett
df_train.head(5) # Create numpy data df_lime = df_train df_lime.head(3)
Få klassenavnet Etiketten er tilgjengelig med objektet unique(). Du bør se:
- '<= 50 XNUMX'
- '> 50K'
# Get the class name class_names = df_lime.label.unique() class_names
array(['<=50K', '>50K'], dtype=object)
indeks av kolonnen med kategoriske funksjoner
Du kan bruke metoden du lener deg før for å få navnet på gruppen. Du koder etiketten med LabelEncoder. Du gjentar operasjonen på alle de kategoriske funksjonene.
## 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 konstruere det forskjellige datasettet som vist i Scikit learn-eksempler nedenfor. Du transformerer faktisk dataene utenfor rørledningen for å unngå feil med LIME. Opplæringssettet i LimeTabularExplainer skal være en numpy array uten streng. Med metoden ovenfor har du allerede konvertert et treningsdatasett.
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 rørledningen med de optimale parameterne fra XGBoost
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. Advarselen forklarer at du ikke trenger å opprette en etikettkoder før rørledningen. Hvis du ikke vil bruke LIME, kan du fint bruke metoden fra første del av Machine Learning with Scikit-learn-opplæringen. Ellers kan du fortsette med denne metoden, først opprette et kodet datasett, sett få den varme enkoderen i rørledningen.
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 vi bruker LIME i aksjon, la oss lage en numpy matrise med funksjonene til feil klassifisering. Du kan bruke den listen senere for å få en idé om hva som villeder klassifisereren.
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)
Du lager en lambda-funksjon for å hente prediksjonen fra modellen med de nye dataene. Du trenger det 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 dataramme til 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)
La oss velge en tilfeldig husholdning fra testsettet og se modellprediksjonen og hvordan datamaskinen gjorde sitt valg.
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 forklaringen med explain_instance for å sjekke forklaringen bak modellen
exp = explainer.explain_instance(X_test_lime[i], predict_fn, num_features=6) exp.show_in_notebook(show_all=False)
Vi kan se at klassifikatoren spådde husholdningen riktig. Inntekten er faktisk over 50k.
Det første vi kan si er at klassifisereren ikke er så sikker på de forutsagte sannsynlighetene. Maskinen spår at husholdningen har en inntekt over 50k med en sannsynlighet på 64%. Disse 64 % består av kapitalgevinst og ekteskap. Den blå fargen bidrar negativt til den positive klassen og den oransje linjen, positivt.
Klassifisereren er forvirret fordi kapitalgevinsten til denne husholdningen er null, mens kapitalgevinsten vanligvis er en god prediktor for formue. Dessuten jobber husholdningen mindre enn 40 timer i uken. Alder, yrke og kjønn bidrar positivt til klassifisereren.
Hvis sivilstatusen var singel, ville klassifikatoren ha spådd en inntekt under 50k (0.64-0.18 = 0.46)
Vi kan prøve med en annen husstand som har blitt feilklassifisert
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)
Klassifisereren spådde en inntekt under 50k mens det er usant. Denne husholdningen virker rar. Den har ikke kapitalgevinst, og heller ikke kapitaltap. Han er skilt og er 60 år gammel, og det er et utdannet folk, dvs. utdanning_num > 12. I følge det overordnede mønsteret skal denne husstanden, som klassifisereren forklarer, få en inntekt under 50k.
Du prøver å leke med LIME. Du vil legge merke til grove feil fra klassifisereren.
Du kan sjekke GitHub til eieren av biblioteket. De gir ekstra dokumentasjon for bilde- og tekstklassifisering.
Sammendrag
Nedenfor er en liste over noen nyttige kommandoer med scikit learning-versjon >=0.20
lage tog-/testdatasett | traineer splittes |
Bygg en rørledning | |
velg kolonnen og bruk transformasjonen | lage kolonnetransformator |
type transformasjon | |
standardisere | Standard Scaler |
min maks | MinMaxScaler |
normal~~POS=TRUNC | Normalisering |
Beregn manglende verdi | tilregne |
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 |