Spec-Zone.ru › scikit-learn

Примечание

Перейти в конец, чтобы скачать полный код примера или запустить его в браузере с помощью JupyterLite или Binder.

Анализ сходимости моделей логистической регрессии с регуляризацией

У этого примера три цели:

  1. Показать, как зарегистрировать ScoringMonitor на этапе логистической регрессии конвейера, вложенного в GridSearchCV.
  2. Показать, как построить график значений метрик, собранных на каждой итерации каждого обучения модели логистической регрессии во время поиска по сетке, и проанализировать сходимость модели для каждой комбинации гиперпараметров.
  3. Показать, как мониторинг различных метрик качества помогает оценить качество модели и компромисс между уточнением и калибровкой.
# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

Подготовка

Сначала определим конвейер и поиск по сетке. Здесь мы регистрируем обратный вызов ScoringMonitor для модели логистической регрессии, чтобы отслеживать оценки на каждой итерации решателя L-BFGS.

Для самого поиска по сетке мы используем те же метрики качества и выбираем наилучшую комбинацию гиперпараметров по D² log-loss.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from sklearn.callback import ProgressBar, ScoringMonitor
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

X, y = make_classification(
    n_samples=1000, n_features=100, n_classes=10, n_informative=30, random_state=42
)

scoring_metrics = ["d2_log_loss_score", "accuracy", "average_precision"]
scoring_monitor = ScoringMonitor(scoring=scoring_metrics)
model = make_pipeline(
    StandardScaler(),
    LogisticRegression(solver="lbfgs", max_iter=1000).set_callbacks(scoring_monitor),
)

param_grid = {
    "standardscaler__with_std": [True, False],
    "logisticregression__C": np.geomspace(0.01, 100, 3),
}

grid_search = GridSearchCV(
    model,
    param_grid,
    cv=5,
    scoring=scoring_metrics,
    n_jobs=2,
    error_score="raise",
    refit=scoring_metrics[0],
)

Выполним поиск по сетке с обратным вызовом индикатора выполнения, который автоматически распространяется. Чтобы получить более подробный вывод с индикаторами выполнения для конвейера, StandardScaler и логистической регрессии, задайте max_propagation_depth=3 в конструкторе ProgressBar.

grid_search.set_callbacks(ProgressBar()).fit(X, y)
GridSearchCV - fit                                                 ━━━ 100% 0:0…
  GridSearchCV - search #0                                         ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #0  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #1  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #2  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #3  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #4  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #5  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #6  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #7  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #8  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #9  ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #10 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #11 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #12 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #13 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #14 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #15 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #16 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #17 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #18 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #19 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #20 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #21 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #22 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #23 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #24 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #25 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #26 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #27 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #28 ━━━ 100% 0:0…
    GridSearchCV - candidate-split-evaluation | Pipeline - fit #29 ━━━ 100% 0:0…
  GridSearchCV - refit-with-best-params | Pipeline - fit #1        ━━━ 100% 0:0…
GridSearchCV(cv=5, error_score='raise',
             estimator=Pipeline(steps=[('standardscaler', StandardScaler()),
                                       ('logisticregression',
                                        LogisticRegression(max_iter=1000))]),
             n_jobs=2,
             param_grid={'logisticregression__C': array([1.e-02, 1.e+00, 1.e+02]),
                         'standardscaler__with_std': [True, False]},
             refit='d2_log_loss_score',
             scoring=['d2_log_loss_score', 'accuracy', 'average_precision'])
В среде Jupyter повторно выполните эту ячейку, чтобы отобразить представление HTML, или доверьте этому ноутбуку.
На GitHub представление HTML не отображается; попробуйте открыть эту страницу с помощью nbviewer.org.
Параметры
estimator estimator: объект-оцениватель

Предполагается, что он реализует интерфейс оценивателя scikit-learn.
Оцениватель должен предоставлять функцию ``score``
или необходимо передать параметр ``scoring``.
Pipeline(step..._iter=1000))])
param_grid param_grid: словарь или список словарей

Словарь, в котором ключами являются имена параметров (`str`), а значениями — списки
настроек параметров для проверки; также может быть передан список таких
словарей. В этом случае рассматриваются сетки, заданные каждым словарём
из списка. Это позволяет выполнять поиск по любой последовательности
настроек параметров.
{'logisticregression__C': array([1.e-02...e+00, 1.e+02]), 'standardscaler__with_std': [True, False]}
scoring scoring: строка, вызываемый объект, список, кортеж или словарь, по умолчанию=None

Стратегия оценки качества модели, проверенной перекрёстной проверкой, на
тестовой выборке.

Если `scoring` задаёт одну оценку, можно использовать:

- одну строку (см. :ref:`scoring_string_names`);
- вызываемый объект (см. :ref:`scoring_callable`), возвращающий одно значение;
- `None` — в этом случае используется
:ref:`критерий оценки по умолчанию для оценивателя <scoring_api_overview>`.

Если `scoring` задаёт несколько оценок, можно использовать:

- список или кортеж уникальных строк;
- вызываемый объект, возвращающий словарь, где ключи — это имена метрик,
а значения — оценки метрик;
- словарь с именами метрик в качестве ключей и вызываемыми объектами в качестве значений.

Пример см. в разделе :ref:`multimetric_grid_search`.
['d2_log_loss_score', 'accuracy', ...]
n_jobs n_jobs: int, по умолчанию=None

