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

Введение

В моей предыдущей статье о наборе данных сейсмических ударов, полученном из архива данных UCI, я применил базовые методы анализа данных для проектирования объектов и стратегий разделения тестовых поездов для несбалансированных наборов данных. В этой статье я продемонстрировал, как применять алгоритмы контролируемого машинного обучения (KNN, Random Forest и SVM) для прогнозов и настраивать гиперпараметры (с помощью GridSearchCV) для получения оптимальных результатов. Результаты оценки эффективности также явно демонстрируют парадокс точности, о котором я подробнее расскажу в следующих разделах. Кроме того, он также демонстрирует, почему важно понимать бизнес-проблему, чтобы выбрать лучшую модель.

Полную записную книжку можно найти в моем репозитории GitHub.

Я начал с…

создание папки, в которой я буду сохранять свои модели. При подгонке нескольких алгоритмов к вашим данным всегда полезно сохранять модели после обучения и настройки. Для этого я создал папку, используя модуль python datetime.

import datetime
def model_store_location():
    return "model-store-{}".format(datetime.date.today())
model_store_location = model_store_location()
print(model_store_location)
!mkdir {model_store_location}

В этой папке будет храниться каждая наиболее эффективная модель.

Затем я установил базовый уровень

Это задача двоичной классификации, и я выбрал простейшую модель классификации, K-ближайших соседей (KNN), чтобы начать моделирование прогнозирования. KNN - один из простейших классификаторов, который присваивает метку невидимому экземпляру на основе максимального количества меток в верхних K похожих наблюдаемых экземплярах.

Для улучшения моделей требуется базовый уровень, с которым будут сравниваться последующие модели. Следовательно, она называется «базовой моделью». Поэтому для базовой модели я инициализировал классификатор KNN с параметрами по умолчанию:

model = KNeighborsClassifier()

Затем я сначала проверил производительность, используя StratifiedKFold из 10 разделений, сохраняя метрику оценки «точность».

skf = StratifiedKFold(n_splits=10)

Для всех складок точность находится в пределах от 0,92 до 0,93, и эта близость значений проявляется через стандартное отклонение оценок.

Точность здесь действительно высокая. Теперь давайте поместим модель в наши обучающие данные и проверим производительность модели -

model.fit(X_train, y_train)
y_pred = model.predict(X_test)

Я добавил фрейм данных для хранения гиперпараметров и характеристик каждой модели, как показано ниже:

df_results = pd.DataFrame(index = ['scoring_technique', 
                                   'algorithm', 'n_neighbors',
                                   'weights', 'leaf_size', 
                                   'accuracy', 'precision', 
                                   'recall', 'f1-score'])

И добавил производительность моей базовой модели:

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
df_results['Baseline'] = ['None', model.algorithm,
                          model.n_neighbors, 
                          model.weights, 
                          model.leaf_size,
                          accuracy_score(y_test, y_pred), 
                          precision_score(y_test, y_pred), 
                          recall_score(y_test, y_pred), 
                          f1_score(y_test, y_pred)]

Так эффективность KNN выходит за рамки точности. Это классический пример парадокса точности. Поскольку большинство сейсмических ударов не опасны, истинные отрицательные значения (TN) намного выше, чем TP, FP и FN вместе взятые, тем самым численно повышая точность и создавая иллюзию правильности прогнозов но, как показывают точность и напоминание, выявление опасных сейсмических ударов ниже 30%.

Показатели эффективности двоичной классификации -

Точность = TP + TN / (TP + FP + TN + FN)

Точность = TP / (TP + FP)

Отзыв = TP / (TP + FN)

F1-Score = 2 * Precision x Recall / (Precision + Recall) = 2TP / (2TP + FP + FN)

Следовательно, исходя из базовых показателей производительности, только 25% прогнозируемых опасных выступов являются правильными и только 5% реальных опасных сейсмических выступов были правильно определены моделью. 93% данных фактически содержат неопасные сейсмические удары, и, таким образом, показатели точности в cross_val_score имеют смысл и также составляют около 93%.

Однако, как видите, пострадали точность и отзывчивость, давайте посмотрим на настройку гиперпараметров с помощью GridSearchCV

GridSearchCV для настройки гиперпараметров KNN

GridSearchCV - это функция, которая принимает возможные значения или диапазоны гиперпараметров и запускает все комбинации указанных значений гиперпараметров и вычисляет производительность на основе упомянутой метрики оценки. Эта метрика оценки должна в основном соответствовать бизнес-ценности или вашим целям.

