Проблемы полиномиальной классификации уникальны тем, что вместо классификации x-количества признаков в класс «A» или класс «B» мы классифицируем 3 или более классов. Это приходит с новыми наборами трудностей. В этом примере я буду использовать классификацию случайного леса, обучать 3 функции и классифицировать их по классам от 0 до 4; всего пять классов.

На этот пост меня вдохновило то, что я не смог найти наборы данных или примеры, которые касались бы некоторых проблем, с которыми я столкнулся, особенно с сильно несбалансированным набором данных, с которым я работал, и я хотел объединить все свои выводы и стратегии в один. почта.

Данные

Функции в моем наборе данных — это типы с плавающей запятой от -4,831 до 6,7965.

Признаки 1 и 2 имеют наибольшую корреляцию, а признаки 1 и 3 — наименьшую корреляцию.

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

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

Итак, как нам справиться с этим серьезным дисбалансом классов?

Поиск по сетке

Существуют различные способы сделать это. В частности, для моего набора данных и модели я реализовал:

◦ Поиск по сетке — создав сетку параметров и используя GridSearchCV, я смог найти наиболее оптимизированные гиперпараметры для моего набора данных и модели.

# Example of parameter grid for GridSearchCV
parameter_grid = { 
    'n_estimators': [100, 200, 500, 1000],
    'max_features': ['auto', 'sqrt', 'log2', 3],
    'max_depth' : [2,4,5,6,7,8,10],
    'criterion' :['gini', 'entropy'],
    'bootstrap': [True, False]
}
my_model = RandomForestClassifier()
clf = GridSearchCV(my_model, parameter_grid, cv = 10, scoring = 'accuracy', n_jobs = -1, verbose = 1)
clf.fit(X_train, y_train)
from sklearn import metrics
print(clf.best_params_)
print(clf.best_score_)
# Best Parameters Output: {bootstrap = True, max_features = 16, max_depth = 4, n_estimators = 1000, criterion = 'gini'}
# Best Score with Parameters: 0.9414807104745758

Балансировка веса класса с использованием аналогичных методов поиска по сетке

# Weighted Decision Tree to find the best weights
balance = [{0:1.0, 1:30.0, 2:50.0, 3:70.0, 4:100.0},
           {0:1.0, 1:20.0, 2:40.0, 3:70.0, 4:100.0},
           {0:1.0, 1:50.0, 2:70.0, 3:80.0, 4:100.0}, 
           {0:1.0, 1:40.0, 2:50.0, 3:85.0, 4:100.0}, 
           {0:1.0, 1:60.0, 2:70.0, 3:80.0, 4:100.0}]
my_model = RandomForestClassifier(bootstrap = True, max_features = 16, max_depth = 4, n_estimators = 1000, criterion = 'gini')
weight_grid = dict(class_weight=balance) 
grid = GridSearchCV(estimator=my_model, param_grid=weight_grid, cv=10, scoring='accuracy', verbose = 1)
# report the best configuration
grid_result = grid.fit(x, y)
print('Best: %f using %s' % (grid_result.best_score_, grid_result.best_params_))
weights =  {0: 1.0, 1: 50.0, 2: 70.0, 3: 80.0, 4: 100.0} #best weights outcome from grid searching

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

Заключение

Балансировка веса класса с несбалансированными данными может быть сложной задачей в машинном обучении. В зависимости от ваших вариантов использования вы должны определить, как вы будете проверять «хорошесть» вашей модели; то есть точность, F1-скоринг, TPR и далее.

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