Один из классических алгоритмов классификации является, алгоритм использования ансамбля решающих деревьев Random Forest (далее просто RF). Его выбирают по следующим причинам:
- Random Forest хорош для не нормализованных данных, многие алгоритмы машинного обучения (ML) дают плохие результаты и данные предварительно надо обрабатывать. Для RF этот шаг можно попробовать опустить и быстро получить работающей прототип
- Быстрота обучения классификатора, поэтому для обучения можно использовать большое количество данных не беспокоясь в времени (в отличии от SVM). Распараллеливание алгоритма.
- Можно получить важность / веса параметров из пространства признаков а также вероятность предсказания
Из некоторых минусув можно выделить то, что обучившись на одних и тех-же данных несколько раз — подход будет предсказывать немного разные значения с разными вероятностями. Т.е. детерминированности вы не получите. От этого не уйдешь, т.к. выборка ансамбля решающих деревьев происходит случайным образом. Для заморозки случайности используйте random_seed.
Первый пример c RF: обучаем модель и предсказываем один элемент
from sklearn.ensemble import RandomForestClassifier x_train = [ [1, 2], [3, 4], [-1, 2], [-3, 4] ] y_train = [1, 1, 0, 0] clf_rf = RandomForestClassifier() clf_rf.fit(x_train, y_train) print(clf_rf.predict([[2, 2]])) # [1] это предсказанный класс print(clf_rf.predict_proba([[2, 2]])) # [[0.2 0.8]] вероятности по классам
Пример второй: кросс-валидация или разбиение оценка точности с помощью разбиения на выборки для теста и для тренировки модели RF
from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score from sklearn.model_selection import train_test_split x_train = [ [1, 2], [5, 6], [3, 4], [7, 8], [-1, 2], [-5, 6], [-3, 4], [-7, 8], [0, 0] ] y_train = [1, 1, 1, 1, 0, 0, 0, 0, 1] clf_rf = RandomForestClassifier() # разбиваем на два подмножества / фолда, параметр cv и получаем точность для каждого scores = cross_val_score(clf_rf, x_train, y_train, cv=2) print(scores) # [0.8 0.75] # кстати рабить на обучающую выборку и тестовую можно функцией X_train, X_test, Y_train, Y_test = train_test_split(x_train, y_train, test_size=0.2) print(X_test, Y_test) # [[5, 6], [-3, 4]] [1, 0]
Возможно вы уже задались вопросом, какие параметры подкрутить, чтобы как-то влиять на точность и адаптировать алгоритм для входных данных и для железа.
n_estimators — параметр, напрямую влияющий на качество, при увеличении пространства признаков, следует рассмотреть увеличение этого параметра
max_depth — поможет если модель получилась сильно переобученной
criterion — entropy или gini . Можно с ними поиграться)
n_jobs — когда можно использовать несколько ядер
Пример третий: использование параметров для настройки RF
Здесь показано как с помощью GridSearchCV найти оптимальные параметры для классификатора.
from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import GridSearchCV x_train = [ [1, 2], [5, 6], [3, 4], [7, 8], [-1, 2], [-5, 6], [-3, 4], [-7, 8], [0, 0] ] y_train = [1, 1, 1, 1, 0, 0, 0, 0, 1] parameter_grid = { 'criterion': ['entropy', 'gini'], 'max_depth': [10, 20, 100], 'n_estimators': [10, 20, 100] } clf = RandomForestClassifier() grid_searcher = GridSearchCV(clf, parameter_grid, verbose=2) grid_searcher.fit(x_train, y_train) clf_best = grid_searcher.best_estimator_ print('Best params = ', clf_best.get_params())
Пример четвертый — сохранение и распаковка обученной модели:
from sklearn.externals import joblib # предполагаем что clf - обучен выше joblib.dump(clf, path_to_pkl, compress=1) clf = joblib.load(self.path_to_pkl)
Здесь параметр compress — влияет на то на сколько сильно будет сжат файл классификатора, чем больше тем сильнее, однако не советую увлекаться, т.к. это обратнопропорционально вляет на время распаковки.
Пример пятый — рисуем график важности параметров. Вполне может пригодиться для презентации результатов.
from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score from sklearn.model_selection import train_test_split from sklearn.model_selection import GridSearchCV import matplotlib.pyplot as plt import numpy as np x_train = [ [1, 2], [5, 6], [3, 4], [7, 8], [-1, 2], [-5, 6], [-3, 4], [-7, 8], [0, 0] ] y_train = [1, 1, 1, 1, 0, 0, 0, 0, 1] parameter_grid = { 'criterion': ['entropy', 'gini'], 'max_depth': [10, 20, 100], 'n_estimators': [10, 20, 100] } clf_rf = RandomForestClassifier() clf_rf.fit(x_train, y_train) importances = clf_rf.feature_importances_ print(importances) std = np.std([tree.feature_importances_ for tree in clf_rf.estimators_], axis=0) indices = np.argsort(importances)[::-1] names_indices = ['x_coor', 'y_coor'] # Plot the feature importances of the forest plt.figure() plt.title("Feature importances") plt.bar(range(len(importances)), importances[indices], color="r") plt.xticks(range(len(importances)), names_indices, rotation=90) plt.tight_layout() plt.xlim([-1, len(importances)]) plt.show()
Как видно из нарисованного графика, первая координа является более ключевой, что действительно так по выборке.