Пользовательская функция оценки для классификации по сетке - PullRequest
0 голосов
/ 16 мая 2018

Я хотел бы выполнить GridSearchCV для RandomForestClassifier в scikit-learn, и у меня есть функция подсчета очков, которую я хотел бы использовать.

Функция оценки будет работать, только если указаны вероятности (например, вместо rfc.predict(...) должен быть вызван rfc.predict_proba(...))

Как я могу дать GridSearchCV команду использовать predict_proba() вместо predict()?

from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier

def my_custom_loss_func(ground_truth, predictions):
    # predictions must be probabilities - e.g. model.predict_proba()
    # example code here:
    diff = np.abs(ground_truth - predictions).max()
    return np.log(1 + diff)

param_grid = {'min_samples_leaf': [1, 2, 5, 10, 20, 50, 100], 'n_estimators': [100, 200, 300]}
grid = GridSearchCV(RandomForestClassifier(), param_grid=param_grid,
                    scoring=my_custom_loss_func)

1 Ответ

0 голосов
/ 17 мая 2018

См. Документацию здесь : вызываемый объект должен иметь параметры (оценщик, X, y)

Тогда вы можете использовать в своем определении, estimator.predict_proba(X)

В качестве альтернативы вы можете использовать make_scorer с needs_proba=True

Пример полного кода:

from sklearn.datasets import make_classification
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import make_scorer
import pandas as pd
import numpy as np

X, y = make_classification()
def my_custom_loss_func_est(estimator, X, y):
    # predictions must be probabilities - e.g. model.predict_proba()
    # example code here:
    diff = np.abs(y - estimator.predict_proba(X)[:, 1]).max()
    return -np.log(1 + diff)

def my_custom_loss_func(ground_truth, predictions):
    # predictions must be probabilities - e.g. model.predict_proba()
    # example code here:
    diff = np.abs(ground_truth - predictions[:, 1]).max()
    return np.log(1 + diff)

custom_scorer = make_scorer(my_custom_loss_func, 
                            greater_is_better=False,
                            needs_proba=True)

Использовать объект счетчика:

param_grid = {'min_samples_leaf': [10, 50], 'n_estimators': [100, 200]}
grid = GridSearchCV(RandomForestClassifier(), param_grid=param_grid,
                scoring=custom_scorer, return_train_score=True)
grid.fit(X, y)
pd.DataFrame(grid.cv_results_)[['mean_test_score',
                                   'mean_train_score',
                                   'param_min_samples_leaf',
                                   'param_n_estimators']]

    mean_test_score mean_train_score    param_min_samples_leaf    param_n_estimators
0         -0.505201        -0.495011                        10                   100
1         -0.509190        -0.498283                        10                   200
2         -0.406279        -0.406292                        50                   100
3         -0.406826        -0.406862                        50                   200

Также легко использовать функцию потерь напрямую

grid = GridSearchCV(RandomForestClassifier(), param_grid=param_grid,
                scoring=my_custom_loss_func_est,     return_train_score=True)
grid.fit(X, y)
pd.DataFrame(grid.cv_results_)[['mean_test_score',
                                   'mean_train_score',
                                   'param_min_samples_leaf',
                                   'param_n_estimators']]

    mean_test_score mean_train_score    param_min_samples_leaf  param_n_estimators
0         -0.509098        -0.491462                        10                100
1         -0.497693        -0.490936                        10                200
2         -0.409025        -0.408957                        50                100
3         -0.409525        -0.409500                        50                200

Результаты отличаются из-за разных сгибов cv (полагаю, но сейчас мне лень устанавливать начальное число и редактировать заново (или есть лучший способ вставить код без необходимости делать отступы вручную?))

...