Урок за Scikit-Learn: Как да инсталирате & примери за Scikit-Learn

Какво е Scikit-learn?

Научете се е с отворен код Python библиотека за машинно обучение. Той поддържа най-съвременни алгоритми като KNN, XGBoost, произволна гора и SVM. Той е изграден върху NumPy. Scikit-learn се използва широко в конкуренцията на Kaggle, както и в известни технологични компании. Помага при предварителна обработка, намаляване на размерността (избор на параметри), класификация, регресия, групиране и избор на модел.

Scikit-learn има най-добрата документация от всички библиотеки с отворен код. Той ви предоставя интерактивна диаграма на https://scikit-learn.org/stable/tutorial/machine_learning_map/index.html.

Как работи Scikit Learn
Как работи Scikit Learn

Scikit-learn не е много труден за използване и осигурява отлични резултати. Обаче scikit learn не поддържа паралелни изчисления. Възможно е да стартирате алгоритъм за дълбоко обучение с него, но това не е оптимално решение, особено ако знаете как да използвате TensorFlow.

Как да изтеглите и инсталирате Scikit-learn

Сега в това Python Урок за Scikit-learn, ще научим как да изтеглим и инсталираме Scikit-learn:

Вариант 1: AWS

scikit-learn може да се използва над AWS. моля вижте Докер изображението, което има предварително инсталиран scikit-learn.

За да използвате версията за разработчици, използвайте командата in Jupyter

import sys
!{sys.executable} -m pip install git+git://github.com/scikit-learn/scikit-learn.git

Вариант 2: Mac или Windows с помощта на Anaconda

За да научите за инсталацията на Anaconda, вижте https://www.guru99.com/download-install-tensorflow.html

Наскоро разработчиците на scikit пуснаха версия за разработка, която се занимава с често срещан проблем, с който се сблъсква текущата версия. Намерихме за по-удобно да използваме версията за разработчици вместо текущата версия.

Как да инсталирате scikit-learn с Conda Environment

Ако сте инсталирали scikit-learn със средата conda, моля, следвайте стъпката за актуализиране до версия 0.20

Стъпка 1) Активирайте среда tensorflow

source activate hello-tf

Стъпка 2) Премахнете scikit lean с помощта на командата conda

conda remove scikit-learn

Стъпка 3) Инсталирайте версията за разработчици.
Инсталирайте версията за разработчици на scikit learn заедно с необходимите библиотеки.

conda install -c anaconda git
pip install Cython
pip install h5py
pip install git+git://github.com/scikit-learn/scikit-learn.git

ЗАБЕЛЕЖКА: Windows потребителят ще трябва да инсталира Microsoft зрителен C++ 14. Можете да го получите от тук

Пример за Scikit-Learn с машинно обучение

Този урок за Scikit е разделен на две части:

  1. Машинно обучение с scikit-learn
  2. Как да се доверите на вашия модел с LIME

Първата част подробно описва как да изградите тръбопровод, да създадете модел и да настроите хиперпараметрите, докато втората част предоставя най-съвременните по отношение на избора на модел.

Стъпка 1) Импортирайте данните

По време на този урок за обучение на Scikit ще използвате набора от данни за възрастни.

За предистория в този набор от данни вижте Ако се интересувате да научите повече за описателната статистика, моля, използвайте инструментите Dive и Overview.

Отнесете този урок научете повече за Dive и Overview

Вие импортирате набора от данни с Pandas. Обърнете внимание, че трябва да преобразувате типа на непрекъснатите променливи в плаващ формат.

Този набор от данни включва осем категорични променливи:

Категоричните променливи са изброени в CATE_FEATURES

  • работен клас
  • образование
  • брачен
  • окупация
  • връзка
  • раса
  • секс
  • родна_страна

освен това шест непрекъснати променливи:

