Один из классических алгоритмов классификации является, алгоритм использования ансамбля решающих деревьев 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()
Как видно из нарисованного графика, первая координа является более ключевой, что действительно так по выборке. 