Количество задач, выполняемых параллельно.
``None`` означает 1, если только код не выполняется в контексте :obj:`joblib.parallel_backend`.
``-1`` означает использование всех процессоров. Дополнительную информацию см. в :term:`глоссарии <n_jobs>`.

.. versionchanged:: v0.20
Значение параметра `n_jobs` по умолчанию изменено с 1 на None
2
refit refit: bool, строка или вызываемый объект, по умолчанию=True

Повторно обучить оцениватель на всём наборе данных, используя лучшие найденные параметры.

При оценке нескольких метрик необходимо задать строку `str`, обозначающую
оценщик, который будет использоваться для поиска лучших параметров при повторном обучении
оценивателя в конце.

Если при выборе лучшего оценивателя важны факторы помимо максимальной оценки,
для ``refit`` можно задать функцию, которая
возвращает выбранный ``best_index_`` на основе ``cv_results_``. В этом
случае атрибуты ``best_estimator_`` и ``best_params_`` будут заданы
в соответствии с возвращённым ``best_index_``, а атрибут ``best_score_``
будет недоступен.

Повторно обученный оцениватель доступен через атрибут ``best_estimator_``
и позволяет напрямую использовать ``predict`` для этого экземпляра
``GridSearchCV``.

Также при оценке нескольких метрик атрибуты ``best_index_``,
``best_score_`` и ``best_params_`` будут доступны только в том случае, если
задан ``refit``; все они будут определяться относительно указанного
оценщика.

Подробнее об оценке нескольких метрик см. параметр ``scoring``.

Информацию о создании пользовательской стратегии выбора с помощью вызываемого объекта
через `refit` см. в разделе :ref:`sphx_glr_auto_examples_model_selection_plot_grid_search_digits.py`.

Пример использования ``refit=callable`` для баланса сложности модели
и оценки перекрёстной проверки приведён в :ref:`этом примере
<sphx_glr_auto_examples_model_selection_plot_grid_search_refit_callable.py>`.

.. versionchanged:: 0.20
Добавлена поддержка вызываемых объектов.
'd2_log_loss_score'
cv cv: int, генератор перекрёстной проверки или итерируемый объект, по умолчанию=None

Определяет стратегию разбиения для перекрёстной проверки.
Возможные значения cv:

- None — использовать перекрёстную проверку с 5 блоками по умолчанию;
- целое число — указать количество блоков в `(Stratified)KFold`;
- :term:`разбиватель CV`;
- итерируемый объект, выдающий разбиения (train, test) в виде массивов индексов.

Для целочисленных значений и None, если оцениватель является классификатором, а ``y``
содержит два или несколько классов, используется :class:`StratifiedKFold`. Во всех
остальных случаях используется :class:`KFold`. Эти разбиения создаются
с `shuffle=False`, поэтому при каждом вызове разбиения будут одинаковыми.

Различные стратегии перекрёстной проверки, доступные здесь, описаны в :ref:`руководстве пользователя <cross_validation>`.

.. versionchanged:: 0.22
Значение ``cv`` по умолчанию при None изменено с 3 блоков на 5.
5
error_score error_score: 'raise' или числовое значение, по умолчанию=np.nan

Значение оценки, которое присваивается в случае ошибки при обучении оценивателя.
Если задано значение 'raise', ошибка вызывается повторно. Если задано числовое значение,
вызывается FitFailedWarning. Этот параметр не влияет на этап повторного обучения
(refit), который всегда вызывает ошибку повторно.
'raise'
verbose verbose: int, по умолчанию=0

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

- 0 : сообщения не выводятся;
- >=1 : сводка общего количества этапов обучения;
- >=2 : время вычислений для каждого блока и кандидата параметров;
- >=3 : индексы блоков и оценки;
- >=10 : индексы кандидатов параметров и сообщения START перед каждым этапом обучения.
0
pre_dispatch pre_dispatch: int или str, по умолчанию='2*n_jobs'

Управляет количеством задач, запускаемых во время параллельного
выполнения. Уменьшение этого количества может помочь избежать чрезмерного
потребления памяти, если запускается больше задач,
чем процессоры могут обработать. Для этого параметра можно задать:

- None — все задачи создаются и запускаются немедленно. Используйте
это значение для лёгких и быстро выполняющихся задач, чтобы избежать задержек
из-за запуска задач по требованию;
- целое число — точное количество запускаемых задач;
- строку — выражение, зависящее от n_jobs, например '2*n_jobs'.
'2*n_jobs'
return_train_score return_train_score: bool, по умолчанию=False

Если задано ``False``, атрибут ``cv_results_`` не будет содержать
оценки на обучающих данных.
Расчёт оценок на обучающих данных позволяет понять, как различные
настройки параметров влияют на компромисс между переобучением и недообучением.
Однако расчёт оценок на обучающей выборке может быть вычислительно
дорогим и не является обязательным для выбора параметров,
обеспечивающих наилучшее качество обобщения.

.. versionadded:: 0.19

.. versionchanged:: 0.21
Значение по умолчанию изменено с ``True`` на ``False``
False
Обученные атрибуты
Имя Тип Значение
best_estimator_ best_estimator_: оцениватель

Оцениватель, выбранный в результате поиска, то есть оцениватель,
который показал наивысшую оценку (или наименьшую потерю, если она задана)
на отложенных данных. Недоступен, если ``refit=False``.

Дополнительную информацию о допустимых значениях см. в параметре ``refit``.
Pipeline Pipeline(step..._iter=1000))])
best_index_ best_index_: int