Непрекъснатите променливи са изброени в CONTI_FEATURES

  • възраст
  • fnlwgt
  • образование_номер
  • капиталова_печалба
  • капиталова_загуба
  • часове_седмица

Имайте предвид, че попълваме списъка на ръка, за да имате по-добра представа какви колони използваме. По-бърз начин за изграждане на списък с категорични или непрекъснати е да използвате:

## 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)

Ето кода за импортиране на данните:

# 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()
възраст fnlwgt образование_номер капиталова_печалба капиталова_загуба часове_седмица
броя 32561.000000 3.256100e + 04 32561.000000 32561.000000 32561.000000 32561.000000
означава 38.581647 1.897784e + 05 10.080679 1077.648844 87.303830 40.437456
станд 13.640433 1.055500e + 05 2.572720 7385.292085 402.960219 12.347429
мин 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
макс 90.000000 1.484705e + 06 16.000000 99999.000000 4356.000000 99.000000

Можете да проверите броя на уникалните стойности на функциите native_country. Можете да видите, че само едно домакинство идва от Холандия-Холандия. Това домакинство няма да ни даде никаква информация, но ще го направи чрез грешка по време на обучението.

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

Можете да изключите този неинформативен ред от набора от данни

## Drop Netherland, because only one row
df_train = df_train[df_train.native_country != "Holand-Netherlands"]

След това съхранявате позицията на непрекъснатите характеристики в списък. Ще ви трябва в следващата стъпка за изграждане на тръбопровода.

Кодът по-долу ще премине през всички имена на колони в CONTI_FEATURES и ще получи тяхното местоположение (т.е. неговия номер) и след това ще го добави към списък, наречен 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]

Кодът по-долу върши същата работа като по-горе, но за категориалната променлива. Кодът по-долу повтаря това, което сте правили преди, с изключение на категоричните функции.

## 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]

Можете да разгледате набора от данни. Имайте предвид, че всяка категорична характеристика е низ. Не можете да захранвате модел със стойност на низ. Трябва да трансформирате набора от данни с помощта на фиктивна променлива.

df_train.head(5)

Всъщност трябва да създадете една колона за всяка група във функцията. Първо, можете да изпълните кода по-долу, за да изчислите общия брой необходими колони.

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

Целият набор от данни съдържа 101 групи, както е показано по-горе. Например характеристиките на работната класа имат девет групи. Можете да визуализирате имената на групите със следните кодове

unique() връща уникалните стойности на категориалните характеристики.

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']

Следователно наборът от данни за обучение ще съдържа 101 + 7 колони. Последните седем колони са непрекъснатите характеристики.

Scikit-learn може да се погрижи за конвертирането. Извършва се в две стъпки:

  • Първо, трябва да конвертирате низа в ID. Например State-gov ще има ID 1, Self-emp-not-inc ID 2 и т.н. Функцията LabelEncoder прави това вместо вас
  • Транспонирайте всеки идентификатор в нова колона. Както бе споменато по-горе, наборът от данни има 101 идентификатор на група. Следователно ще има 101 колони, обхващащи групите на всички категорични характеристики. Scikit-learn има функция, наречена OneHotEncoder, която извършва тази операция

Стъпка 2) Създайте комплекта за обучение/тест

Сега, когато наборът от данни е готов, можем да го разделим 80/20.

80 процента за комплекта за обучение и 20 процента за комплекта за тестване.

Можете да използвате train_test_split. Първият аргумент е рамката с данни е характеристиките, а вторият аргумент е рамката с данни на етикета. Можете да посочите размера на тестовия набор с 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)

Стъпка 3) Изградете тръбопровода

Конвейерът улеснява захранването на модела с последователни данни.

Идеята зад нея е да поставите необработените данни в „тръбопровод“, за да извършвате операции.

Например, с текущия набор от данни трябва да стандартизирате непрекъснатите променливи и да конвертирате категоричните данни. Имайте предвид, че можете да извършвате всяка операция вътре в конвейера. Например, ако имате „NA“ в набора от данни, можете да ги замените със средна стойност или медиана. Можете също да създавате нови променливи.

