Spec-Zone.ru › scikit-learn

Примечание

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

Признаки машины Больцмана с ограничениями для классификации цифр

Для данных изображений в оттенках серого, где значения пикселей можно интерпретировать как степень черноты на белом фоне, например при распознавании рукописных цифр, модель машины Больцмана с ограничениями Бернулли (BernoulliRBM) может эффективно выполнять нелинейное извлечение признаков.

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

Генерация данных

Чтобы получить качественные скрытые представления из небольшого набора данных, мы искусственно генерируем дополнительные размеченные данные, сдвигая обучающие данные на 1 пиксель в каждом направлении.

import numpy as np
from scipy.ndimage import convolve

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import minmax_scale


def nudge_dataset(X, Y):
    """
    This produces a dataset 5 times bigger than the original one,
    by moving the 8x8 images in X around by 1px to left, right, down, up
    """
    direction_vectors = [
        [[0, 1, 0], [0, 0, 0], [0, 0, 0]],
        [[0, 0, 0], [1, 0, 0], [0, 0, 0]],
        [[0, 0, 0], [0, 0, 1], [0, 0, 0]],
        [[0, 0, 0], [0, 0, 0], [0, 1, 0]],
    ]

    def shift(x, w):
        return convolve(x.reshape((8, 8)), mode="constant", weights=w).ravel()

    X = np.concatenate(
        [X] + [np.apply_along_axis(shift, 1, X, vector) for vector in direction_vectors]
    )
    Y = np.concatenate([Y for _ in range(5)], axis=0)
    return X, Y


X, y = datasets.load_digits(return_X_y=True)
X = np.asarray(X, "float32")
X, Y = nudge_dataset(X, y)
X = minmax_scale(X, feature_range=(0, 1))  # 0-1 scaling

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)

Определение моделей

Мы создаём конвейер классификации с экстрактором признаков BernoulliRBM и классификатором LogisticRegression.

from sklearn import linear_model
from sklearn.neural_network import BernoulliRBM
from sklearn.pipeline import Pipeline

logistic = linear_model.LogisticRegression(solver="newton-cg", tol=1)
rbm = BernoulliRBM(random_state=0, verbose=True)

rbm_features_classifier = Pipeline(steps=[("rbm", rbm), ("logistic", logistic)])

Обучение

Гиперпараметры всей модели (скорость обучения, размер скрытого слоя, регуляризация) были оптимизированы с помощью поиска по сетке, но результаты поиска здесь не приводятся из-за ограничений по времени выполнения.

from sklearn.base import clone

# Hyper-parameters. These were set by cross-validation,
# using a GridSearchCV. Here we are not performing cross-validation to
# save time.
rbm.learning_rate = 0.06
rbm.n_iter = 10

# More components tend to give better prediction performance, but larger
# fitting time
rbm.n_components = 100
logistic.C = 6000

# Training RBM-Logistic Pipeline
rbm_features_classifier.fit(X_train, Y_train)

# Training the Logistic regression classifier directly on the pixel
raw_pixel_classifier = clone(logistic)
raw_pixel_classifier.C = 100.0
raw_pixel_classifier.fit(X_train, Y_train)
[BernoulliRBM] Iteration 1, pseudo-likelihood = -25.57, time = 0.10s
[BernoulliRBM] Iteration 2, pseudo-likelihood = -23.68, time = 0.15s
[BernoulliRBM] Iteration 3, pseudo-likelihood = -22.88, time = 0.14s
[BernoulliRBM] Iteration 4, pseudo-likelihood = -21.91, time = 0.14s
[BernoulliRBM] Iteration 5, pseudo-likelihood = -21.79, time = 0.14s
[BernoulliRBM] Iteration 6, pseudo-likelihood = -20.96, time = 0.14s
[BernoulliRBM] Iteration 7, pseudo-likelihood = -20.88, time = 0.13s
[BernoulliRBM] Iteration 8, pseudo-likelihood = -20.50, time = 0.14s
[BernoulliRBM] Iteration 9, pseudo-likelihood = -20.36, time = 0.13s
[BernoulliRBM] Iteration 10, pseudo-likelihood = -20.07, time = 0.14s
LogisticRegression(C=100.0, solver='newton-cg', tol=1)
В среде Jupyter повторно запустите эту ячейку, чтобы отобразить HTML-представление, или доверьте этому блокноту.
На GitHub HTML-представление не удаётся отобразить; попробуйте загрузить эту страницу с помощью nbviewer.org.
Параметры
C C: float, по умолчанию=1.0

Обратная сила регуляризации; должна быть положительным числом с плавающей точкой.
Как и в машинах опорных векторов, меньшие значения задают более сильную
регуляризацию. `C=np.inf` приводит к логистической регрессии без штрафа.
Наглядный пример влияния настройки параметра `C`
со штрафом L1 см. в разделе:
:ref:`sphx_glr_auto_examples_linear_model_plot_logistic_path.py`.
100.0
tol tol: float, по умолчанию=1e-4

Допуск для критерия остановки.
1
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:`Table <logistic_regression_solvers>` с описанием поддержки решателями разных штрафов,
см. в :ref:`Руководстве пользователя <Logistic_regression>`.