Индекс (в массивах ``cv_results_``), соответствующий лучшей
настройке параметров-кандидату.

Словарь по адресу ``search.cv_results_['params'][search.best_index_]`` содержит
настройку параметров лучшей модели, которая обеспечивает наивысшую
среднюю оценку (``search.best_score_``).

При оценке нескольких метрик этот атрибут присутствует только в том случае, если задан ``refit``.
int64 np.int64(1)
best_params_ best_params_: dict

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

При оценке нескольких метрик этот атрибут присутствует только в том случае, если задан ``refit``.
dict {'lo..._C': np.float64(0.01), 'st...td': False}
best_score_ best_score_: float

Средняя оценка лучшего оценивателя, полученная с помощью перекрёстной проверки.

При оценке нескольких метрик этот атрибут присутствует только в том случае, если задан ``refit``.

Этот атрибут недоступен, если ``refit`` является функцией.
float64 0.1706
classes_ classes_: ndarray формы (n_classes,)

Метки классов. Присутствует только в том случае, если задан ``refit`` и
базовый оцениватель является классификатором.
ndarray[int64](10,) [0,1,2,...,7,8,9]
cv_results_ cv_results_: dict из маскированных массивов numpy

Словарь, в котором ключи соответствуют заголовкам столбцов, а значения — самим столбцам. Его можно
импортировать в ``DataFrame`` библиотеки pandas.

Например, приведённая ниже таблица

+------------+-----------+------------+-----------------+---+---------+
|param_kernel|param_gamma|param_degree|split0_test_score|...|rank_t...|
+============+===========+============+=================+===+=========+
| 'poly' | -- | 2 | 0.80 |...| 2 |
+------------+-----------+------------+-----------------+---+---------+
| 'poly' | -- | 3 | 0.70 |...| 4 |
+------------+-----------+------------+-----------------+---+---------+
| 'rbf' | 0.1 | -- | 0.80 |...| 3 |
+------------+-----------+------------+-----------------+---+---------+
| 'rbf' | 0.2 | -- | 0.93 |...| 1 |
+------------+-----------+------------+-----------------+---+---------+

будет представлена словарём ``cv_results_`` следующего вида::

{
'param_kernel': masked_array(data = ['poly', 'poly', 'rbf', 'rbf'],
mask = [False False False False]...)
'param_gamma': masked_array(data = [-- -- 0.1 0.2],
mask = [ True True False False]...),
'param_degree': masked_array(data = [2.0 3.0 -- --],
mask = [False False True True]...),
'split0_test_score' : [0.80, 0.70, 0.80, 0.93],
'split1_test_score' : [0.82, 0.50, 0.70, 0.78],
'mean_test_score' : [0.81, 0.60, 0.75, 0.85],
'std_test_score' : [0.01, 0.10, 0.05, 0.08],
'rank_test_score' : [2, 4, 3, 1],
'split0_train_score' : [0.80, 0.92, 0.70, 0.93],
'split1_train_score' : [0.82, 0.55, 0.70, 0.87],
'mean_train_score' : [0.81, 0.74, 0.70, 0.90],
'std_train_score' : [0.01, 0.19, 0.00, 0.03],
'mean_fit_time' : [0.73, 0.63, 0.43, 0.49],
'std_fit_time' : [0.01, 0.02, 0.01, 0.01],
'mean_score_time' : [0.01, 0.06, 0.04, 0.04],
'std_score_time' : [0.00, 0.00, 0.00, 0.01],
'params' : [{'kernel': 'poly', 'degree': 2}, ...],
}

Пример визуализации и интерпретации результатов GridSearch см. в разделе
:ref:`sphx_glr_auto_examples_model_selection_plot_grid_search_stats.py`.

ПРИМЕЧАНИЕ

Ключ ``'params'`` используется для хранения списка словарей настроек
параметров для всех кандидатов параметров.

Значения ``mean_fit_time``, ``std_fit_time``, ``mean_score_time`` и
``std_score_time`` указаны в секундах.

При оценке нескольких метрик оценки всех оценщиков доступны в словаре
``cv_results_`` по ключам, оканчивающимся именем соответствующего
оценщика (``'_<scorer_name>'``), а не ``'_score'``, как показано
выше. (например, 'split0_test_precision', 'mean_train_precision' и т. д.)
dict {'me...me': array([0.1771... 3.87409887]), 'me...me': array([0.0225... 0.01172628]), 'me...cy': array([0.296,...0.26 , 0.258]), 'me...on': array([0.2980... 0.26786657]), ...}
multimetric_ multimetric_: bool

Вычисляют ли оценщики несколько метрик.
bool True
n_features_in_ n_features_in_: int

Количество признаков, обнаруженных во время :term:`обучения`. Определён только в том случае,
если определён `best_estimator_` (подробнее см. документацию по параметру `refit`)
и `best_estimator_` предоставляет `n_features_in_` при обучении.

.. versionadded:: 0.24
int 100
n_splits_ n_splits_: int

Количество разбиений (блоков/итераций) при перекрёстной проверке.
int 5
refit_time_ refit_time_: float

Время в секундах, затраченное на повторное обучение лучшей модели на всём наборе данных.

Присутствует только в том случае, если ``refit`` не равен False.

.. versionadded:: 0.20
float 0.981
scorer_ scorer_: функция или словарь

Функция-оценщик, используемая на отложенных данных для выбора лучших
параметров модели.