Чтобы увидеть, какие показатели оценки предоставляются, этот код помогает:

import sklearn
sorted(sklearn.metrics.SCORERS.keys())

Этот код создаст полный список доступных методов оценки.

Затем я определил гиперпараметры для KNN, как показано в приведенном ниже коде, и создал словарь с именем param_grid , который содержит параметры для гиперпараметров KNN, как определено в документации Scikit-Learns по KNN, ключи, а значения содержат соответствующий список ценностей.

n_neighbors = [1, 2, 3, 4, 5] 
weights = ['uniform', 'distance'] 
algorithm = ['ball_tree', 'kd_tree', 'brute'] 
leaf_size = [10, 20, 30 , 40, 50]  #
param_grid = dict(n_neighbors=n_neighbors, 
                  weights=weights, 
                  algorithm=algorithm, 
                  leaf_size=leaf_size)

Затем я инициализировал GridSearchCV с моделью, сеткой для наилучшего поиска гиперпараметров, типом перекрестной проверки, метрикой оценки как точностью, а также использовал параметр refit, чтобы гарантировать, что наилучшая оценка доступна как best_estimator_, что является подогнанная модель, когда обучающая выборка сделана доступной для прогнозирования. Verbose определяет, сколько информации вы хотите отображать на экране из журналов.

grid = GridSearchCV(estimator=model, 
                    param_grid=param_grid, 
                    cv=StratifiedKFold(shuffle=True), 
                    scoring=['precision'],
                    refit='precision',
                    verbose=10)

И… я вызываю метод подгонки, чтобы начать процесс настройки гиперпараметров.

grid_result = grid.fit(X_train, y_train)

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

Я экспериментировал с разными scoring -

Модель 1 - scoring: точность

Модель 2 - scoring: отзыв

Модель 3 - scoring: f1

Ниже приводится сводка характеристик моделей:

Если вы заметили в этой сетке, наилучший возможный результат оценки метрик для каждой модели принадлежит соответствующей метрике scoring, указанной во всей сетке, т. Е. Когда параметр - «точность», никакая другая модель не обеспечивает такую ​​высокую точность, как Модель 1. Аналогичным образом, что касается «отзыва», лучшее в таблице разделяют Модель 2 и Модель 3. Фактически, их эффективность одинакова.

В модели 1, точность которой составляет 50%, то есть 50% предсказанных опасных сейсмических ударов были правильными, есть возможность отметить, что эта модель хороша лишь до подбрасывания монеты. Но подбрасывание монеты было справедливым, в то время как наш набор данных - нет, это несбалансированный набор данных. При справедливом подбрасывании монеты вероятность возникновения орла и решки одинакова, но для этого набора данных опасные и неопасные сейсмические удары не допускаются.

В Модель 2 и Модель 3 степень отзыва является наивысшей, что можно интерпретировать как 14% правильно идентифицированных реально опасных сейсмических ударов. Точность тоже 16%. Результат f1 намного лучше, чем у Model 1, что довольно неплохо. Низкий показатель f1 модели 1 связан с плохой отзывчивостью в 2%, что говорит о том, что эта модель может прогнозировать только 2% реальных опасных сейсмических ударов, что no bu eno.

Может ли классификатор случайных лесов победить в этом испытании?

Следующая модель, которую я выбрал, - это Random Forest Classifier, модель машинного обучения, победившая в соревнованиях. Это надежная модель машинного обучения, в которой несколько деревьев решений построены для объединения их выходных данных. Окончательный прогноз является функцией всех прогнозов отдельного дерева решений. Вот почему модели случайного леса работают лучше.

Я начал с инициализации классификатора случайного леса:

from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()

Затем я построил сетку, чтобы найти наиболее подходящие параметры:

param_grid = {
 ‘bootstrap’: [True],
 ‘max_depth’: [80, 90, 100, 110],
 ‘max_features’: [2, 3, 4],
 ‘min_samples_leaf’: [3, 4, 5, 6],
 ‘min_samples_split’: [8, 10, 12],
 ‘n_estimators’: [100, 200, 300, 500]
}

Я также снова выбрал «точность» для «подсчета очков». Вот полный код:

