Я работаю над набором данных из примерно 20000 строк.Цель состоит в том, чтобы предсказать, был ли человек нанят компанией или нет с учетом некоторых особенностей, таких как пол, опыт, дата подачи заявления, тестовый балл, уровень квалификации и т. Д. Набор данных является несбалансированным: классы либо «1», либо «0'(нанят / не нанят) с соотношением 1: 10.
Я решил обучить классификатор случайных лесов для работы над этой проблемой.Я случайным образом разделил набор данных на 70% -30% на обучающий набор и набор тестов.
После тщательного изучения различных вариантов решения проблемы дисбаланса (например, Работа с дисбалансом классов в бинарной классификации), Несбалансированная классификация с использованием RandomForestClassifier в sklearn ) Я застрял при получении хорошего результата на моем тестовом наборе.
Я пробовал несколько вещей:
- Я обучил три разных случайных леса на всем X_train, на малой выборке X_und и на избыточной X_sm соответственно.X_und был сгенерирован путем простого случайного сокращения строк X_train, помеченных 0, чтобы получить соотношения 50-50, 66-33 или 75-25, равные 0 и 1;X_sm был сгенерирован SMOTE.
Используя scikit-learn GridSearchCV
я настроил три модели для получения наилучших параметров:
param_grid = {'min_samples_leaf':[3,5,7,10,15],'max_features':[0.5,'sqrt','log2'],
'max_depth':[10,15,20],
'class_weight':[{0:1,1:1},{0:1,1:2},{0:1,1:5},'balanced'],
'criterion':['entropy','gini']}
sss = StratifiedShuffleSplit(n_splits=5)
grid = GridSearchCV(RandomForestClassifier(),param_grid,cv=sss,verbose=1,n_jobs=-1,scoring='roc_auc')
grid.fit(X_train,y_train)
Наилучший результат был получен с
rfc = RandomForestClassifier(n_estimators=150, criterion='gini', min_samples_leaf=3,
max_features=0.5, n_jobs=-1, oob_score=True, class_weight={0:1,1:5})
Тренировался на всем X_train и давал классификационный отчет по тестовому набору
precision recall f1-score support
0 0.9397 0.9759 0.9575 5189
1 0.7329 0.5135 0.6039 668
micro avg 0.9232 0.9232 0.9232 5857
macro avg 0.8363 0.7447 0.7807 5857
weighted avg 0.9161 0.9232 0.9171 5857
С методами отбора проб я получил похожие результаты, но не лучшие.Точность снижалась при пониженной выборке, и я получал почти такой же результат при избыточной выборке.
Для недостаточной выборки:
precision recall f1-score support
0 0.9532 0.9310 0.9420 5189
1 0.5463 0.6452 0.5916 668
Для SMOTE:
precision recall f1-score support
0 0.9351 0.9794 0.9567 5189
1 0.7464 0.4716 0.5780 668
- Я играл с параметром
class_weights
, чтобы придать больший вес единицам, а также с sample_weight
в процессе подгонки. - Я пытался выяснить, какой счет следует учитывать, кроме точности.Запустив
GridSearchCV
для настройки леса, я использовал разные баллы, уделяя особое внимание f1
и roc_auc
в надежде уменьшить количество ложных негативов.Я получил отличные результаты благодаря SMOTE-передискретизации, но эта модель не очень хорошо подходила для тестового набора.Я не мог понять, как изменить критерий расщепления или оценку для случайного леса, чтобы уменьшить количество ложных отрицательных значений и увеличить повторный вызов для 1.Я видел, что cohen_kappa_score
также полезен для несбалансированных наборов данных, но его нельзя использовать в методах перекрестной проверки sklearn, таких как GridSearch. - Выберите только самые важные функции, но это не изменило результат, наоборот, ухудшилось.Я отметил, что важность функции, полученная при обучении RF после SMOTE, полностью отличалась от обычной выборки.
- Я не знаю точно, что делать с
oob_score
, кроме как рассматривать его как бесплатный балл проверкиполучается при тренировке леса.С передискретизацией я получаю наивысшее значение oob_score = 0.9535
, но это естественно, так как тренировочный набор в этом случае сбалансирован, проблема по-прежнему в том, что он плохо обобщается на тестовый набор.
Прямо сейчас у меня закончились идеи, поэтому я хотел бы знать, что я что-то упускаю или делаю что-то не так.Или я должен просто попробовать другую модель вместо Random Forest?