Учебник Scikit-Learn: как установить и примеры Scikit-Learn

by moiseevrus

Что такое 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 не очень сложен в использовании и дает отличные результаты. Однако scikitlearn не поддерживает параллельные вычисления. С ним можно запустить алгоритм глубокого обучения, но это не оптимальное решение, особенно если вы знаете, как использовать TensorFlow.

Как скачать и установить Scikit-learn

Теперь в этом руководстве по Python Scikit-learn мы узнаем, как загрузить и установить Scikit-learn:

Вариант 1: АМС

scikit-learn можно использовать через AWS. Пожалуйста , обратитесь к образу докера с предустановленным scikit-learn.

Чтобы использовать версию для разработчиков, используйте команду в 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

Если вы установили scikit-learn со средой conda, выполните шаг для обновления до версии 0.20.

Шаг 1) Активируйте среду тензорного потока

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 Visual C++ 14. Вы можете скачать его здесь .

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

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

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

В первой части подробно рассказывается, как построить конвейер, создать модель и настроить гиперпараметры, а во второй части представлены самые современные сведения о выборе модели.

Шаг 1) Импорт данных

В этом учебном пособии по Scikit вы будете использовать набор данных для взрослых.

Для получения дополнительной информации об этом наборе данных см. Если вам интересно узнать больше об описательной статистике, используйте инструменты «Погружение» и «Обзор».

Обратитесь к этому руководству, чтобы узнать больше о погружении и обзоре.

Вы импортируете набор данных с помощью Pandas. Обратите внимание, что вам необходимо преобразовать тип непрерывных переменных в формат с плавающей запятой.

Обратите внимание, что мы заполняем список вручную, чтобы вы лучше понимали, какие столбцы мы используем. Более быстрый способ построить список категориальных или непрерывных состоит в том, чтобы использовать:

## 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')
возраст фнлвгт Education_num прирост капитала капитал_убыток часы_неделя
считать 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

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 группу, как показано выше. Например, характеристики рабочего класса имеют девять групп. Вы можете визуализировать название групп со следующими кодами

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

unique() возвращает уникальные значения категориальных признаков.

Следовательно, обучающий набор данных будет содержать 101 + 7 столбцов. Последние семь столбцов — это непрерывные функции.

Scikit-learn может позаботиться о преобразовании. Делается в два этапа:

  • Во-первых, вам нужно преобразовать строку в идентификатор. Например, State-gov будет иметь идентификатор 1, идентификатор Self-emp-not-inc 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 тривиально. Вам нужно использовать подгонку объекта, которому предшествует конвейер, т.е. модель. Вы можете распечатать точность с помощью объекта score из библиотеки 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)

ВЫХОД


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_

ВЫХОД

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


В среде Юпитера

Следующий,

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 имеет лучший результат, чем предыдущая логистическая регрессия.


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

LIME: доверяйте своей модели

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

Три исследователя придумали отличный инструмент, чтобы увидеть, как компьютер делает прогноз. Статья называется «Почему я должен вам доверять?».

Они разработали алгоритм под названием Local Interpretable Model-Agnostic Explanations (LIME) .

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

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

Врач, например, не может доверять диагнозу только потому, что так сказал компьютер. Вы также должны знать, можете ли вы доверять модели, прежде чем запускать ее в производство.

Представьте, что мы можем понять, почему любой классификатор делает прогноз даже невероятно сложных моделей, таких как нейронные сети, случайные леса или svms с любым ядром.

станет более доступным для доверия прогнозу, если мы сможем понять причины, стоящие за ним. Из примера с врачом, если бы модель сказала ему, какие симптомы существенны, вы бы ей доверились, также легче понять, не стоит ли вам доверять модели.

Lime может подсказать, какие функции влияют на решения классификатора.

Подготовка данных

Это пара вещей, которые вам нужно изменить, чтобы запустить LIME с python . В первую очередь нужно установить лайм в терминал. Вы можете использовать pip install лайм

Lime использует объект LimeTabularExplainer для локальной аппроксимации модели. Этот объект требует:

  • набор данных в формате numpy
  • Название функций: feature_names
  • Название классов: class_names
  • Индекс столбца категориальных признаков: categorical_features
  • Имя группы для каждой категориальной функции: categorical_names

Создать набор поездов numpy

Вы можете очень легко скопировать и преобразовать df_train из pandas в numpy.

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

Получить имя класса Метка доступна с помощью объекта unique(). Тебе следует увидеть:

  • ‘<=50K’
  • ‘> 50 тыс.’
# 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 должен быть пустым массивом без строки. С помощью описанного выше метода у вас уже есть преобразованный набор обучающих данных.

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


Вы можете использовать объяснитель с объяснением_экземпляра, чтобы проверить объяснение модели.

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

Учебное пособие по Scikit-Learn

Мы видим, что классификатор правильно предсказал домохозяйство. Доход, действительно, выше 50 тыс.

Первое, что мы можем сказать, это то, что классификатор не так уж уверен в предсказанных вероятностях. Машина предсказывает, что домохозяйство имеет доход более 50 тысяч с вероятностью 64%. Эти 64% состоят из прироста капитала и брака. Синий цвет отрицательно влияет на положительный класс, а оранжевая линия — положительно.

Классификатор сбивает с толку, потому что прирост капитала этого домохозяйства равен нулю, в то время как прирост капитала обычно является хорошим предиктором богатства. Кроме того, домохозяйство работает менее 40 часов в неделю. Возраст, род занятий и пол положительно влияют на классификатор.

Если бы семейное положение было холостым, классификатор предсказал бы доход ниже 50 тысяч (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)

Scikit-Learn Tutorial

Классификатор предсказывал доход ниже 50 тысяч, но это неправда. Этот дом кажется странным. Он не имеет ни прироста капитала, ни убытка капитала. Он разведен, ему 60 лет, и он образованный человек, т.е. education_num > 12. По общей схеме это домохозяйство должно, как поясняет классификатор, получать доход ниже 50к.

Вы пытаетесь поиграть с LIME. Вы заметите грубые ошибки классификатора.

Вы можете проверить GitHub владельца библиотеки. Они предоставляют дополнительную документацию для классификации изображений и текста.

Резюме

Ниже приведен список некоторых полезных команд с версией scikit Learn >=0.20.

создать набор данных поезда/теста трейни разделились
Построить трубопровод
выберите столбец и примените преобразование сделатьколоннтрансформер
тип преобразования
стандартизировать Стандартный масштабатор
мин Макс МинМаксСкалер
нормализовать нормализатор
Вменить отсутствующее значение Импутер
Преобразовать категориальный OneHotEncoder
Подгонка и преобразование данных fit_transform
Сделать конвейер make_pipeline
Базовая модель
логистическая регрессия Логистическая регрессия
XGBoost XGBКлассификатор
Нейронная сеть MLPКлассификатор
Поиск по сетке GridSearchCV
Рандомизированный поиск Рандомизированный поискрезюме
Статья является переводом guru99-com






You may also like

Leave a Comment