.. versionadded:: 0.17
Решатель стохастического градиентного спуска с усреднением (SAG). Поддержка мультиномиальной классификации добавлена в
версии 0.18.
.. versionadded:: 0.19
Решатель SAGA.
.. versionchanged:: 0.22
В версии 0.22 решатель по умолчанию изменён с 'liblinear' на 'lbfgs'.
.. versionadded:: 1.2
Решатель newton-cholesky. Поддержка мультиномиальной классификации добавлена в версии 1.6.
'newton-cg'
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`. Задайте `l1_ratio=0` для `penalty='l2'`,
`l1_ratio=1` для `penalty='l1'`, любое значение `l1_ratio` от 0 до 1
для `penalty='elasticnet'` и `C=np.inf` для `penalty=None`.
'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. Если n_samples > n_features, предпочтительно задавать `dual=False`.
False
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, эти веса будут перемножены с ним (он передаётся
в метод fit).

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

Используется для перемешивания данных, когда ``solver`` равен 'sag', 'saga' или 'liblinear'.
Подробнее см. в :term:`глоссарии <random_state>`.
None
max_iter max_iter: int, по умолчанию=100

Максимальное число итераций, выполняемых решателями для достижения сходимости.
100
verbose verbose: int, по умолчанию=0

Для решателей liblinear и lbfgs задайте любое положительное значение,
чтобы включить подробный вывод.
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[float32](10, 64) [[0.,0.,0.,...,0.,0.,0.], [0.,0.,0.,...,0.,0.,0.], [0.,0.,0.,...,0.,0.,0.], ..., [0.,0.,0.,...,0.,0.,0.], [0.,0.,0.,...,0.,0.,0.], [0.,0.,0.,...,0.,0.,0.]]
intercept_ intercept_: ndarray формы (1,) или (n_classes,)

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

Если параметру `fit_intercept` присвоено значение False, свободный член равен нулю.
`intercept_` имеет форму (1,), если рассматриваемая задача является бинарной.
ndarray[float32](10,) [0.,0.,0.,...,0.,0.,0.]
n_features_in_ n_features_in_: int

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

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

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

.. versionchanged:: 0.20

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


Оценка

from sklearn import metrics

Y_pred = rbm_features_classifier.predict(X_test)
print(
    "Logistic regression using RBM features:\n%s\n"
    % (metrics.classification_report(Y_test, Y_pred))
)
/home/circleci/project/sklearn/metrics/_classification.py:1879: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, f"{metric.capitalize()} is", result.shape[0])
/home/circleci/project/sklearn/metrics/_classification.py:1879: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, f"{metric.capitalize()} is", result.shape[0])
/home/circleci/project/sklearn/metrics/_classification.py:1879: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, f"{metric.capitalize()} is", result.shape[0])
Logistic regression using RBM features:
              precision    recall  f1-score   support

           0       0.10      1.00      0.18       174
           1       0.00      0.00      0.00       184
           2       0.00      0.00      0.00       166
           3       0.00      0.00      0.00       194
           4       0.00      0.00      0.00       186
           5       0.00      0.00      0.00       181
           6       0.00      0.00      0.00       207
           7       0.00      0.00      0.00       154
           8       0.00      0.00      0.00       182
           9       0.00      0.00      0.00       169

    accuracy                           0.10      1797
   macro avg       0.01      0.10      0.02      1797
weighted avg       0.01      0.10      0.02      1797
Y_pred = raw_pixel_classifier.predict(X_test)
print(
    "Logistic regression using raw pixel features:\n%s\n"
    % (metrics.classification_report(Y_test, Y_pred))
)
/home/circleci/project/sklearn/metrics/_classification.py:1879: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, f"{metric.capitalize()} is", result.shape[0])
/home/circleci/project/sklearn/metrics/_classification.py:1879: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, f"{metric.capitalize()} is", result.shape[0])
/home/circleci/project/sklearn/metrics/_classification.py:1879: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, f"{metric.capitalize()} is", result.shape[0])
Logistic regression using raw pixel features:
              precision    recall  f1-score   support

           0       0.10      1.00      0.18       174
           1       0.00      0.00      0.00       184
           2       0.00      0.00      0.00       166
           3       0.00      0.00      0.00       194
           4       0.00      0.00      0.00       186
           5       0.00      0.00      0.00       181
           6       0.00      0.00      0.00       207
           7       0.00      0.00      0.00       154
           8       0.00      0.00      0.00       182
           9       0.00      0.00      0.00       169

    accuracy                           0.10      1797
   macro avg       0.01      0.10      0.02      1797
weighted avg       0.01      0.10      0.02      1797

Признаки, извлечённые BernoulliRBM, помогают повысить точность классификации по сравнению с логистической регрессией на исходных пикселях.

Построение графиков

import matplotlib.pyplot as plt

plt.figure(figsize=(4.2, 4))
for i, comp in enumerate(rbm.components_):
    plt.subplot(10, 10, i + 1)
    plt.imshow(comp.reshape((8, 8)), cmap=plt.cm.gray_r, interpolation="nearest")
    plt.xticks(())
    plt.yticks(())
plt.suptitle("100 components extracted by RBM", fontsize=16)
plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23)

plt.show()
100 components extracted by RBM

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

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_rbm_logistic_classification.ipynb

Download Python source code: plot_rbm_logistic_classification.py

Download zipped: plot_rbm_logistic_classification.zip

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

Построение графика вероятностей классификации

Разреженная многоклассовая логистическая регрессия на наборе 20newgroups

Конвейерная обработка: объединение PCA и логистической регрессии

Границы принятия решений мультиномиальной логистической регрессии и регрессии «один против остальных»

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

Spec-Zone.ru

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