Підручник Scikit-Learn: як встановити та приклади 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 не підтримує паралельні обчислення. З ним можна запустити алгоритм глибокого навчання, але це не оптимальне рішення, особливо якщо ви знаєте, як використовувати 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 розділений на дві частини:
- Машинне навчання за допомогою scikit-learn
- Як довіряти своїй моделі 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 |
std | 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
Трубопровід виконає дві операції перед подачею логістичного класифікатора:
- Стандартизуйте змінну: `StandardScaler()“
- Перетворення категоріальних ознак: 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)
ВИХІД
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 виграв багато змагань з каггла. З середнім розміром набору даних він може працювати так само добре, як алгоритм глибокого навчання або навіть краще.
Класифікатор є складним для навчання, оскільки він має велику кількість параметрів для налаштування. Ви, звичайно, можете використовувати 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 використовує об’єкт 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 годин на тиждень. Вік, професія та стать позитивно впливають на класифікатор.
Якби сімейний стан був неодруженим, класифікатор передбачив би дохід нижче 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)
Класифікатор передбачив дохід нижче 50 тис. Поки це неправда. Цей будинок здається дивним. Він не має ні приросту капіталу, ні збитку капіталу. Він розлучений, йому 60 років, і це освічена людина, тобто, Education_num > 12. Відповідно до загальної моделі, це домогосподарство повинно, як пояснює класифікатор, отримувати дохід нижче 50 тис.
Ви намагаєтеся пограти з LIME. Ви помітите грубі помилки класифікатора.
Ви можете перевірити GitHub власника бібліотеки. Вони надають додаткову документацію для класифікації зображень і тексту.
Підсумки
Нижче наведено список деяких корисних команд із scikit learn версії >=0.20
створити набір даних навчання/тесту | стажисти розділилися |
Побудуйте трубопровід | |
виберіть стовпець і застосуйте перетворення | makecolumntransformer |
вид трансформації | |
стандартизувати | StandardScaler |
мін макс | MinMaxScaler |
Нормалізувати | Нормалізатор |
Введіть відсутнє значення | приписувати |
Перетворення категоричних | OneHotEncoder |
Припасуйте та трансформуйте дані | fit_transform |
Зробіть трубопровід | make_pipeline |
Базова модель | |
логістична регресія | Логістична регресія |
XGBoost | XGBClassifier |
Нейронна мережа | MLPClassifier |
Пошук у сітці | GridSearchCV |
Рандомізований пошук | Рандомізований пошук CV |