При оценке нескольких метрик этот атрибут содержит проверенный
словарь ``scoring``, сопоставляющий ключ оценщика с вызываемым объектом оценщика.
dict {'ac...cy': make_scorer(a...hod='predict'), 'av...on': make_scorer(a...edict_proba')), 'd2...re': make_scorer(d...redict_proba')}
Параметры
with_std with_std: bool, по умолчанию=True

Если True, масштабировать данные до единичной дисперсии (или, что эквивалентно,
единичного стандартного отклонения).
False
copy copy: bool, по умолчанию=True

Если False, попытаться избежать копирования и масштабировать данные на месте.
Это не гарантирует, что операция всегда будет выполнена на месте; например, если данные
не являются массивом NumPy или разреженной матрицей scipy.sparse CSR, всё равно может быть
возвращена копия.
True
with_mean with_mean: bool, по умолчанию=True

Если True, центрировать данные перед масштабированием.
Это не работает (и приводит к исключению) при применении к
разреженным матрицам, поскольку центрирование подразумевает создание плотной
матрицы, которая в типичных случаях использования, скорее всего, будет слишком велика для размещения в
памяти.
True
Атрибуты обученной модели
Имя Тип Значение
mean_ mean_: ndarray формы (n_features,) или None

Среднее значение каждого признака в обучающей выборке.
Равно ``None``, если ``with_mean=False`` и ``with_std=False``.
ndarray[float64](100,) [-0.1 , 0.05, 0. ,..., 0.06,-0. , 0.3 ]
n_features_in_ n_features_in_: int

Количество признаков, обнаруженных при :term:`fit`.

.. versionadded:: 0.24
int 100
n_samples_seen_ n_samples_seen_: int или ndarray формы (n_features,)

Количество образцов, обработанных оценивателем для каждого признака.
Если отсутствующих образцов нет, ``n_samples_seen`` будет целым числом; в противном случае это будет массив типа int. Если
используются `sample_weights`, значение будет числом с плавающей запятой (при отсутствии пропущенных данных)
или массивом типа float, содержащим сумму весов, учтённых на данный момент.
Сбрасывается при новых вызовах fit, но увеличивается при вызовах
``partial_fit``.
float64 1000
scale_ scale_: ndarray формы (n_features,) или None

Относительный коэффициент масштабирования данных для каждого признака, обеспечивающий нулевое среднее и единичную
дисперсию. Обычно он вычисляется с помощью `np.sqrt(var_)`. Если
дисперсия равна нулю, добиться единичной дисперсии невозможно, поэтому данные остаются
без изменений, а коэффициент масштабирования равен 1. `scale_` равен `None`,
если `with_std=False`.

.. versionadded:: 0.17
*scale_*
NoneType None
var_ var_: ndarray формы (n_features,) или None

Дисперсия каждого признака в обучающей выборке. Используется для вычисления
`scale_`. Равно ``None``, если ``with_mean=False`` и
``with_std=False``.
NoneType None
100 признаков
x0
x1
x2
x3
x4
x5
x6
x7
x8
x9
x10
x11
x12
x13
x14
x15
x16
x17
x18
x19
x20
x21
x22
x23
x24
x25
x26
x27
x28
x29
x30
x31
x32
x33
x34
x35
x36
x37
x38
x39
x40
x41
x42
x43
x44
x45
x46
x47
x48
x49
x50
x51
x52
x53
x54
x55
x56
x57
x58
x59
x60
x61
x62
x63
x64
x65
x66
x67
x68
x69
x70
x71
x72
x73
x74
x75
x76
x77
x78
x79
x80
x81
x82
x83
x84
x85
x86
x87
x88
x89
x90
x91
x92
x93
x94
x95
x96
x97
x98
x99
Параметры
C C: float, по умолчанию=1.0

Обратная величина силы регуляризации; должна быть положительным числом с плавающей точкой.
Как и в методе опорных векторов, меньшие значения соответствуют более сильной
регуляризации. `C=np.inf` означает логистическую регрессию без штрафа.
Наглядный пример влияния настройки параметра `C`
при штрафе L1 см. в:
:ref:`sphx_glr_auto_examples_linear_model_plot_logistic_path.py`.
np.float64(0.01)
max_iter max_iter: int, по умолчанию=100

Максимальное количество итераций, выполняемых решателями для сходимости.
1000
penalty penalty: {'l1', 'l2', 'elasticnet', None}, по умолчанию='l2'

Укажите норму штрафа:

- `None`: штраф не добавляется;
- `'l2'`: добавляется штрафной член L2; это вариант по умолчанию;
- `'l1'`: добавляется штрафной член L1;
- `'elasticnet'`: добавляются штрафные члены L1 и L2.

.. warning::
Некоторые штрафы могут быть несовместимы с отдельными решателями. См. параметр
`solver` ниже, чтобы узнать о совместимости штрафа и
решателя.

.. versionadded:: 0.19
штраф L1 с решателем SAGA (поддержка 'multinomial' + L1)

.. deprecated:: 1.8
`penalty` устарел в версии 1.8 и будет удалён в версии 1.10.
Вместо него используйте `l1_ratio` и `C`. Для `penalty='l2'` задайте `l1_ratio=0`,
для `penalty='l1'` — `l1_ratio=1`, для `penalty='elasticnet'` задайте `l1_ratio` равным любому числу с плавающей точкой от 0 до 1,
а для `penalty=None` используйте `C=np.inf`.
'deprecated'
l1_ratio l1_ratio: float, по умолчанию=0.0