from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
param_grid = {
 ‘bootstrap’: [True],
 ‘max_depth’: [80, 90, 100, 110],
 ‘max_features’: [2, 3, 4],
 ‘min_samples_leaf’: [3, 4, 5, 6],
 ‘min_samples_split’: [8, 10, 12],
 ‘n_estimators’: [100, 200, 300, 500]
}
grid = GridSearchCV(estimator=model, 
                    param_grid=param_grid, 
                    cv=StratifiedKFold(shuffle=True), 
                    scoring=['precision'],
                    refit='precision',
                    verbose=10)
grid_result = grid.fit(X_train, y_train)
file_name = 'seismic_bump_rf_model.sav'
joblib.dump(model, model_store_location + file_name)
print(grid_result.best_estimator_)

Модель, которая вытекает из этого, -

Однако при прогнозировании набора тестов точность равна нулю.

Обучение и настройка машины опорных векторов

Поскольку модель случайного леса меня очень разочаровала, я подумал об использовании Support Vector Machine (SVM). SVM относятся к группе алгоритмов классификации методов ядра, которые используются для соответствия границам решения. Классификация основана на том, на какой стороне границы принятия решения находится точка данных.

SVM требует больших вычислительных ресурсов и может быть продемонстрирован с помощью этой настройки поиска по сетке:

from sklearn.svm import SVC 
model = SVC()
param_grid1 = {'C': [0.1, 1, 10, 100, 1000],  
              'gamma': [1, 0.1, 0.01, 0.001, 0.0001], 
              'kernel': [ 'linear', 'poly', 'rbf', 'sigmoid']}

Установка этой сетки заняла более 10 часов, что мне пришлось прервать. Я проверил, что многоугольное ядро ​​дает лучшие результаты. Все линейные ядра работают быстро, но имеют нулевую точность. В общей сложности эта сетка была эквивалентна 500 подгонкам, 5 складок на каждые 100 кандидатов (5 * 5 * 4).

Поэтому я построил новую сетку следующим образом:

param_grid2 = {'C': [1],  
              'gamma': [1], 
              'kernel': ['poly', 'rbf', 'sigmoid']}

Эта сетка имела в общей сложности 15 подгонок, и процесс настройки занял около 3,5 часов.

Теперь, следуя тому же процессу, я посмотрел на наиболее подходящую модель, как показано ниже:

grid_result.best_estimator_
Output:
SVC(C=1, gamma=1)

Ядро по умолчанию - rbf или радиальная базисная функция (RBF). Чтобы узнать больше о функциях ядра, обратитесь к документации Scikit-learn.

grid_result.best_estimator_.kernel
Output:
rbf

Вот окончательные результаты производительности SVM:

Это выглядит намного лучше с точки зрения точности, чем все другие модели. Однако отзыв только ненамного лучше.

А теперь сравним и подведем итоги…

В приведенной выше таблице точность SVM немного лучше, но точность значительно улучшилась: 67% фактического количества опасных сейсмических ударов предсказываются правильно. Однако отзыв составляет 6%, то есть только 6% реальных опасных сейсмических ударов являются правильными. Оценка f1 модели KNN ниже, чем у SVM.

В целом, эта постановка проблемы потребует более точного отзыва из-за фактора риска, связанного с невозможностью идентифицировать опасные сейсмические удары. Единственная модель, которая показала лучшие результаты для отзыва, была KNN с одинаковыми весами, n_neighbours как 1 и leaf_size 10.

Важность бизнес-требований варьируется от случая к случаю. Иногда предпочтительнее вспоминать (как здесь), а иногда - точность. Если принятие мер в отношении прогнозируемых результатов связано с расходами, тогда важна точность, т. Е. Вам нужно меньше ложных срабатываний. Более высокий отзыв желателен в тех случаях, когда стоимость каждого ложноотрицательного результата связана с затратами. В случаях, когда оба важны, значение f1, которое представляет собой гармоническое среднее значение точности и запоминания, приобретает значение.

Ссылка:

[1] Сикора М., Вробель Л .: Применение алгоритмов индукции правил для анализа данных, собранных системами мониторинга сейсмической опасности на угольных шахтах. Архив горных наук, 55 (1), 2010, 91–114.

Спасибо за посещение. Надеюсь, вам понравилось читать этот блог!

Дополнительную информацию об обработке несбалансированного класса с помощью SMOTE можно найти в этом блоге, созданном CathL и командой:



Ссылка GitHub на этот блокнот:



Мои ссылки: Средний | LinkedIn | GitHub