Tutorial Scikit-Learn: Cum se instalează și exemple Scikit-Learn
Ce este Scikit-learn?
Scikit-învață este un open-source Python bibliotecă pentru învățarea automată. Acceptă algoritmi de ultimă generație, cum ar fi KNN, XGBoost, pădure aleatoare și SVM. Este construit pe NumPy. Scikit-learn este utilizat pe scară largă în competiția Kaggle, precum și în companiile de tehnologie proeminente. Ajută la preprocesare, reducerea dimensionalității (selectarea parametrilor), clasificarea, regresia, gruparea și selecția modelului.
Scikit-learn are cea mai bună documentație dintre toate bibliotecile open-source. Vă oferă o diagramă interactivă la https://scikit-learn.org/stable/tutorial/machine_learning_map/index.html.
Scikit-learn nu este foarte dificil de utilizat și oferă rezultate excelente. Cu toate acestea, scikit Learn nu acceptă calcule paralele. Este posibil să rulați un algoritm de învățare profundă cu acesta, dar nu este o soluție optimă, mai ales dacă știți să utilizați TensorFlow.
Cum să descărcați și să instalați Scikit-learn
Acum în asta Python Tutorial Scikit-learn, vom învăța cum să descărcați și să instalați Scikit-learn:
Opțiunea 1: AWS
scikit-learn poate fi utilizat pe AWS. Vă rog trimite Imaginea docker care are scikit-learn preinstalat.
Pentru a utiliza versiunea de dezvoltator, utilizați comanda în Jupyter
import sys !{sys.executable} -m pip install git+git://github.com/scikit-learn/scikit-learn.git
Opțiunea 2: Mac sau Windows folosind Anaconda
Pentru a afla despre instalarea Anaconda, consultați https://www.guru99.com/download-install-tensorflow.html
Recent, dezvoltatorii scikit au lansat o versiune de dezvoltare care abordează problema comună cu care se confruntă versiunea actuală. Am considerat că este mai convenabil să folosim versiunea de dezvoltator în loc de versiunea actuală.
Cum se instalează scikit-learn cu Conda Environment
Dacă ați instalat scikit-learn cu mediul conda, vă rugăm să urmați pasul pentru a actualiza la versiunea 0.20
Pas 1) Activați mediul tensorflow
source activate hello-tf
Pas 2) Eliminați scikit lean folosind comanda conda
conda remove scikit-learn
Pas 3) Instalați versiunea de dezvoltator.
Instalați versiunea de dezvoltator scikit Learn împreună cu bibliotecile necesare.
conda install -c anaconda git pip install Cython pip install h5py pip install git+git://github.com/scikit-learn/scikit-learn.git
NOTĂ: Windows utilizatorul va trebui să instaleze Microsoft Vizual C++ 14. Îl poți obține de la aici
Scikit-Learn Exemplu cu Machine Learning
Acest tutorial Scikit este împărțit în două părți:
- Învățare automată cu scikit-learn
- Cum să ai încredere în modelul tău cu LIME
Prima parte detaliază cum să construiți o conductă, să creați un model și să reglați hiperparametrii, în timp ce a doua parte oferă stadiul tehnicii în ceea ce privește selecția modelului.
Pasul 1) Importați datele
În timpul acestui tutorial de învățare Scikit, veți folosi setul de date pentru adulți.
Pentru informații despre acest set de date, consultați Dacă sunteți interesat să aflați mai multe despre statisticile descriptive, vă rugăm să utilizați instrumentele Dive și Overview.
Trimite acest tutorial aflați mai multe despre scufundare și prezentare generală
Importați setul de date cu Pandas. Rețineți că trebuie să convertiți tipul variabilelor continue în format flotant.
Acest set de date include opt variabile categoriale:
Variabilele categoriale sunt listate în CATE_FEATURES
- clasa de lucru
- educaţie
- marital
- ocupație
- relaţie
- rasă
- sex
- tara de origine
în plus, șase variabile continue:
Variabilele continue sunt listate în CONTI_FEATURES
- vârstă
- fnlwgt
- educație_num
- câștig de capital
- pierdere_capital
- ore_săptămână
Rețineți că completăm lista manual, astfel încât să aveți o idee mai bună despre ce coloane folosim. O modalitate mai rapidă de a construi o listă de categorii categorice sau continue este să utilizați:
## 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)
Iată codul pentru a importa datele:
# 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()
vârstă | fnlwgt | educație_num | câștig de capital | pierdere_capital | ore_săptămână | |
---|---|---|---|---|---|---|
conta | 32561.000000 | 3.256100e + 04 | 32561.000000 | 32561.000000 | 32561.000000 | 32561.000000 |
însemna | 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 |
minute | 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 |
Puteți verifica numărul de valori unice ale caracteristicilor native_country. Puteți vedea că o singură gospodărie provine din Olanda-Olanda. Această gospodărie nu ne va aduce nicio informație, dar o va face printr-o eroare în timpul antrenamentului.
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
Puteți exclude acest rând neinformativ din setul de date
## Drop Netherland, because only one row df_train = df_train[df_train.native_country != "Holand-Netherlands"]
Apoi, stocați poziția caracteristicilor continue într-o listă. Veți avea nevoie de el în următorul pas pentru a construi conducta.
Codul de mai jos va trece peste numele tuturor coloanelor din CONTI_FEATURES și va obține locația acestuia (adică, numărul) și apoi îl va adăuga la o listă numită 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]
Codul de mai jos face aceeași treabă ca mai sus, dar pentru variabila categorială. Codul de mai jos repetă ceea ce ați făcut anterior, cu excepția caracteristicilor categoriale.
## 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]
Puteți arunca o privire la setul de date. Rețineți că fiecare caracteristică categorială este un șir. Nu puteți alimenta un model cu o valoare șir. Trebuie să transformați setul de date folosind o variabilă inactivă.
df_train.head(5)
De fapt, trebuie să creați o coloană pentru fiecare grup din caracteristică. În primul rând, puteți rula codul de mai jos pentru a calcula cantitatea totală de coloane necesare.
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
Întregul set de date conține 101 grupuri, așa cum se arată mai sus. De exemplu, caracteristicile clasei de muncă au nouă grupuri. Puteți vizualiza numele grupurilor cu următoarele coduri
unique() returnează valorile unice ale caracteristicilor categoriale.
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']
Prin urmare, setul de date de antrenament va conține 101 + 7 coloane. Ultimele șapte coloane sunt caracteristicile continue.
Scikit-learn se poate ocupa de conversie. Se realizează în doi pași:
- Mai întâi, trebuie să convertiți șirul în ID. De exemplu, State-gov va avea ID 1, Self-emp-not-inc ID 2 și așa mai departe. Funcția LabelEncoder face acest lucru pentru tine
- Transpuneți fiecare ID într-o coloană nouă. După cum sa menționat anterior, setul de date are 101 ID-uri de grup. Prin urmare, vor exista 101 coloane care captează toate grupurile de caracteristici categorice. Scikit-learn are o funcție numită OneHotEncoder care efectuează această operație
Pasul 2) Creați trenul/setul de testare
Acum că setul de date este gata, îl putem împărți 80/20.
80% pentru setul de antrenament și 20% pentru setul de testare.
Puteți folosi train_test_split. Primul argument este cadrul de date este caracteristicile și al doilea argument este cadrul de date eticheta. Puteți specifica dimensiunea setului de testare cu 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)
Pasul 3) Construiți conducta
Conducta facilitează alimentarea modelului cu date consistente.
Ideea din spate este de a pune datele brute într-o „conductă” pentru a efectua operațiuni.
De exemplu, cu setul de date curent, trebuie să standardizați variabilele continue și să convertiți datele categorice. Rețineți că puteți efectua orice operațiune în interiorul conductei. De exemplu, dacă aveți „NA” în setul de date, le puteți înlocui cu media sau mediana. De asemenea, puteți crea variabile noi.
Ai de ales; codificați cele două procese sau creați o conductă. Prima alegere poate duce la scurgeri de date și poate crea inconsecvențe în timp. O opțiune mai bună este utilizarea conductei.
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
Conducta va efectua două operațiuni înainte de a alimenta clasificatorul logistic:
- Standardizați variabila: „StandardScaler()“
- Convertiți caracteristicile categoriale: OneHotEncoder(sparse=False)
Puteți efectua cei doi pași folosind make_column_transformer. Această funcție nu este disponibilă în versiunea curentă a scikit-learn (0.19). Cu versiunea curentă nu este posibil să se realizeze codificatorul de etichetă și un codificator fierbinte în conductă. Acesta este unul dintre motivele pentru care am decis să folosim versiunea pentru dezvoltatori.
make_column_transformer este ușor de utilizat. Trebuie să definiți ce coloane să aplicați transformarea și ce transformare să operați. De exemplu, pentru a standardiza caracteristica continuă, puteți face:
- conti_features, StandardScaler() în interiorul make_column_transformer.
- conti_features: listă cu variabila continuă
- StandardScaler: standardizați variabila
Obiectul OneHotEncoder din make_column_transformer codifică automat eticheta.
preprocess = make_column_transformer( (conti_features, StandardScaler()), ### Need to be numeric not string to specify columns name (categorical_features, OneHotEncoder(sparse=False)) )
Puteți testa dacă conducta funcționează cu fit_transform. Setul de date ar trebui să aibă următoarea formă: 26048, 107
preprocess.fit_transform(X_train).shape
(26048, 107)
Transformatorul de date este gata de utilizare. Puteți crea conducta cu make_pipeline. Odată ce datele sunt transformate, puteți alimenta regresia logistică.
model = make_pipeline( preprocess, LogisticRegression())
Antrenarea unui model cu scikit-learn este banala. Trebuie să utilizați potrivirea obiectului precedată de conductă, adică modelul. Puteți imprima acuratețea cu obiectul scor din biblioteca scikit-learn
model.fit(X_train, y_train) print("logistic regression score: %f" % model.score(X_test, y_test))
logistic regression score: 0.850891
În cele din urmă, puteți prezice clasele cu predict_proba. Returnează probabilitatea pentru fiecare clasă. Rețineți că se însumează la unu.
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]])
Pasul 4) Utilizarea conductei noastre într-o căutare în grilă
Reglarea hiperparametrului (variabilele care determină structura rețelei precum unitățile ascunse) poate fi obositoare și obositoare.
O modalitate de a evalua modelul ar putea fi schimbarea dimensiunii setului de antrenament și evaluarea performanțelor.
Puteți repeta această metodă de zece ori pentru a vedea valorile scorului. Cu toate acestea, este prea multă muncă.
În schimb, scikit-learn oferă o funcție pentru a efectua reglarea parametrilor și validarea încrucișată.
Validare încrucișată
Validarea încrucișată înseamnă în timpul antrenamentului, setul de antrenament este alunecat de n număr de ori în pliuri și apoi evaluează modelul n timp. De exemplu, dacă cv este setat la 10, setul de antrenament este antrenat și evaluează de zece ori. La fiecare rundă, clasificatorul alege aleatoriu nouă pliuri pentru a antrena modelul, iar a zecea ori este destinată evaluării.
Căutare în grilă
Fiecare clasificator are hiperparametri de reglat. Puteți încerca valori diferite sau puteți seta o grilă de parametri. Dacă accesați site-ul oficial scikit-learn, puteți vedea că clasificatorul logistic are diferiți parametri de reglat. Pentru a face antrenamentul mai rapid, alegeți să reglați parametrul C. Controlează parametrul de regularizare. Ar trebui să fie pozitiv. O valoare mică conferă mai multă greutate regulatorului.
Puteți utiliza obiectul GridSearchCV. Trebuie să creați un dicționar care să conțină hiperparametrii de reglat.
Listați hiperparametrii urmați de valorile pe care doriți să le încercați. De exemplu, pentru a regla parametrul C, utilizați:
- 'logisticregression__C': [0.1, 1.0, 1.0]: Parametrul este precedat de numele, în litere mici, a clasificatorului și două litere de subliniere.
Modelul va încerca patru valori diferite: 0.001, 0.01, 0.1 și 1.
Antrenați modelul folosind 10 pliuri: cv=10
from sklearn.model_selection import GridSearchCV # Construct the parameter grid param_grid = { 'logisticregression__C': [0.001, 0.01,0.1, 1.0], }
Puteți antrena modelul folosind GridSearchCV cu parametrul gri și cv.
# Train the model grid_clf = GridSearchCV(model, param_grid, cv=10, iid=False) grid_clf.fit(X_train, y_train)
REZULTATE
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)
Pentru a accesa cei mai buni parametri, utilizați best_params_
grid_clf.best_params_
REZULTATE
{'logisticregression__C': 1.0}
După antrenarea modelului cu patru valori de regularizare diferite, parametrul optim este
print("best logistic regression from grid search: %f" % grid_clf.best_estimator_.score(X_test, y_test))
cea mai bună regresie logistică din căutarea în grilă: 0.850891
Pentru a accesa probabilitățile prezise:
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]])
Model XGBoost cu scikit-learn
Să încercăm exemple Scikit-learn pentru a instrui unul dintre cei mai buni clasificatori de pe piață. XGBoost este o îmbunătățire față de pădurea aleatorie. Fundalul teoretic al clasificatorului în afara domeniului de aplicare al acestui Python Tutorial Scikit. Rețineți că, XGBoost a câștigat o mulțime de competiții de kaggle. Cu o dimensiune medie a setului de date, poate funcționa la fel de bine ca un algoritm de învățare profundă sau chiar mai bine.
Clasificatorul este dificil de antrenat, deoarece are un număr mare de parametri de reglat. Puteți, desigur, să utilizați GridSearchCV pentru a alege parametrul pentru dvs.
În schimb, să vedem cum să folosim o modalitate mai bună de a găsi parametrii optimi. GridSearchCV poate fi plictisitor și foarte lung de antrenat dacă treci de multe valori. Spațiul de căutare crește odată cu numărul de parametri. O soluție preferabilă este utilizarea RandomizedSearchCV. Această metodă constă în alegerea aleatorie a valorilor fiecărui hiperparametru după fiecare iterație. De exemplu, dacă clasificatorul este antrenat peste 1000 de iterații, atunci sunt evaluate 1000 de combinații. Funcționează mai mult sau mai puțin ca. GridSearchCV
Trebuie să importați xgboost. Dacă biblioteca nu este instalată, vă rugăm să utilizați pip3 install xgboost sau
use import sys !{sys.executable} -m pip install xgboost
In Jupyter mediu inconjurator
În continuare,
import xgboost from sklearn.model_selection import RandomizedSearchCV from sklearn.model_selection import StratifiedKFold
Următorul pas în acest Scikit Python tutorialul include specificarea parametrilor de reglat. Puteți consulta documentația oficială pentru a vedea toți parametrii de reglat. De dragul Python Tutorial Sklearn, alegeți doar doi hiperparametri cu câte două valori fiecare. XGBoost durează mult timp pentru a se antrena, cu cât sunt mai mulți hiperparametri în grilă, cu atât trebuie să așteptați mai mult.
params = { 'xgbclassifier__gamma': [0.5, 1], 'xgbclassifier__max_depth': [3, 4] }
Construiți o nouă conductă cu clasificatorul XGBoost. Alegeți să definiți 600 de estimatori. Rețineți că n_estimators sunt un parametru pe care îl puteți regla. O valoare mare poate duce la supraadaptare. Puteți încerca singur valori diferite, dar fiți conștienți că poate dura ore. Utilizați valoarea implicită pentru ceilalți parametri
model_xgb = make_pipeline( preprocess, xgboost.XGBClassifier( n_estimators=600, objective='binary:logistic', silent=True, nthread=1) )
Puteți îmbunătăți validarea încrucișată cu validatorul încrucișat Stratified K-Folds. Construiți doar trei ori aici pentru a accelera calculul, dar pentru a reduce calitatea. Creșteți această valoare la 5 sau 10 acasă pentru a îmbunătăți rezultatele.
Alegeți să antrenați modelul în patru iterații.
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)
Căutarea randomizată este gata de utilizare, puteți antrena modelul
#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)
După cum puteți vedea, XGBoost are un scor mai bun decât regresia logistică anterioară.
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)
Creați DNN cu MLPClassifier în scikit-learn
În cele din urmă, puteți antrena un algoritm de învățare profundă cu scikit-learn. Metoda este aceeași ca și celălalt clasificator. Clasificatorul este disponibil la MLPClassifier.
from sklearn.neural_network import MLPClassifier
Definiți următorul algoritm de învățare profundă:
- Adam rezolvator
- Funcția de activare Relu
- Alfa = 0.0001
- dimensiunea lotului de 150
- Două straturi ascunse cu 100 și, respectiv, 50 de neuroni
model_dnn = make_pipeline( preprocess, MLPClassifier(solver='adam', alpha=0.0001, activation='relu', batch_size=150, hidden_layer_sizes=(200, 100), random_state=1))
Puteți modifica numărul de straturi pentru a îmbunătăți modelul
model_dnn.fit(X_train, y_train) print("DNN regression score: %f" % model_dnn.score(X_test, y_test))
Scorul de regresie DNN: 0.821253
LIME: Ai încredere în modelul tău
Acum că ai un model bun, ai nevoie de un instrument în care să ai încredere în el. Invatare mecanica algoritmul, în special pădurile aleatorii și rețelele neuronale, sunt cunoscute a fi algoritm cutie neagră. Spune altfel, funcționează, dar nimeni nu știe de ce.
Trei cercetători au venit cu un instrument excelent pentru a vedea cum computerul face o predicție. Lucrarea se numește De ce ar trebui să am încredere în tine?
Ei au dezvoltat un algoritm numit Explicații locale interpretabile pentru model-agnostic (LIME).
Luați un exemplu:
uneori nu știi dacă poți avea încredere într-o predicție de învățare automată:
Un medic, de exemplu, nu poate avea încredere într-un diagnostic doar pentru că așa spune un computer. De asemenea, trebuie să știți dacă puteți avea încredere în model înainte de a-l pune în producție.
Imaginați-vă că putem înțelege de ce orice clasificator face o predicție chiar și modele incredibil de complicate, cum ar fi rețele neuronale, păduri aleatorii sau svm-uri cu orice nucleu
va deveni mai accesibil să avem încredere într-o predicție dacă putem înțelege motivele din spatele acesteia. Din exemplul cu medicul, dacă modelul i-a spus ce simptome sunt esențiale ai avea încredere în el, este și mai ușor să-ți dai seama dacă nu ar trebui să ai încredere în model.
Lime vă poate spune ce caracteristici afectează deciziile clasificatorului
Pregătirea datelor
Sunt câteva lucruri pe care trebuie să le schimbi pentru a rula LIME piton. În primul rând, trebuie să instalați var în terminal. Puteți folosi pip install var
Lime folosește obiectul LimeTabularExplainer pentru a aproxima modelul la nivel local. Acest obiect necesită:
- un set de date în format numpy
- Numele caracteristicilor: feature_names
- Numele claselor: class_names
- Indexul coloanei caracteristicilor categoriale: caracteristici_categorice
- Numele grupului pentru fiecare caracteristică categorială: nume_categorice
Creați un set de tren numpy
Puteți copia și converti df_train din panda în NumPy foarte usor
df_train.head(5) # Create numpy data df_lime = df_train df_lime.head(3)
Obțineți numele clasei Eticheta este accesibilă cu obiectul unique(). Ar trebui sa vezi:
- „<=50K”
- „>50K”
# Get the class name class_names = df_lime.label.unique() class_names
array(['<=50K', '>50K'], dtype=object)
indicele coloanei trăsăturilor categoriale
Puteți folosi metoda pe care o înclinați înainte pentru a obține numele grupului. Codificați eticheta cu LabelEncoder. Repetați operația pe toate caracteristicile categoriale.
## 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
Acum că setul de date este gata, puteți construi setul de date diferit, așa cum se arată în exemplele de mai jos Scikit Learn. De fapt, transformați datele în afara conductei pentru a evita erorile cu LIME. Setul de antrenament din LimeTabularExplainer ar trebui să fie o matrice numpy fără șir. Cu metoda de mai sus, aveți deja un set de date de antrenament convertit.
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)
Puteți realiza conducta cu parametrii optimi din 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))])
Primești un avertisment. Avertismentul explică faptul că nu trebuie să creați un codificator de etichetă înaintea conductei. Dacă nu doriți să utilizați LIME, este bine să utilizați metoda din prima parte a tutorialului Machine Learning cu Scikit-learn. În caz contrar, puteți păstra această metodă, creați mai întâi un set de date codificat, setați obțineți codificatorul fierbinte în conductă.
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)
Înainte de a folosi LIME în acțiune, să creăm o matrice numpy cu caracteristicile clasificării greșite. Puteți folosi acea listă mai târziu pentru a vă face o idee despre ceea ce induce în eroare clasificatorul.
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)
Creați o funcție lambda pentru a prelua predicția din model cu noile date. Veți avea nevoie de el în curând.
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]])
Convertiți cadrul de date panda în matrice numpy
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)
Să alegem o gospodărie aleatorie din setul de testare și să vedem predicția modelului și modul în care computerul a făcut alegerea sa.
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])
Puteți folosi explicația cu explic_instance pentru a verifica explicația din spatele modelului
exp = explainer.explain_instance(X_test_lime[i], predict_fn, num_features=6) exp.show_in_notebook(show_all=False)
Putem vedea că clasificatorul a prezis corect gospodăria. Venitul este, într-adevăr, peste 50k.
Primul lucru pe care îl putem spune este că clasificatorul nu este atât de sigur cu privire la probabilitățile prezise. Aparatul prezice că gospodăria are un venit peste 50k cu o probabilitate de 64%. Acest 64% este alcătuit din câștig de capital și conjugal. Culoarea albastră contribuie negativ la clasa pozitivă, iar linia portocalie, pozitiv.
Clasificatorul este confuz deoarece câștigul de capital al acestei gospodării este nul, în timp ce câștigul de capital este de obicei un bun predictor al bogăției. În plus, gospodăria lucrează mai puțin de 40 de ore pe săptămână. Vârsta, ocupația și sexul contribuie pozitiv la clasificare.
Dacă starea civilă ar fi fost singură, clasificatorul ar fi prezis un venit sub 50k (0.64-0.18 = 0.46)
Putem încerca cu o altă gospodărie care a fost clasificată greșit
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)
Clasificatorul a prezis un venit sub 50k, în timp ce este neadevărat. Gospodăria asta pare ciudată. Nu are câștig de capital, nici pierdere de capital. El este divorțat și are 60 de ani și este un popor educat, adică education_num > 12. Conform modelului general, această gospodărie ar trebui, așa cum explică clasificatorul, să obțină un venit sub 50k.
Încercați să vă jucați cu LIME. Veți observa greșeli grave de la clasificator.
Puteți verifica GitHub-ul proprietarului bibliotecii. Acestea oferă documentație suplimentară pentru clasificarea imaginilor și a textului.
Rezumat
Mai jos este o listă cu câteva comenzi utile cu versiunea scikit learn >=0.20
creați setul de date tren/test | stagiarii s-au împărțit |
Construiți o conductă | |
selectați coloana și aplicați transformarea | makecolumntransformer |
tip de transformare | |
standardiza | StandardScaler |
minim maxim | MinMaxScaler |
normaliza | Normalizator |
Imputați valoarea lipsă | imputa |
Convertiți categoric | OneHotEncoder |
Potriviți și transformați datele | potrivi_transforma |
Faceți conducta | make_pipeline |
Model de bază | |
regresie logistică | Regresie logistică |
XGBoost | XGBClassifier |
Rețea neuronală | Clasificator MLPC |
Căutare în grilă | GridSearchCV |
Căutare aleatorie | RandomizedSearchCV |