Výukový program Scikit-Learn: Jak nainstalovat a příklady Scikit-Learn
Co je to Scikit-learn?
Scikit-učit se je open-source Python knihovna pro strojové učení. Podporuje nejmodernější algoritmy, jako je KNN, XGBoost, random forest a SVM. Je postaven na vrcholu NumPy. Scikit-learn je široce používán v soutěži Kaggle i v předních technologických společnostech. Pomáhá při předzpracování, redukci rozměrů (výběr parametrů), klasifikaci, regresi, shlukování a výběru modelu.
Scikit-learn má nejlepší dokumentaci ze všech open-source knihoven. Poskytuje vám interaktivní graf na adrese https://scikit-learn.org/stable/tutorial/machine_learning_map/index.html.

Scikit-learn není příliš náročný na použití a poskytuje vynikající výsledky. Nicméně scikit learn nepodporuje paralelní výpočty. Je možné s ním spustit algoritmus hlubokého učení, ale není to optimální řešení, zvláště pokud víte, jak používat TensorFlow.
Jak stáhnout a nainstalovat Scikit-learn
Nyní v tomto Python Scikit-learn tutoriál, naučíme se, jak stáhnout a nainstalovat Scikit-learn:
Možnost 1: AWS
scikit-learn lze použít přes AWS. Prosím odkázat Obraz dockeru, který má předinstalovaný scikit-learn.
Chcete-li použít vývojářskou verzi, použijte příkaz in Jupyter
import sys !{sys.executable} -m pip install git+git://github.com/scikit-learn/scikit-learn.git
Možnost 2: Mac nebo Mac Windows pomocí Anacondy
Chcete-li se dozvědět o instalaci Anaconda, viz https://www.guru99.com/download-install-tensorflow.html
Nedávno vývojáři scikit vydali vývojovou verzi, která řeší běžný problém, kterému čelí současná verze. Zjistili jsme, že je pohodlnější používat vývojářskou verzi místo aktuální verze.
Jak nainstalovat scikit-learn s prostředím Conda
Pokud jste si nainstalovali scikit-learn s prostředím conda, postupujte podle kroků pro aktualizaci na verzi 0.20
Krok 1) Aktivujte prostředí tensorflow
source activate hello-tf
Krok 2) Odstraňte scikit lean pomocí příkazu conda
conda remove scikit-learn
Krok 3) Nainstalujte vývojářskou verzi.
Nainstalujte vývojářskou verzi scikit learn spolu s potřebnými knihovnami.
conda install -c anaconda git pip install Cython pip install h5py pip install git+git://github.com/scikit-learn/scikit-learn.git
POZNÁMKA: Windows uživatel bude muset nainstalovat Microsoft Vizuální C++ 14. Můžete to získat od zde
Příklad Scikit-Learn se strojovým učením
Tento tutoriál Scikit je rozdělen do dvou částí:
- Strojové učení se scikit-learn
- Jak důvěřovat svému modelu s LIME
První část podrobně popisuje, jak postavit potrubí, vytvořit model a vyladit hyperparametry, zatímco druhá část poskytuje nejmodernější z hlediska výběru modelu.
Krok 1) Importujte data
Během tohoto výukového programu Scikit budete používat datovou sadu pro dospělé.
Pozadí v tomto datovém souboru naleznete v případě, že se chcete dozvědět více o popisných statistikách, použijte nástroje Dive a Overview.
Odkázat tento výukový program zjistěte více o ponoru a přehledu
Importujete datovou sadu pomocí Pandas. Všimněte si, že musíte převést typ spojitých proměnných do formátu float.
Tato datová sada obsahuje osm kategorických proměnných:
Kategorické proměnné jsou uvedeny v CATE_FEATURES
- pracovní třída
- vzdělání
- manželský
- povolání
- vztah
- závod
- pohlaví
- rodná země
navíc šest spojitých proměnných:
Spojité proměnné jsou uvedeny v CONTI_FEATURES
- stáří
- fnlwgt
- vzdělání_číslo
- kapitálový zisk
- kapitálová_ztráta
- hodiny_týden
Všimněte si, že seznam vyplňujeme ručně, abyste měli lepší představu o tom, jaké sloupce používáme. Rychlejší způsob, jak vytvořit seznam kategorických nebo spojitých, je použít:
## 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)
Zde je kód pro import dat:
# 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()
stáří | fnlwgt | vzdělání_číslo | kapitálový zisk | kapitálová_ztráta | hodiny_týden | |
---|---|---|---|---|---|---|
počítat | 32561.000000 | 3.256100e + 04 | 32561.000000 | 32561.000000 | 32561.000000 | 32561.000000 |
střední | 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 |
min | 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 |
Můžete zkontrolovat počet jedinečných hodnot funkcí native_country. Vidíte, že pouze jedna domácnost pochází z Holandska-Nizozemí. Tato domácnost nám žádné informace nepřinese, ale dojde k chybě během školení.
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
Tento neinformativní řádek můžete z datové sady vyloučit
## Drop Netherland, because only one row df_train = df_train[df_train.native_country != "Holand-Netherlands"]
Dále uložíte polohu spojitých prvků do seznamu. Budete jej potřebovat v dalším kroku pro stavbu potrubí.
Níže uvedený kód bude opakovat názvy všech sloupců v CONTI_FEATURES a získá jeho umístění (tj. jeho číslo) a poté jej připojí k seznamu s názvem 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]
Níže uvedený kód dělá stejnou práci jako výše, ale pro kategorickou proměnnou. Níže uvedený kód opakuje to, co jste udělali dříve, s výjimkou kategorických funkcí.
## 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]
Můžete se podívat na datovou sadu. Všimněte si, že každý kategorický prvek je řetězec. Model nelze napájet hodnotou řetězce. Musíte transformovat datovou sadu pomocí fiktivní proměnné.
df_train.head(5)
Ve skutečnosti musíte vytvořit jeden sloupec pro každou skupinu v prvku. Nejprve můžete spustit kód níže a vypočítat celkový počet potřebných sloupců.
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
Celá datová sada obsahuje 101 skupin, jak je uvedeno výše. Například funkce pracovní třídy mají devět skupin. Názvy skupin si můžete vizualizovat pomocí následujících kódů
unique() vrací jedinečné hodnoty kategoriálních funkcí.
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']
Tréninková datová sada tedy bude obsahovat 101 + 7 sloupců. Posledních sedm sloupců jsou souvislé prvky.
O konverzi se může postarat Scikit-learn. Provádí se ve dvou krocích:
- Nejprve musíte převést řetězec na ID. Například stát-gov bude mít ID 1, Self-emp-not-inc ID 2 a tak dále. Funkce LabelEncoder to udělá za vás
- Transponujte každé ID do nového sloupce. Jak již bylo zmíněno, datová sada má 101 ID skupiny. Proto zde bude 101 sloupců zachycujících všechny skupiny prvků kategorií. Scikit-learn má funkci nazvanou OneHotEncoder, která tuto operaci provádí
Krok 2) Vytvořte vlak/testovací sadu
Nyní, když je datová sada připravena, můžeme ji rozdělit v poměru 80/20.
80 procent pro tréninkovou sadu a 20 procent pro testovací sadu.
Můžete použít train_test_split. První argument je dataframe is the features a druhý argument je label dataframe. Velikost testovací sady můžete určit pomocí 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)
Krok 3) Postavte potrubí
Potrubí usnadňuje dodávání modelu konzistentními daty.
Základní myšlenkou je umístit nezpracovaná data do „potrubí“ pro provádění operací.
Například s aktuální datovou sadou potřebujete standardizovat spojité proměnné a převést kategorická data. Všimněte si, že uvnitř potrubí můžete provádět jakoukoli operaci. Pokud například máte v sadě dat „NA“, můžete je nahradit průměrem nebo mediánem. Můžete také vytvářet nové proměnné.
Máte na výběr; pevně zakódujte dva procesy nebo vytvořte kanál. První volba může vést k úniku dat a vytvářet nekonzistence v průběhu času. Lepší možností je použít potrubí.
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
Potrubí provede dvě operace, než naplní logistický klasifikátor:
- Standardizujte proměnnou: „StandardScaler()“
- Převeďte kategorické funkce: OneHotEncoder(sparse=False)
Tyto dva kroky můžete provést pomocí make_column_transformer. Tato funkce není v aktuální verzi scikit-learn (0.19) dostupná. V aktuální verzi není možné provádět kodér štítků a jeden hot kodér v potrubí. To je jeden z důvodů, proč jsme se rozhodli použít vývojářskou verzi.
make_column_transformer se snadno používá. Musíte definovat, které sloupce použít transformaci a jakou transformaci provozovat. Chcete-li například standardizovat spojitou funkci, můžete:
- conti_features, StandardScaler() uvnitř make_column_transformer.
- conti_features: seznam se spojitou proměnnou
- StandardScaler: standardizace proměnné
Objekt OneHotEncoder uvnitř make_column_transformer automaticky zakóduje štítek.
preprocess = make_column_transformer( (conti_features, StandardScaler()), ### Need to be numeric not string to specify columns name (categorical_features, OneHotEncoder(sparse=False)) )
Můžete otestovat, zda potrubí funguje pomocí fit_transform. Soubor dat by měl mít následující tvar: 26048, 107
preprocess.fit_transform(X_train).shape
(26048, 107)
Datový transformátor je připraven k použití. Potrubí můžete vytvořit pomocí make_pipeline. Jakmile jsou data transformována, můžete napájet logistickou regresi.
model = make_pipeline( preprocess, LogisticRegression())
Trénink modelu pomocí scikit-learn je triviální. Musíte použít přizpůsobení objektu, kterému předchází potrubí, tj. model. Přesnost můžete vytisknout pomocí objektu skóre z knihovny scikit-learn
model.fit(X_train, y_train) print("logistic regression score: %f" % model.score(X_test, y_test))
logistic regression score: 0.850891
Nakonec můžete předpovídat třídy pomocí forecast_proba. Vrací pravděpodobnost pro každou třídu. Všimněte si, že se to rovná jedné.
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]])
Krok 4) Pomocí našeho potrubí při vyhledávání v mřížce
Ladění hyperparametru (proměnné, které určují strukturu sítě jako skryté jednotky) může být zdlouhavé a vyčerpávající.
Jedním ze způsobů hodnocení modelu by mohla být změna velikosti tréninkové sady a hodnocení výkonů.
Tuto metodu můžete desetkrát zopakovat, abyste viděli metriky skóre. Je to však příliš mnoho práce.
Místo toho scikit-learn poskytuje funkci pro ladění parametrů a křížovou validaci.
Křížová validace
Cross-Validation znamená, že během trénování se trénovací množina sklouzává nkrát v záhybech a poté model nkrát vyhodnocuje. Pokud je například cv nastaveno na 10, trénovací sada se natrénuje a vyhodnotí desetkrát. V každém kole si klasifikátor náhodně vybere devět záhybů pro trénování modelu a 10. záhyb je určen k vyhodnocení.
Vyhledávání v mřížce
Každý klasifikátor má hyperparametry k vyladění. Můžete vyzkoušet různé hodnoty nebo můžete nastavit mřížku parametrů. Pokud přejdete na oficiální web scikit-learn, můžete vidět, že logistický klasifikátor má různé parametry k vyladění. Pro urychlení tréninku zvolíte vyladění parametru C. Ovládá parametr regularizace. Mělo by to být pozitivní. Malá hodnota dává větší váhu regularizátoru.
Můžete použít objekt GridSearchCV. Musíte vytvořit slovník obsahující hyperparametry k ladění.
Vypíšete hyperparametry následované hodnotami, které chcete vyzkoušet. Chcete-li například vyladit parametr C, použijte:
- 'logisticregression__C': [0.1, 1.0, 1.0]: Parametru předchází název klasifikátoru v malých písmenech a dvě podtržítka.
Model vyzkouší čtyři různé hodnoty: 0.001, 0.01, 0.1 a 1.
Model trénujete pomocí 10 záhybů: cv=10
from sklearn.model_selection import GridSearchCV # Construct the parameter grid param_grid = { 'logisticregression__C': [0.001, 0.01,0.1, 1.0], }
Model můžete trénovat pomocí GridSearchCV s parametrem gri a cv.
# Train the model grid_clf = GridSearchCV(model, param_grid, cv=10, iid=False) grid_clf.fit(X_train, y_train)
VÝSTUP
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)
Pro přístup k nejlepším parametrům použijte best_params_
grid_clf.best_params_
VÝSTUP
{'logisticregression__C': 1.0}
Po natrénování modelu se čtyřmi různými hodnotami regularizace je optimální parametr
print("best logistic regression from grid search: %f" % grid_clf.best_estimator_.score(X_test, y_test))
nejlepší logistická regrese z vyhledávání v mřížce: 0.850891
Chcete-li získat přístup k předpokládaným pravděpodobnostem:
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 se scikit-learn
Zkusme příklady Scikit-learn, abychom vytrénovali jeden z nejlepších klasifikátorů na trhu. XGBoost je vylepšení oproti náhodnému lese. Teoretické pozadí klasifikátoru mimo rámec tohoto Python Scikit tutoriál. Mějte na paměti, že XGBoost vyhrál spoustu kaggle soutěží. S průměrnou velikostí datové sady může fungovat stejně dobře jako algoritmus hlubokého učení nebo dokonce lépe.
Klasifikátor je náročný na trénování, protože má vysoký počet parametrů k vyladění. Pro výběr parametru můžete samozřejmě použít GridSearchCV.
Místo toho se podívejme, jak využít lepší způsob, jak najít optimální parametry. GridSearchCV může být zdlouhavé a velmi zdlouhavé na trénování, pokud překonáte mnoho hodnot. Vyhledávací prostor roste spolu s počtem parametrů. Vhodnějším řešením je použití RandomizedSearchCV. Tato metoda spočívá v náhodném výběru hodnot každého hyperparametru po každé iteraci. Pokud je například klasifikátor trénován více než 1000 iterací, vyhodnotí se 1000 kombinací. Funguje to víceméně jako. GridSearchCV
Musíte importovat xgboost. Pokud knihovna není nainstalována, použijte prosím pip3 install xgboost nebo
use import sys !{sys.executable} -m pip install xgboost
In Jupyter životní prostředí
Dále
import xgboost from sklearn.model_selection import RandomizedSearchCV from sklearn.model_selection import StratifiedKFold
Další krok v tomto Scikitu Python výukový program obsahuje specifikaci parametrů k ladění. Všechny parametry k vyladění naleznete v oficiální dokumentaci. V zájmu Python Sklearn tutoriál, vyberete pouze dva hyperparametry se dvěma hodnotami každý. Trénink XGBoost zabere spoustu času, čím více hyperparametrů v mřížce, tím delší dobu musíte čekat.
params = { 'xgbclassifier__gamma': [0.5, 1], 'xgbclassifier__max_depth': [3, 4] }
Vytvoříte nový kanál s klasifikátorem XGBoost. Můžete definovat 600 odhadů. Všimněte si, že n_estimators jsou parametry, které můžete vyladit. Vysoká hodnota může vést k nadměrnému vybavení. Můžete sami vyzkoušet různé hodnoty, ale uvědomte si, že to může trvat hodiny. Pro ostatní parametry použijete výchozí hodnotu
model_xgb = make_pipeline( preprocess, xgboost.XGBClassifier( n_estimators=600, objective='binary:logistic', silent=True, nthread=1) )
Křížovou validaci můžete zlepšit pomocí křížového validátoru Stratified K-Folds. Zde vytvoříte pouze tři záhyby, abyste urychlili výpočet, ale snížili kvalitu. Zvyšte tuto hodnotu na 5 nebo 10 doma, abyste zlepšili výsledky.
Můžete si vybrat trénování modelu ve čtyřech iteracích.
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)
Náhodné vyhledávání je připraveno k použití, můžete model trénovat
#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)
Jak můžete vidět, XGBoost má lepší skóre než předchozí logisitc regrese.
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)
Vytvořte DNN pomocí MLPClassifier ve scikit-learn
Konečně můžete trénovat algoritmus hlubokého učení pomocí scikit-learn. Metoda je stejná jako u druhého klasifikátoru. Klasifikátor je k dispozici na MLPClassifier.
from sklearn.neural_network import MLPClassifier
Definujete následující algoritmus hlubokého učení:
- Adam řešitel
- Funkce aktivace Relu
- Alfa = 0.0001
- velikost dávky 150
- Dvě skryté vrstvy se 100 a 50 neurony
model_dnn = make_pipeline( preprocess, MLPClassifier(solver='adam', alpha=0.0001, activation='relu', batch_size=150, hidden_layer_sizes=(200, 100), random_state=1))
Pro vylepšení modelu můžete změnit počet vrstev
model_dnn.fit(X_train, y_train) print("DNN regression score: %f" % model_dnn.score(X_test, y_test))
DNN regresní skóre: 0.821253
LIME: Důvěřujte svému modelu
Nyní, když máte dobrý model, potřebujete nástroj, abyste mu důvěřovali. Strojové učení Algoritmus, zejména náhodný les a neuronová síť, jsou známy jako algoritmus černé skříňky. Řekni to jinak, funguje to, ale nikdo neví proč.
Tři výzkumníci přišli se skvělým nástrojem, jak zjistit, jak počítač předpovídá. List se jmenuje Proč bych ti měl věřit?
Vyvinuli algoritmus s názvem Local Interpretable Model-Agnostic Explanations (LIME).
Vezměte si příklad:
někdy nevíte, jestli můžete věřit predikci strojového učení:
Lékař například nemůže věřit diagnóze jen proto, že to řekl počítač. Před uvedením do výroby musíte také vědět, zda modelu můžete důvěřovat.
Představte si, že dokážeme pochopit, proč jakýkoli klasifikátor předpovídá i neuvěřitelně komplikované modely, jako jsou neuronové sítě, náhodné lesy nebo svms s jakýmkoli jádrem
bude přístupnější důvěřovat předpovědi, pokud pochopíme její důvody. Z příkladu s lékařem, pokud mu model řekl, které příznaky jsou zásadní, důvěřovali byste mu, je také snazší zjistit, zda byste modelu neměli věřit.
Lime vám může říct, jaké vlastnosti ovlivňují rozhodnutí klasifikátoru
Příprava dat
Je to několik věcí, které musíte změnit, abyste mohli provozovat LIME krajta. Nejprve musíte do terminálu nainstalovat vápno. Můžete použít pip install vápno
Lime využívá objekt LimeTabularExplainer k místní aproximaci modelu. Tento objekt vyžaduje:
- datovou sadu ve formátu numpy
- Název funkcí: feature_names
- Název tříd: class_names
- Index sloupce kategorických prvků: categorical_features
- Název skupiny pro každý kategorický prvek: categorical_names
Vytvořte nudnou vlakovou soupravu
Můžete zkopírovat a převést df_train z pand do otupělý velmi lehce
df_train.head(5) # Create numpy data df_lime = df_train df_lime.head(3)
Získejte název třídy Štítek je přístupný pomocí objektu unique(). Měl bys vidět:
- '<=50 XNUMX'
- '>50 XNUMX'
# Get the class name class_names = df_lime.label.unique() class_names
array(['<=50K', '>50K'], dtype=object)
index sloupce kategoriálních znaků
K získání názvu skupiny můžete použít metodu, kterou jste před tím naklonili. Štítek zakódujete pomocí LabelEncoder. Opakujete operaci se všemi kategorickými prvky.
## 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
Nyní, když je datová sada připravena, můžete sestavit jinou datovou sadu, jak je uvedeno níže v příkladech učení Scikit. Ve skutečnosti transformujete data mimo potrubí, abyste se vyhnuli chybám s LIME. Tréninková sada v LimeTabularExplainer by měla být numpy pole bez řetězce. Pomocí výše uvedené metody máte již trénovací datovou sadu převedenou.
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)
Z XGBoost můžete udělat potrubí s optimálními parametry
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))])
Dostanete varování. Varování vysvětluje, že není nutné vytvářet kodér štítků před kanálem. Pokud nechcete používat LIME, můžete použít metodu z první části výukového programu Machine Learning with Scikit-learn. V opačném případě můžete zůstat u této metody, nejprve vytvořte kódovanou datovou sadu, nastavte kodér get hot one v rámci kanálu.
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)
Než použijeme LIME v akci, vytvořte numpy pole s vlastnostmi nesprávné klasifikace. Tento seznam můžete použít později, abyste získali představu o tom, co klasifikátor klame.
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)
Vytvoříte funkci lambda pro načtení predikce z modelu s novými daty. Brzy to budete potřebovat.
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]])
Převedete datový rámec pandy na numpy pole
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)
Vyberme si náhodnou domácnost z testovací sady a podívejme se na předpověď modelu a na to, jak si počítač vybral.
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])
Ke kontrole vysvětlení za modelem můžete použít vysvětlující modul s vysvětlením_instance
exp = explainer.explain_instance(X_test_lime[i], predict_fn, num_features=6) exp.show_in_notebook(show_all=False)
Vidíme, že klasifikátor předpověděl domácnost správně. Příjem je skutečně přes 50 tis.
První věc, kterou můžeme říci, je, že klasifikátor si není tak jistý předpovídanými pravděpodobnostmi. Automat předpovídá, že domácnost má příjem nad 50 tisíc s pravděpodobností 64 %. Těchto 64 % tvoří kapitálový zisk a manželství. Modrá barva přispívá negativně k pozitivní třídě a oranžová linie pozitivně.
Klasifikátor je zmatený, protože kapitálový zisk této domácnosti je nulový, zatímco kapitálový zisk je obvykle dobrým prediktorem bohatství. Kromě toho domácnost pracuje méně než 40 hodin týdně. Věk, povolání a pohlaví přispívají ke klasifikátoru pozitivně.
Pokud by byl rodinný stav svobodný, klasifikátor by předpověděl příjem pod 50 0.64 (0.18-0.46 = XNUMX)
Můžeme to zkusit s jinou domácností, která byla špatně zařazena
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)
Klasifikátor předpověděl příjem pod 50 60, ačkoli to není pravda. Tahle domácnost vypadá divně. Nemá kapitálový zisk, ani kapitálovou ztrátu. Je rozvedený, je mu 12 let a je to vzdělaný člověk, tj. vzdělání_číslo > 50. Podle celkového vzorce by tato domácnost měla, jak vysvětluje klasifikátor, dostávat příjem pod XNUMX tisíc.
Zkuste si pohrát s LIME. U klasifikátoru si všimnete hrubých chyb.
Můžete zkontrolovat GitHub vlastníka knihovny. Poskytují další dokumentaci pro klasifikaci obrázků a textu.
Shrnutí
Níže je uveden seznam některých užitečných příkazů ve verzi scikit learn >=0.20
vytvořit datovou sadu vlaku/testu | stážisté se rozdělí |
Vybudujte potrubí | |
vyberte sloupec a použijte transformaci | makecolumntransformer |
typ transformace | |
standardizovat | StandardScaler |
min. max | MinMaxScaler |
Normalizovat | Normalizátor |
Imputujte chybějící hodnotu | přičítat |
Převést kategorické | OneHotEncoder |
Přizpůsobte a transformujte data | fit_transform |
Vytvořte potrubí | make_pipeline |
Základní model | |
logistické regrese | Logistická regrese |
XGBoost | XGBClassifier |
Neuronová síť | Klasifikátor MLPC |
Vyhledávání v mřížce | GridSearchCV |
Randomizované vyhledávání | RandomizedSearchCV |