Параметр смешивания Elastic-Net, где `0 <= l1_ratio <= 1`. Значение
`l1_ratio=1` задаёт чистый штраф L1, а `l1_ratio=0` — чистый штраф L2.
Любое значение между 0 и 1 задаёт штраф Elastic-Net вида
`l1_ratio * L1 + (1 - l1_ratio) * L2`.

.. warning::
Некоторые значения `l1_ratio`, то есть отдельные штрафы, могут быть несовместимы с некоторыми
решателями. См. параметр `solver` ниже, чтобы узнать о совместимости штрафа и решателя.

.. versionchanged:: 1.8
Значение по умолчанию изменено с None на 0.0.

.. deprecated:: 1.8
`None` устарел и будет удалён в версии 1.10. Всегда используйте
`l1_ratio` для задания типа штрафа.
0.0
dual dual: bool, по умолчанию=False

Двойственная (с ограничениями) или прямая (регуляризованная, см. также
:ref:`это уравнение <regularized-logistic-loss>`) формулировка. Двойственная формулировка
реализована только для штрафа L2 с решателем liblinear. Предпочтительно использовать `dual=False`,
если n_samples > n_features.
False
tol tol: float, по умолчанию=1e-4

Допуск для критерия остановки.
0.0001
fit_intercept fit_intercept: bool, по умолчанию=True

Указывает, следует ли добавить к функции принятия решения константу (также называемую смещением или свободным членом).
True
intercept_scaling intercept_scaling: float, по умолчанию=1

Используется только при выборе решателя `liblinear`
и значении `True` для `self.fit_intercept`. В этом случае `x` становится
`[x, self.intercept_scaling]`,
то есть к вектору экземпляра добавляется «синтетический» признак с постоянным значением, равным
`intercept_scaling`.
Свободный член становится равным
``intercept_scaling * synthetic_feature_weight``.

.. note::
Вес синтетического признака подвергается штрафу L1 или L2, как и все остальные признаки.
Чтобы уменьшить влияние регуляризации на вес синтетического признака
(и, следовательно, на свободный член), значение `intercept_scaling` следует увеличить.
1
class_weight class_weight: dict или 'balanced', по умолчанию=None

Веса классов в виде ``{class_label: weight}``.
Если параметр не задан, предполагается, что вес всех классов равен единице.

Режим "balanced" использует значения y для автоматической настройки весов,
обратно пропорциональных частотам классов во входных данных,
по формуле ``n_samples / (n_classes * np.bincount(y))``.

Обратите внимание: если задан sample_weight, эти веса будут умножены на sample_weight (переданный
через метод fit).

.. versionadded:: 0.17
*class_weight='balanced'*
None
random_state random_state: int, экземпляр RandomState, по умолчанию=None

Используется для перемешивания данных, если ``solver`` == 'sag', 'saga' или 'liblinear'.
Подробности см. в :term:`глоссарии <random_state>`.
None
solver solver: {'lbfgs', 'liblinear', 'newton-cg', 'newton-cholesky', 'sag', 'saga'}, по умолчанию='lbfgs'

Алгоритм для задачи оптимизации. По умолчанию используется 'lbfgs'.
При выборе решателя можно учитывать следующие аспекты:

- 'lbfgs' — хороший вариант по умолчанию, поскольку он достаточно хорошо работает для широкого
класса задач.
- Для задач :term:`многоклассовой классификации` (`n_classes >= 3`) все решатели, кроме
'liblinear', минимизируют полную мультиномиальную функцию потерь; 'liblinear' вызовет
ошибку.
- 'newton-cholesky' — хороший выбор, если
`n_samples` >> `n_features * n_classes`, особенно для категориальных признаков, закодированных методом one-hot,
с редкими категориями. Учтите, что использование памяти этим решателем
квадратично зависит от `n_features * n_classes`,
поскольку он явно вычисляет полную матрицу Гессе.
- Для небольших наборов данных хорошо подходит 'liblinear', тогда как 'sag'
и 'saga' быстрее работают с большими наборами;
- 'liblinear' по умолчанию поддерживает только бинарную классификацию. Чтобы применить схему
«один против остальных» для многоклассовой задачи, его можно обернуть в
:class:`~sklearn.multiclass.OneVsRestClassifier`.

.. warning::
Выбор алгоритма зависит от выбранного штрафа (`l1_ratio=0`
для штрафа L2, `l1_ratio=1` для штрафа L1 и `0 < l1_ratio < 1` для
Elastic-Net), а также от поддержки (мультиномиальной) многоклассовой классификации:

================= ======================== ======================
solver l1_ratio мультиномиальная многоклассовая классификация
================= ======================== ======================
'lbfgs' l1_ratio=0 да
'liblinear' l1_ratio=1 или l1_ratio=0 нет
'newton-cg' l1_ratio=0 да
'newton-cholesky' l1_ratio=0 да
'sag' l1_ratio=0 да
'saga' 0<=l1_ratio<=1 да
================= ======================== ======================

.. note::
Быстрая сходимость 'sag' и 'saga' гарантируется только для признаков
примерно одинакового масштаба. Данные можно предварительно обработать с помощью
масштабировщика из :mod:`sklearn.preprocessing`.

.. seealso::
Дополнительные сведения о :class:`LogisticRegression`, в частности
о поддержке решателями штрафов, см. в :ref:`руководстве пользователя <Logistic_regression>` и
в обобщающей :ref:`таблице <logistic_regression_solvers>`.

.. versionadded:: 0.17
Решатель стохастического градиентного спуска с усреднением (SAG). Поддержка мультиномиальной классификации добавлена в
версии 0.18.
.. versionadded:: 0.19
Решатель SAGA.
.. versionchanged:: 0.22
В версии 0.22 решатель по умолчанию изменён с 'liblinear' на 'lbfgs'.
.. versionadded:: 1.2
Решатель newton-cholesky. Поддержка мультиномиальной классификации добавлена в версии 1.6.
'lbfgs'
verbose verbose: int, по умолчанию=0

Для решателей liblinear и lbfgs задайте любое положительное значение verbose,
чтобы включить подробный вывод.
0
warm_start warm_start: bool, по умолчанию=False

Если задано значение True, результат предыдущего вызова fit повторно используется
как начальное приближение; в противном случае предыдущий результат удаляется.
Не применяется для решателя liblinear. См. :term:`глоссарий <warm_start>`.

.. versionadded:: 0.17
*warm_start* для поддержки решателей *lbfgs*, *newton-cg*, *sag*, *saga*.
False
n_jobs n_jobs: int, по умолчанию=None

Не оказывает никакого влияния.

.. deprecated:: 1.8
`n_jobs` устарел в версии 1.8 и будет удалён в версии 1.10.
None
Атрибуты обученной модели
Имя Тип Значение
classes_ classes_: ndarray формы (n_classes, )

Список меток классов, известных классификатору.
ndarray[int64](10,) [0,1,2,...,7,8,9]
coef_ coef_: ndarray или матрица CSR формы (1, n_features) или (n_classes, n_features)

Коэффициенты признаков в функции принятия решения.

Для бинарной задачи `coef_` имеет форму (1, n_features).

По умолчанию создаётся плотный массив, но его можно преобразовать в
разреженный (формат CSR) с помощью :meth:`sparsify` (это может быть полезно
при регуляризации L1, если многие коэффициенты равны нулю), а затем обратно в
плотный с помощью :meth:`densify`.
ndarray[float64](10, 100) [[ 0.14,-0. , 0.06,..., 0.01, 0. ,-0. ], [ 0.01, 0.04, 0.01,..., 0.02,-0.03, 0.01], [-0.11,-0.04, 0.06,...,-0.06, 0.06, 0. ], ..., [-0.06, 0.05, 0.04,...,-0.07, 0.03, 0.02], [-0.03, 0. ,-0.05,..., 0.04,-0.06,-0.14], [-0.04,-0.05, 0. ,..., 0.03,-0. , 0.05]]
intercept_ intercept_: ndarray формы (1,) или (n_classes,)

Свободный член (также называемый смещением), добавляемый к функции принятия решения.

Если для `fit_intercept` задано значение False, свободный член равен нулю.
Для бинарной задачи `intercept_` имеет форму (1,).
ndarray[float64](10,) [-0. , 0.23,-0.15,..., 0.13,-0.07,-0.18]
n_features_in_ n_features_in_: int

Количество признаков, обнаруженных при :term:`fit`.

.. versionadded:: 0.24
int 100
n_iter_ n_iter_: ndarray формы (1, )

Фактическое количество итераций для всех классов.

.. versionchanged:: 0.20

В SciPy <= 1.0.0 количество итераций lbfgs могло превышать
``max_iter``. Теперь ``n_iter_`` сообщает значение не больше ``max_iter``.
ndarray[int32](1,) [77]


Мы используем поиск по сетке с 3 значениями параметра регуляризации C и 2 значениями параметра стандартизации признаков, что даёт 6 комбинаций параметров.

Поскольку мы используем 5-блочную перекрёстную проверку (cv=5), для каждой комбинации параметров будет выполнено 5 обучений модели логистической регрессии, то есть всего 30 обучений в качестве подзадач «поиска» задачи обучения.

Кроме того, поиск по сетке выполняет итоговое повторное обучение на всём наборе данных с наилучшей комбинацией гиперпараметров, найденной в ходе поиска. Выше в выводе это показано как задача «refit-with-best-params».

Сводка результатов поиска по сетке

Рассмотрим результаты поиска по сетке.