Вие имате избор; кодирайте твърдо двата процеса или създайте конвейер. Първият избор може да доведе до изтичане на данни и да създаде несъответствия с течение на времето. По-добрият вариант е да използвате тръбопровода.

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

Тръбопроводът ще извърши две операции, преди да захрани логистичния класификатор:

  1. Стандартизирайте променливата: `StandardScaler()“
  2. Преобразувайте категоричните характеристики: OneHotEncoder(sparse=False)

Можете да изпълните двете стъпки с помощта на make_column_transformer. Тази функция не е налична в текущата версия на scikit-learn (0.19). Не е възможно с текущата версия да се изпълни енкодерът на етикети и един горещ енкодер в конвейера. Това е една от причините да решим да използваме версията за разработчици.

make_column_transformer е лесен за използване. Трябва да дефинирате кои колони да приложите трансформацията и каква трансформация да оперирате. Например, за да стандартизирате непрекъснатата функция, можете да направите:

  • conti_features, StandardScaler() в make_column_transformer.
    • conti_features: списък с непрекъснатата променлива
    • StandardScaler: стандартизира променливата

Обектът OneHotEncoder вътре в make_column_transformer автоматично кодира етикета.

preprocess = make_column_transformer(
    (conti_features, StandardScaler()),
    ### Need to be numeric not string to specify columns name 
    (categorical_features, OneHotEncoder(sparse=False))
)

Можете да тествате дали тръбопроводът работи с fit_transform. Наборът от данни трябва да има следната форма: 26048, 107

preprocess.fit_transform(X_train).shape
(26048, 107)

Трансформаторът на данни е готов за употреба. Можете да създадете тръбопровода с make_pipeline. След като данните се трансформират, можете да подадете логистичната регресия.

model = make_pipeline(
    preprocess,
    LogisticRegression())

Обучението на модел със scikit-learn е тривиално. Трябва да използвате напасването на обекта, предшествано от тръбопровода, т.е. модел. Можете да отпечатате точността с резултатния обект от библиотеката scikit-learn

model.fit(X_train, y_train)
print("logistic regression score: %f" % model.score(X_test, y_test))
logistic regression score: 0.850891

И накрая, можете да предвидите класовете с predict_proba. Връща вероятността за всеки клас. Обърнете внимание, че сумата е една.

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]])

Стъпка 4) Използване на нашия конвейер при търсене в мрежа

Настройването на хиперпараметъра (променливи, които определят мрежовата структура като скрити единици) може да бъде досадно и изтощително.

Един от начините за оценка на модела може да бъде промяна на размера на набора за обучение и оценка на представянето.

Можете да повторите този метод десет пъти, за да видите показателите за резултата. Това обаче е твърде много работа.

Вместо това scikit-learn предоставя функция за извършване на настройка на параметри и кръстосано валидиране.

Кръстосана проверка

Кръстосаното валидиране означава, че по време на обучението комплектът за обучение се приплъзва n пъти на гънки и след това оценява модела n пъти. Например, ако cv е зададено на 10, наборът за обучение се обучава и оценява десет пъти. Във всеки кръг класификаторът избира произволно девет сгъвания, за да обучи модела, а 10-тото сгъване е предназначено за оценка.

Търсене в мрежата

Всеки класификатор има хиперпараметри за настройка. Можете да опитате различни стойности или да зададете мрежа с параметри. Ако отидете на официалния уебсайт на scikit-learn, можете да видите, че логистичният класификатор има различни параметри за настройка. За да направите обучението по-бързо, избирате да настроите параметъра C. Той контролира параметъра за регулиране. Трябва да е положително. Малка стойност придава по-голяма тежест на регулатора.

Можете да използвате обекта GridSearchCV. Трябва да създадете речник, съдържащ хиперпараметрите за настройка.

Изброявате хиперпараметрите, последвани от стойностите, които искате да опитате. Например, за да настроите параметъра C, използвате:

  • 'logisticregression__C': [0.1, 1.0, 1.0]: Параметърът се предшества от името, с малки букви, на класификатора и две долни черти.

Моделът ще изпробва четири различни стойности: 0.001, 0.01, 0.1 и 1.

Обучавате модела, като използвате 10 сгъвания: cv=10

from sklearn.model_selection import GridSearchCV
# Construct the parameter grid
param_grid = {
    'logisticregression__C': [0.001, 0.01,0.1, 1.0],
    }

Можете да обучите модела с помощта на GridSearchCV с параметъра gri и cv.

# Train the model
grid_clf = GridSearchCV(model,
                        param_grid,
                        cv=10,
                        iid=False)
grid_clf.fit(X_train, y_train)

OUTPUT

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)

За достъп до най-добрите параметри, използвайте best_params_

grid_clf.best_params_

OUTPUT

{'logisticregression__C': 1.0}

След обучение на модела с четири различни стойности на регулация, оптималният параметър е

print("best logistic regression from grid search: %f" % grid_clf.best_estimator_.score(X_test, y_test))

най-добра логистична регресия от търсене в мрежата: 0.850891

За достъп до прогнозираните вероятности:

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 с scikit-learn

Нека опитаме Scikit-learn примери, за да обучим един от най-добрите класификатори на пазара. XGBoost е подобрение спрямо произволната гора. Теоретичната основа на класификатора е извън обхвата на това Python Урок за Scikit. Имайте предвид, че XGBoost спечели много състезания по kaggle. Със среден размер на набора от данни, той може да работи толкова добре, колкото алгоритъм за дълбоко обучение или дори по-добре.

Класификаторът е предизвикателство за обучение, защото има голям брой параметри за настройка. Можете, разбира се, да използвате GridSearchCV, за да изберете параметъра вместо вас.

Вместо това, нека да видим как да използваме по-добър начин за намиране на оптималните параметри. GridSearchCV може да бъде досаден и много дълъг за обучение, ако предавате много стойности. Пространството за търсене расте заедно с броя на параметрите. Предпочитано решение е да използвате RandomizedSearchCV. Този метод се състои в избиране на произволни стойности на всеки хиперпараметър след всяка итерация. Например, ако класификаторът е обучен за 1000 итерации, тогава се оценяват 1000 комбинации. Работи горе-долу като. GridSearchCV

Трябва да импортирате xgboost. Ако библиотеката не е инсталирана, моля, използвайте pip3 install xgboost или

use import sys
!{sys.executable} -m pip install xgboost

In Jupyter заобикаляща среда

След

import xgboost
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import StratifiedKFold

Следващата стъпка в този Scikit Python урокът включва определяне на параметрите за настройка. Можете да се обърнете към официалната документация, за да видите всички параметри за настройка. В името на Python Урок за Sklearn, вие избирате само два хиперпараметъра с по две стойности. XGBoost отнема много време за обучение, колкото повече хиперпараметри в мрежата, толкова по-дълго време трябва да чакате.

params = {
        'xgbclassifier__gamma': [0.5, 1],
        'xgbclassifier__max_depth': [3, 4]
        }

Създавате нов тръбопровод с XGBoost класификатор. Вие избирате да дефинирате 600 оценителя. Имайте предвид, че n_estimators са параметър, който можете да настройвате. Високата стойност може да доведе до прекомерно оборудване. Можете да опитате сами различни стойности, но имайте предвид, че това може да отнеме часове. Използвате стойността по подразбиране за другите параметри

model_xgb = make_pipeline(
    preprocess,
    xgboost.XGBClassifier(
                          n_estimators=600,
                          objective='binary:logistic',
                          silent=True,
                          nthread=1)
)

Можете да подобрите кръстосаното валидиране с кръстосания валидатор Stratified K-Folds. Тук създавате само три гънки, за да ускорите изчислението, но понижавате качеството. Увеличете тази стойност до 5 или 10 у дома, за да подобрите резултатите.

Вие избирате да обучите модела през четири повторения.

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)

Рандомизираното търсене е готово за използване, можете да обучите модела

#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)

Както можете да видите, XGBoost има по-добър резултат от предишната logisitc регресия.

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)

Създайте DNN с MLPClassifier в scikit-learn

И накрая, можете да тренирате алгоритъм за дълбоко обучение със scikit-learn. Методът е същият като при другия класификатор. Класификаторът е наличен в MLPClassifier.

from sklearn.neural_network import MLPClassifier

Вие дефинирате следния алгоритъм за дълбоко обучение:

  • Решател на Адам
  • Функция за активиране на Relu
  • Алфа = 0.0001
  • размер на партидата 150
  • Два скрити слоя съответно със 100 и 50 неврона
model_dnn = make_pipeline(
    preprocess,
    MLPClassifier(solver='adam',
                  alpha=0.0001,
                  activation='relu',
                    batch_size=150,
                    hidden_layer_sizes=(200, 100),
                    random_state=1))

Можете да промените броя на слоевете, за да подобрите модела

model_dnn.fit(X_train, y_train)
  print("DNN regression score: %f" % model_dnn.score(X_test, y_test))

DNN регресионен резултат: 0.821253

LIME: Доверете се на своя модел

Сега, когато имате добър модел, имате нужда от инструмент, за да му се доверите. машина обучение Алгоритъмът, особено случайната гора и невронната мрежа, са известни като алгоритъм на черна кутия. Кажете по друг начин, работи, но никой не знае защо.

Трима изследователи са измислили страхотен инструмент, за да видят как компютърът прави прогноза. Документът се казва Защо трябва да ви вярвам?

Те разработиха алгоритъм на име Локални интерпретируеми модели-агностични обяснения (LIME).

Вземете пример:

понякога не знаете дали можете да се доверите на прогноза от машинно обучение:

Един лекар, например, не може да се довери на диагноза само защото компютърът го е казал. Също така трябва да знаете дали можете да се доверите на модела, преди да го пуснете в производство.

Представете си, че можем да разберем защо всеки класификатор прави прогноза дори за невероятно сложни модели като невронни мрежи, произволни гори или svms с всяко ядро

ще стане по-достъпно за доверие в прогноза, ако можем да разберем причините зад нея. От примера с лекаря, ако моделът му каже кои симптоми са съществени, ще му се доверите, също така е по-лесно да разберете дали не трябва да се доверявате на модела.

Lime може да ви каже какви функции влияят на решенията на класификатора

Подготовка на данните

Това са няколко неща, които трябва да промените, за да работите с LIME питон. На първо място, трябва да инсталирате вар в терминала. Можете да използвате pip install lime

Lime използва обект LimeTabularExplainer, за да приближи модела локално. Този обект изисква:

  • набор от данни във формат numpy
  • Името на функциите: имена_на_функции
  • Името на класовете: class_names
  • Индексът на колоната на категорийните признаци: категорични_характеристики
  • Името на групата за всяка категорична характеристика: categorical_names

Създайте набор от влакове numpy

Можете да копирате и конвертирате df_train от pandas в буца много лесно

df_train.head(5)
# Create numpy data
df_lime = df_train
df_lime.head(3)

Вземете името на класа Етикетът е достъпен с обекта unique(). Трябва да видите:

  • „<=50K“
  • '>50K'
# Get the class name
class_names = df_lime.label.unique()
class_names
array(['<=50K', '>50K'], dtype=object)

индекс на колоната на категориалните характеристики

Можете да използвате метода, който сте използвали преди, за да получите името на групата. Вие кодирате етикета с LabelEncoder. Повтаряте операцията върху всички категорични характеристики.

## 
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

Сега, когато наборът от данни е готов, можете да конструирате различния набор от данни, както е показано в примерите за обучение на Scikit по-долу. Вие всъщност трансформирате данните извън тръбопровода, за да избегнете грешки с LIME. Наборът за обучение в LimeTabularExplainer трябва да бъде numpy масив без низ. С метода по-горе имате вече конвертиран набор от данни за обучение.

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)

Можете да направите тръбопровода с оптимални параметри от 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))])

Получаваш предупреждение. Предупреждението обяснява, че не е необходимо да създавате енкодер на етикети преди конвейера. Ако не искате да използвате LIME, можете да използвате метода от първата част на урока за машинно обучение със Scikit-learn. В противен случай можете да продължите с този метод, първо да създадете кодиран набор от данни, да зададете получаване на горещия енкодер в конвейера.

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)

Преди да използваме LIME в действие, нека създадем numpy масив с характеристиките на грешната класификация. Можете да използвате този списък по-късно, за да получите представа какво е подвело класификатора.

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)

Създавате ламбда функция, за да извлечете прогнозата от модела с новите данни. Скоро ще ви трябва.

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]])

Преобразувате рамката от данни на pandas в масив 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)

Нека изберем произволно домакинство от набора от тестове и да видим прогнозата на модела и как компютърът е направил своя избор.

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])

Можете да използвате обяснителя с expand_instance, за да проверите обяснението зад модела

exp = explainer.explain_instance(X_test_lime[i], predict_fn, num_features=6)
exp.show_in_notebook(show_all=False)

Подготовка на данните

Виждаме, че класификаторът е предвидил правилно домакинството. Доходите наистина са над 50 хиляди.

Първото нещо, което можем да кажем е, че класификаторът не е толкова сигурен относно прогнозираните вероятности. Машината прогнозира, че домакинството има доход над 50 хиляди с вероятност от 64%. Тези 64% се състоят от капиталова печалба и брак. Синият цвят допринася отрицателно за положителния клас, а оранжевата линия - положително.

Класификаторът е объркан, тъй като капиталовата печалба на това домакинство е нула, докато капиталовата печалба обикновено е добър показател за богатство. Освен това домакинството работи по-малко от 40 часа седмично. Възрастта, професията и полът допринасят положително за класификатора.

Ако семейното положение беше необвързано, класификаторът щеше да предвиди доход под 50k (0.64-0.18 = 0.46)

Можем да опитаме с друго домакинство, което е грешно класифицирано

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)

Подготовка на данните

Класификаторът прогнозира доход под 50k, докато не е вярно. Това домакинство изглежда странно. Няма нито капиталова печалба, нито капиталова загуба. Той е разведен и е на 60 години и е образован човек, т.е. образование_num > 12. Според общия модел това домакинство трябва, както е обяснено от класификатора, да получи доход под 50k.

Опитвате се да си играете с LIME. Ще забележите груби грешки от класификатора.

Можете да проверите GitHub на собственика на библиотеката. Те предоставят допълнителна документация за класификация на изображения и текст.

Oбобщение

По-долу е даден списък с някои полезни команди с scikit learn версия >=0.20

създаване на набор от данни за влак/тест стажантите се разделят
Изградете тръбопровод
изберете колоната и приложете трансформацията makecolumntransformer
тип трансформация
стандартизирам StandardScaler
мин макс MinMaxScaler
нормализирам Нормализатор
Приписване на липсваща стойност вменявам
Преобразувайте категорично OneHotEncoder
Нагласете и трансформирайте данните fit_transform
Направи тръбопровода make_pipeline
Основен модел
логистична регресия Логистична регресия
XGBoost XGB Класификатор
Невронна мрежа MLPClassifier
Търсене в мрежата GridSearchCV
Случайно търсене RandomizedSearchCV

Обобщете тази публикация с: