В этой статье мы подойдем к той же проблеме предсказания появления на собеседовании, что и в прошлой статье. Поскольку размер набора данных был относительно небольшим, около 1200 экземпляров, и данные распределены по классам, я решил протестировать его с помощью ряда статистических алгоритмов. Мы обнаружили, что LinearDiscriminant и XGB работают лучше всего; оба приближаются к точности 69%. Следовательно, я стремился улучшить производительность путем настройки и набора алгоритмов. Моя цель состояла в том, чтобы получить еще 2% сверх модели по умолчанию. Вряд ли 71% хорошая точность для сбалансированного набора данных. Однако в этом случае у вас будут всевозможные перекосы, например, 90% данных принадлежат кандидатам, присутствовавшим на собеседовании. А еще есть странная вещь, например, 80% женатых мужчин, пришедших на собеседование, из Ченнаи. В любом случае, чтобы показать, как перекос между классами влияет на модель, я намереваюсь сгенерировать синтетические данные, чтобы внести некоторый баланс, чтобы показать, как модели дали бы точность более 98%, если бы данные были более сбалансированными.

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

Утечка данных — очень распространенная проблема, которая возникает непреднамеренно в процессе построения модели машинного обучения. Когда у вас есть небольшой объем данных или набор данных, который требует тщательной очистки; в этом случае оба варианта верны, в результате один из них предоставляет модели весь набор данных во время обучения. Это означает, что модель знает обо всех проверках и извлечении признаков, которые можно было бы выполнить для всего набора данных; тем самым становясь хорошим в прогнозировании значений увиденных данных. Однако он плохо работает, когда получает неаудированные, невидимые данные. Мы будем использовать конвейер данных scikit-learn, чтобы избежать утечки данных и автоматизировать этап подготовки данных.

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

Настройка производительности

XGBoost — это продвинутая библиотека дерева, повышающая градиент. Есть два класса параметров, на которых можно сосредоточиться, чтобы улучшить производительность алгоритма:

  1. Управляйте сложностью модели с помощью max_depth, min_child_weight и gamma
  2. Добавьте случайность, чтобы сделать обучение устойчивым к шуму с помощью subsample и colsample_bytree. Другими словами, эти параметры помогают избежать переобучения.

Прежде чем приступить к обсуждению настройки параметров, знайте, что, настраивая параметры, можно получить постепенно улучшающиеся результаты. Мой запуск по умолчанию давал точность 68,8%, поэтому я хотел довести ее до 71%. XGBoost довольно хорошо справляется с разреженными матрицами или категориальными функциями. Некоторые из важных параметров, которые могут быть настроены:

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

Модель по умолчанию

модель = XGBClassifier (начальное число = 7)

Точность составила 68,86%. И топ-20 функций были:

Как видно, важными характеристиками становятся количество клиентов, локации и семейное положение. Мы уже обсуждали дисбаланс между классами. Поэтому следующим шагом должно быть предоставление sklearn GridSearchCV возможности определить наилучшие возможные значения параметров. В этом случае я запустил поиск, который на моей машине занял 8 часов, используя следующий код:

param_test = {
'max_depth':[3,4,5],
'min_child_weight':[4,6,8],
'gamma':[i/10.0 for i in range(0,5)],
'subsample':[i/100.0 for i in range(75,90,5)],
'colsample_bytree':[i/100.0 for i in range(75,90,5)],
'reg_alpha':[0, 0.001, 0.005, 0.01, 0.05]
‘n_estimators’: [x for x in range(100, 400, 40)]
}
gsearch = GridSearchCV(estimator = XGBClassifier( learning_rate =0.1, n_estimators=140, max_depth=5, min_child_weight=1, gamma=0, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=7), param_grid = param_test, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
gsearch.fit(X,Y)
print(gsearch.cv_results_)
print(gsearch.best_params_)
print(gsearch.best_score_)

Поскольку best_params_ — это словарь, ключи которого уже известны, в данном случае это ключи param_test. Затем оптимальные значения используются для создания окончательной модели, что дало мне точность 70,6%. Важность особенностей оптимизированной модели заключалась в следующем:

Как видим, местонахождение, название компаний, семейное положение не попали в топ-10 признаков. Это также дает улучшение производительности на 2,6%. Вот распечатка оптимизированного дерева:

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

После достижения цели настройки параметров давайте переключим наше внимание на ансамблевые и синтетические данные. Для ансамбля мы будем использовать 2 лучших алгоритма из нашего предыдущего запуска — LDA и XGB.

Конвейер данных

Автоматизация конвейера данных сама по себе может быть разделена на две разные части — подготовка данных и извлечение признаков.

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

Стандартизация (использование в общем виде) данных важна, потому что большинство алгоритмов будут работать лучше, если они получат значение признака в диапазоне от -1 до 1. Некоторым из них также требуется нормальное распределение. Кроме дерева решений, я не могу придумать ни одного алгоритма, включая глубокое обучение, которое будет хорошо, если значения функции (столбца) будут любым числом. Масштабирование, стандартизация и нормализация данных являются взаимозаменяемыми терминами. Но все они разные и поэтому имеет смысл использовать их по необходимости.

Масштабирование данных влечет за собой изменение масштаба или диапазона данных без изменения формы их распределения. Думайте об этом как о крошечном двойнике реального здания. Диапазон обычно устанавливается от 0 до 1. Стандартизация обычно означает изменение значений таким образом, чтобы стандартное отклонение распределения от среднего равнялось единице. В основном он рассчитывается путем вычитания среднего значения признака из значения экземпляра и деления его на стандартное отклонение этого признака. Нормализация данных обычно означает, что распределение становится нормальным или, другими словами, масштабируется, а также стандартизируется. Для всех практических целей все, что мы делаем, это используем scikit-learns sklearn.preprocessing.StandardScaler() для данных обучения и проверки отдельно.

# Create a pipeline that standardizes the data then creates a model
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# create pipeline
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('lda', LinearDiscriminantAnalysis()))
model = Pipeline(estimators)
# evaluate pipeline
kfold = KFold(n_splits=10, random_state=7)
results = cross_val_score(model, X, Y, cv=kfold)
print(results.mean())

Извлечение признаков

Извлечение признаков — еще один подход, приводящий к крупной утечке данных. В этом случае я мало что мог представить в качестве задачи по извлечению функций, которая могла бы принести добавленную стоимость. Чтобы избежать ненужной разреженности данных, все, что я сделал, это позволил PCA выбрать два наиболее важных столбца местоположения из 5 предоставленных. Я бы не стал этого делать, если бы данные не повторялись в этих столбцах в каждой строке. Тем не менее, если бы я работал с реальной моделью, я бы сделал много преобразований функций, обнаружив соответствие навыков резюме с навыками, требуемыми JD; просмотрев другие связанные точки данных по заданию, например, сколько других заявок поступило на ту же работу из той же компании/населенного пункта и т. д.

Как и при подготовке данных, процедуры извлечения признаков должны быть ограничены данными в наборе обучающих данных. Конвейер предоставляет удобный компонент под названием FeatureUnion, который позволяет объединять результаты нескольких процедур выбора и извлечения признаков в более крупный набор данных, на котором можно обучать модель. Важно отметить, что все извлечение признаков и объединение признаков происходит в рамках каждой складки процедуры перекрестной проверки.

Прогноз ансамбля

Я использовал механизм голосования ансамбля, чтобы поэкспериментировать с этими данными. Модель была построена путем объединения LDA, XGB и SBM с весом 50%, 100% и 50% соответственно для определения окончательного прогноза. Голосование — один из самых простых способов объединения прогнозов нескольких алгоритмов машинного обучения. Он работает, сначала создавая две или более автономные модели из набора обучающих данных. Затем можно использовать классификатор голосования для обертывания ваших моделей и усреднения прогнозов подмоделей, когда вас попросят сделать прогнозы для новых данных. Прогнозы подмоделей могут быть взвешены, но указать веса для классификаторов вручную или даже эвристически сложно. Более продвинутые методы могут узнать, как наилучшим образом взвешивать прогнозы из подмоделей, но это называется суммированием (агрегация с накоплением) и в настоящее время не предоставляется в scikit-learn.

from sklearn.ensemble import VotingClassifier
kfold = KFold(n_splits=10, random_state=7)
# create the sub models
estimators = []
model1 = LinearDiscriminantAnalysis ()
estimators.append((lda, model1))
model2 = XGBClassifier(learning_rate =0.03, n_estimators=240, max_depth=5, min_child_weight=8, gamma=0.2,reg_alpha=0.001, subsample=0.85,colsample_bytree=0.75,objective= 'binary:logistic',nthread=4,scale_pos_weight=1, seed=7)
estimators.append((xgb, model2))
params = {'n_estimators': 500, 'max_depth': 4, 'min_samples_split': 2,'learning_rate': 0.01, 'loss': 'ls'}
model3 = ensemble.GradientBoostingRegressor(**params)
estimators.append((gbm, model3))
# create the ensemble model
ensemble = VotingClassifier(estimators, voting=’hard’, weights=[1,2,1])
results = cross_val_score(ensemble, X, Y, cv=kfold)
print(results.mean())

Ансамбль смог вернуть мне точность 72,34%.

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

«Ожидаемый» дисбаланс данных о функциях:

Чтобы быстро проверить влияние сбалансированных данных на предсказуемость модели, я сократил два класса до 98, чтобы они соответствовали количеству экземпляров нет. Я использовал Naïve-Baise для достижения точности 81%. С передискретизацией, реализованной с помощью SMOTE, я смог достичь 92% с генерацией первых трех функций, связанных с синтетическими данными. Кстати, он также обрабатывает категориальные данные, однако вам придется применить его, опубликовав onehotencoding.

В следующей статье я познакомлю вас со своим шаблоном ML, который до сих пор сослужил мне хорошую службу. Это шаблон, который вы должны настроить под себя. Поскольку у меня есть не только процесс, но и несколько полезных рецептов, которые помогут вам повысить эффективность экспериментов. Спасибо за чтение. Пожалуйста, не стесняйтесь связаться со мной в Twitter и LinkedIn.