3.3. Настройка порога принятия решения для предсказания класса#

Классификацию лучше разделить на две части:

  • статистическая задача обучения модели для предсказания, в идеале, вероятностей классов;

  • проблему принятия решений для выполнения конкретных действий на основе этих вероятностных прогнозов.

Рассмотрим простой пример, связанный с прогнозированием погоды: первый пункт относится к ответу на вопрос «какова вероятность, что завтра будет дождь?», а второй пункт относится к ответу на вопрос «стоит ли мне завтра взять зонт?».

Когда речь идёт об API scikit-learn, первый пункт решается предоставлением оценок с использованием predict_proba или decision_function. Первый возвращает оценки условных вероятностей \(P(y|X)\) для каждого класса, в то время как последний возвращает оценку решения для каждого класса.

Стоимость вывода не зависит от стратегии разделения. Она зависит только от глубины дерева, predict. В бинарной классификации правило решения или действие затем определяется пороговым значением оценок, что приводит к предсказанию одного метки класса для каждого образца. Для бинарной классификации в scikit-learn предсказания меток классов получаются жёстко закодированными правилами отсечения: положительный класс предсказывается, когда условная вероятность \(P(y|X)\) больше 0.5 (получено с помощью predict_proba) или если оценка решения больше 0 (получена с decision_function).

#32258 \(P(y|X)\) и метки классов:

>>> from sklearn.datasets import make_classification
>>> from sklearn.tree import DecisionTreeClassifier
>>> X, y = make_classification(random_state=0)
>>> classifier = DecisionTreeClassifier(max_depth=2, random_state=0).fit(X, y)
>>> classifier.predict_proba(X[:4])
array([[0.94     , 0.06     ],
       [0.94     , 0.06     ],
       [0.0416, 0.9583],
       [0.0416, 0.9583]])
>>> classifier.predict(X[:4])
array([0, 0, 1, 1])

Хотя эти жестко заданные правила могут сначала показаться разумными в качестве поведения по умолчанию, они определенно не идеальны для большинства случаев использования. Проиллюстрируем это на примере.

Рассмотрим сценарий, в котором прогнозная модель развертывается для помощи врачам в обнаружении опухолей. В этой ситуации врачи, скорее всего, будут заинтересованы в выявлении всех пациентов с раком, чтобы не пропустить ни одного случая, и могут предоставить им правильное лечение. Другими словами, врачи отдают приоритет достижению высокой полноты (recall). Этот акцент на полноту, конечно, сопряжен с компромиссом потенциально большего количества ложноположительных прогнозов, что снижает точность (precision) модели. Это риск, на который врачи готовы пойти, потому что стоимость пропущенного рака намного выше стоимости дальнейших диагностических тестов. Следовательно, при принятии решения о классификации пациента как имеющего рак или нет, может быть более выгодно классифицировать его как положительного по раку, когда оценка условной вероятности намного ниже 0.5.

3.3.1. Пост-настройка порога принятия решений#

Одним из решений для решения проблемы, изложенной во введении, является настройка порога принятия решений классификатора после обучения модели. TunedThresholdClassifierCV настраивает этот порог с помощью внутренней кросс-валидации. Оптимальный порог выбирается для максимизации заданной метрики.

На следующем изображении показана настройка порога принятия решений для градиентного бустингового классификатора. В то время как базовый и настроенный классификаторы дают одинаковый predict_proba выходы и, следовательно, одинаковые кривые рабочих характеристик приемника (ROC) и точности-полноты, предсказания меток классов различаются из-за настроенного порога принятия решения. Ванильный классификатор предсказывает интересующий класс для условной вероятности больше 0.5, в то время как настроенный классификатор предсказывает интересующий класс для очень низкой вероятности (около 0.02). Этот порог принятия решения оптимизирует метрику полезности, определенную бизнесом (в данном случае страховой компанией).

../_images/sphx_glr_plot_cost_sensitive_learning_002.png

3.3.1.1. Опции для настройки порога принятия решения#

Порог принятия решения может быть настроен с помощью различных стратегий, управляемых параметром scoring.

Один из способов настройки порога — максимизация предопределенной метрики scikit-learn. Эти метрики можно найти, вызвав функцию get_scorer_namesПо умолчанию используется сбалансированная точность, но следует выбирать осмысленную метрику для конкретного случая использования.

Примечание

Важно отметить, что эти метрики поставляются с параметрами по умолчанию, в частности с меткой интересующего класса (т.е. pos_label). Таким образом, если эта метка не подходит для вашего приложения, вам нужно определить оценщик и передать правильную pos_label (и дополнительные параметры) с использованием make_scorer. См. Вызываемые скореры чтобы получить информацию для определения собственной функции оценки. Например, мы показываем, как передать информацию оценщику о том, что интересующий нас метка - это 0 при максимизации f1_score:

>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.model_selection import TunedThresholdClassifierCV
>>> from sklearn.metrics import make_scorer, f1_score
>>> X, y = make_classification(
...   n_samples=1_000, weights=[0.1, 0.9], random_state=0)
>>> pos_label = 0
>>> scorer = make_scorer(f1_score, pos_label=pos_label)
>>> base_model = LogisticRegression()
>>> model = TunedThresholdClassifierCV(base_model, scoring=scorer)
>>> scorer(model.fit(X, y), X, y)
0.88
>>> # compare it with the internal score found by cross-validation
>>> model.best_score_
np.float64(0.86)

3.3.1.2. Важные замечания относительно внутренней кросс-валидации#

По умолчанию TunedThresholdClassifierCV использует 5-кратную стратифицированную перекрестную проверку для настройки порога принятия решений. Параметр cv позволяет контролировать стратегию перекрестной проверки. Можно обойти перекрестную проверку, установив cv="prefit" и предоставление обученного классификатора. В этом случае порог принятия решения настраивается на данных, предоставленных fit метод.

Однако следует быть крайне осторожным при использовании этой опции. Никогда не используйте одни и те же данные для обучения классификатора и настройки порога принятия решения из-за риска переобучения. Обратитесь к следующему разделу примера для подробностей (см. Соображения относительно переобучения модели и перекрестной проверки). Если у вас ограниченные ресурсы, рассмотрите использование числа с плавающей точкой для cv чтобы ограничиться одним внутренним разделением на обучение-тест.

Опция cv="prefit" следует использовать только тогда, когда предоставленный классификатор уже обучен, и вы просто хотите найти лучший порог принятия решений с использованием нового валидационного набора.

3.3.1.3. Ручная установка порога принятия решений#

Предыдущие разделы обсуждали стратегии поиска оптимального порога принятия решений. Также можно вручную установить порог принятия решений с помощью класса FixedThresholdClassifier. В случае, если вы не хотите переобучать модель при вызове fit, оберните ваш суб-оценщик с помощью FrozenEstimator и делают FixedThresholdClassifier(FrozenEstimator(estimator), ...).

3.3.1.4. Примеры#