cv_results = pd.DataFrame(grid_search.cv_results_)
cv_results.sort_values(by="rank_test_d2_log_loss_score", ascending=True)
mean_fit_time std_fit_time mean_score_time std_score_time param_logisticregression__C param_standardscaler__with_std params split0_test_d2_log_loss_score split1_test_d2_log_loss_score split2_test_d2_log_loss_score split3_test_d2_log_loss_score split4_test_d2_log_loss_score mean_test_d2_log_loss_score std_test_d2_log_loss_score rank_test_d2_log_loss_score split0_test_accuracy split1_test_accuracy split2_test_accuracy split3_test_accuracy split4_test_accuracy mean_test_accuracy std_test_accuracy rank_test_accuracy split0_test_average_precision split1_test_average_precision split2_test_average_precision split3_test_average_precision split4_test_average_precision mean_test_average_precision std_test_average_precision rank_test_average_precision
1 1.267080 0.032673 0.019322 0.009167 0.01 False {'logisticregression__C': 0.01, 'standardscale... 0.135960 0.167780 0.189062 0.173567 0.186634 0.170601 0.019051 1 0.285 0.330 0.330 0.355 0.305 0.321 0.023958 1 0.319819 0.309708 0.360697 0.323126 0.340503 0.330771 0.017957 1
0 0.177192 0.019364 0.022506 0.008361 0.01 True {'logisticregression__C': 0.01, 'standardscale... 0.125785 0.112817 0.129538 0.127723 0.140616 0.127296 0.008883 2 0.290 0.275 0.315 0.320 0.280 0.296 0.018276 2 0.293645 0.258271 0.320959 0.290856 0.326432 0.298033 0.024429 2
2 0.439983 0.008141 0.011064 0.001072 1.00 True {'logisticregression__C': 1.0, 'standardscaler... -0.262989 -0.348023 -0.293989 -0.300126 -0.229700 -0.286965 0.039509 3 0.270 0.245 0.260 0.230 0.290 0.259 0.020591 5 0.299362 0.258130 0.268917 0.268336 0.276840 0.274317 0.013860 3
3 3.458270 0.147971 0.020982 0.011292 1.00 False {'logisticregression__C': 1.0, 'standardscaler... -0.344269 -0.424780 -0.381219 -0.380261 -0.299665 -0.366039 0.041863 4 0.280 0.250 0.260 0.230 0.280 0.260 0.018974 3 0.296932 0.259109 0.266720 0.268014 0.275371 0.273229 0.012926 4
4 0.530252 0.062160 0.016049 0.009084 100.00 True {'logisticregression__C': 100.0, 'standardscal... -0.455882 -0.566974 -0.524439 -0.507518 -0.417598 -0.494482 0.052390 5 0.285 0.235 0.265 0.230 0.285 0.260 0.023664 3 0.293392 0.253425 0.258071 0.263983 0.271392 0.268052 0.014024 5
5 3.874099 0.537535 0.011726 0.002423 100.00 False {'logisticregression__C': 100.0, 'standardscal... -0.458082 -0.571424 -0.526726 -0.510858 -0.419702 -0.497358 0.053110 6 0.285 0.235 0.255 0.230 0.285 0.258 0.023580 6 0.293282 0.253446 0.257693 0.263782 0.271130 0.267867 0.014034 6


Мы видим, что лучшие модели используют регуляризацию (малые значения C). Стандартизация признаков, по-видимому, не имеет большого значения, но помогает сократить время обучения. У многих моделей показатели точности схожи, но значения D² log-loss и средней точности различаются. D² log-loss и средняя точность чувствительнее к качеству модели, чем точность, поскольку они оценивают всё распределение вероятностей предсказаний, а не только совпадение наиболее вероятного предсказанного класса с истинным классом.

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

Эти значения хранятся в объекте обратного вызова scoring_monitor:

all_tasks_log = scoring_monitor.get_logs().data_as_pandas
all_tasks_log
task_id_path parent_task_id_path estimator_name task_name task_id sequential_subtasks d2_log_loss_score accuracy average_precision
0 (0, 1, 1) (0, 1) LogisticRegression fit 1 True 0.399415 0.53100 0.506463
1 (0, 0, 0, 1) (0, 0, 0) LogisticRegression fit 1 True 0.306252 0.56000 0.565995
2 (0, 0, 1, 1) (0, 0, 1) LogisticRegression fit 1 True 0.311447 0.57875 0.587007
3 (0, 0, 2, 1) (0, 0, 2) LogisticRegression fit 1 True 0.305960 0.56250 0.564362
4 (0, 0, 3, 1) (0, 0, 3) LogisticRegression fit 1 True 0.309061 0.58875 0.574045
... ... ... ... ... ... ... ... ... ...
2765 (0, 0, 29, 1, 192) (0, 0, 29, 1) LogisticRegression lbfgs-iter 192 True 0.552078 0.66750 0.557115
2766 (0, 0, 29, 1, 193) (0, 0, 29, 1) LogisticRegression lbfgs-iter 193 True 0.552078 0.66750 0.557045
2767 (0, 0, 29, 1, 194) (0, 0, 29, 1) LogisticRegression lbfgs-iter 194 True 0.552078 0.66750 0.557063
2768 (0, 0, 29, 1, 195) (0, 0, 29, 1) LogisticRegression lbfgs-iter 195 True 0.552078 0.66750 0.556962
2769 (0, 0, 29, 1, 196) (0, 0, 29, 1) LogisticRegression lbfgs-iter 196 True 0.552078 0.66750 0.556983

2770 строк × 9 столбцов



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

candidate_params = pd.DataFrame(grid_search.cv_results_["params"]).add_prefix("param_")

n_splits = grid_search.n_splits_
lbfgs_log = all_tasks_log.query(
    "estimator_name == 'LogisticRegression' and task_name == 'lbfgs-iter'"
).copy()
# Index 2 in ``task_id_path`` is the ``candidate-split-evaluation`` task id.
# Future versions of scikit-learn will provide a more convenient way to
# retrieve this task id.
lbfgs_log["eval_task_id"] = lbfgs_log["task_id_path"].map(lambda path: path[2])
lbfgs_log["candidate_idx"] = lbfgs_log["eval_task_id"] // n_splits
lbfgs_log["split_idx"] = lbfgs_log["eval_task_id"] % n_splits
lbfgs_log = lbfgs_log.query("split_idx == 0").join(candidate_params, on="candidate_idx")

Исключим финальное переобучение на полном наборе данных (parent_task_id_path начинается с (0, 1) вместо (0, 0) для моделей, обучаемых на фолдах кросс-валидации). При необходимости можно вызвать scoring_monitor.get_logs(include_lineage=True), чтобы получить имя задачи для задач-предков.

cv_lbfgs_log = lbfgs_log[
    lbfgs_log["parent_task_id_path"].map(lambda path: path[1]) == 0
]

Зададим подписи для построения графиков и построим график для каждой метрики отдельно.

cv_lbfgs_log["param_label"] = cv_lbfgs_log.apply(
    lambda row: (
        f"with_std={row['param_standardscaler__with_std']}, "
        f"C={row['param_logisticregression__C']:.2g}"
    ),
    axis=1,
)

metrics = {
    "d2_log_loss_score": "D² log-loss (train)",
    "accuracy": "Accuracy (train)",
    "average_precision": "Average precision (train)",
}
_, axes = plt.subplots(
    len(metrics),
    1,
    figsize=(8, 2.5 * len(metrics)),
    sharex=True,
    constrained_layout=True,
)
for idx, (metric, ylabel) in enumerate(metrics.items()):
    ax = axes[idx]
    for param_label, group in cv_lbfgs_log.groupby("param_label", sort=False):
        ax.plot(group["task_id"], group[metric], label=param_label)
    ax.set_ylabel(ylabel)
    if idx == 0:
        ax.set_title("CV split 0")
        ax.legend(title="Hyperparameters", fontsize="small")

_ = axes[-1].set_xlabel("L-BFGS iteration")
CV split 0

Анализ сходимости моделей логистической регрессии

Сходимость D² log-loss

Оценки D² log-loss, как правило, монотонно улучшаются для всех моделей. Это ожидаемо, поскольку модель логистической регрессии обучается минимизацией (регуляризованной) функции log-loss, вычисленной на обучающей выборке.

Колебания точности

Показатель точности растёт с увеличением числа итераций, хотя и с некоторыми локальными колебаниями. Это ожидаемо, поскольку точность — разрывная метрика, которую модель не оптимизирует напрямую. Вместо этого модель минимизирует функцию log-loss — гладкую аппроксимацию функции потерь zero-one (и поэтому связанную с точностью, но не оптимизируемую напрямую).

Регуляризация и масштабирование

Мы также видим, что модели с наименьшей регуляризацией (большие значения C) обычно достигают более высоких оценок D² log-loss, а модели, обученные на масштабированных признаках, сходятся за гораздо меньшее число итераций.

Кроме того, модели, обученные с сильной регуляризацией (меньшие значения C), сходятся к конечному значению D² log-loss, зависящему от силы регуляризации. Для моделей со слабой регуляризацией это не так: оптимальная сила регуляризации тесно связана с масштабированием признаков.

Средняя точность и log-loss: качество ранжирования и калибровка

Наконец, мы видим, что значение средней точности, измеренное на обучающей выборке, может быстро улучшаться на первых итерациях, а затем ухудшаться, несмотря на продолжающееся улучшение значения D² log-loss на тех же обучающих данных. Особенно заметно это для моделей, обученных со слабой регуляризацией и стандартизацией признаков. Это на первый взгляд парадоксальное поведение можно объяснить следующим образом. Прежде всего, напомним, что средняя точность — это метрика ранжирования, которая измеряет способность модели выдавать предсказанные вероятности, позволяющие расположить образцы заданного класса выше образцов других классов, но не учитывает калибровку предсказанных вероятностей. Иными словами, средняя точность оценивает лишь правильность взаимного упорядочивания предсказанных вероятностей и нечувствительна к преобразованию их абсолютных значений, сохраняющему ранжирование. Функция log-loss, напротив, является строго правильной scoring rule, которая учитывает как качество ранжирования модели, так и калибровку предсказанных вероятностей.

Таким образом, кривые средней точности моделей со слабой регуляризацией, обученных на масштабированных признаках, показывают, что первые итерации преимущественно улучшают качество ранжирования моделей, временно оставляя калибровку без внимания. На более поздних итерациях оценка log-loss продолжает улучшаться, но значения средней точности ухудшаются. Это позволяет предположить, что в ходе последних итераций модель логистической регрессии постепенно жертвует качеством ранжирования ради калибровки. Это явление изучалось в работе [1].

Было бы интересно проверить, происходит ли то же самое при оценке модели на валидационной выборке, чтобы реализовать досрочную остановку по средней точности и явно выбирать модель с высоким качеством ранжирования на валидационной выборке. На момент написания это пока невозможно. Планируется предоставить обратным вызовам доступ к валидационной выборке в будущей версии scikit-learn. Обратите внимание, что API обратных вызовов всё ещё является экспериментальным и может измениться без обычного цикла устаревания.

Ссылки

[1]

Berta, E., Holzmüller, D., Jordan, M. I. и Bach, F. «Переосмысление досрочной остановки: сначала уточнение, затем калибровка» (2025).

Общее время выполнения скрипта: (0 минут 27.101 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_scoring_monitor.ipynb

Download Python source code: plot_scoring_monitor.py

Download zipped: plot_scoring_monitor.zip

Связанные примеры

Пользовательская стратегия переобучения при поиске по сетке с кросс-валидацией

Сравнение калибровки классификаторов

Сравнение случайного поиска и поиска по сетке для подбора гиперпараметров

Траектория регуляризации логистической регрессии с L1-регуляризацией

© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/callbacks/plot_scoring_monitor.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API