1.17. Модели нейронных сетей (контролируемые)¶
Предупреждение
Данная реализация не предназначена для крупномасштабных приложений. В частности, scikit-learn не предлагает поддержки GPU. Более быстрые реализации на базе GPU, а также фреймворки, обеспечивающие гораздо большую гибкость при построении архитектур глубокого обучения, см. в Related Projects.
1.17.1. Многослойный перцептрон¶
Многослойный перцептрон (Multi-layer Perceptron - MLP) - это алгоритм контролируемого обучения, который обучает функцию \(f(\cdot): R^m \rightarrow R^o\) путем обучения на наборе данных, где \(m\) - количество размерностей для входа, а \(o\) - количество размерностей для выхода. Учитывая набор признаков \(X = {x_1, x_2, ..., x_m}\) и цель \(y\), он может выучить аппроксиматор нелинейной функции для классификации или регрессии. Она отличается от логистической регрессии тем, что между входным и выходным слоем может быть один или несколько нелинейных слоев, называемых скрытыми слоями. На рисунке 1 показан MLP с одним скрытым слоем и скалярным выходом.
Самый левый слой, известный как входной, состоит из набора нейронов \(\{x_i | x_1, x_2, ..., x_m\}\), представляющих входные признаки. Каждый нейрон в скрытом слое преобразует значения из предыдущего слоя с помощью взвешенного линейного сложения \(w_1x_1 + w_2x_2 + ... + w_mx_m\), за которым следует нелинейная функция активации \(g(\cdot):R \rightarrow R\) - подобно гиперболической функции tan. Выходной слой получает значения из последнего скрытого слоя и преобразует их в выходные значения.
Модуль содержит публичные атрибуты coefs_
и intercepts_
. coefs_
- это список матриц весов, где матрица весов с индексом \(i\) представляет собой веса между слоем \(i\) и слоем \(i+1\). intercepts_
- список векторов смещения, где вектор с индексом \(i\) представляет значения смещения, добавленные к слою \(i+1\).
Преимуществами многослойного перцептрона являются:
Возможность обучения нелинейным моделям.
Возможность обучения моделей в реальном времени (on-line обучение) с помощью
partial_fit
.
К недостаткам многослойного перцептрона (MLP) относятся:
MLP со скрытыми слоями имеют невыпуклую функцию потерь, в которой существует более одного локального минимума. Поэтому различные случайные инициализации весов могут привести к разной точности проверки.
MLP требует настройки ряда гиперпараметров, таких как количество скрытых нейронов, слоев и итераций.
MLP чувствительна к масштабированию признаков.
См. раздел Советы по практическому использованию, в котором рассматриваются некоторые из этих недостатков.
1.17.2. Классификация¶
Класс MLPClassifier
реализует алгоритм многослойного перцептрона (MLP), который обучается по методу Метод обратного распространения ошибки (Backpropagation).
MLP обучается на двух массивах: массиве X
размером (n_samples, n_features)
, который содержит обучающие выборки, представленные в виде векторов признаков с плавающей точкой, и массиве y
размером (n_samples,)
, который содержит целевые значения (метки классов) для обучающих выборок:
>>> from sklearn.neural_network import MLPClassifier
>>> X = [[0., 0.], [1., 1.]]
>>> y = [0, 1]
>>> clf = MLPClassifier(solver='lbfgs', alpha=1e-5,
... hidden_layer_sizes=(5, 2), random_state=1)
...
>>> clf.fit(X, y)
MLPClassifier(alpha=1e-05, hidden_layer_sizes=(5, 2), random_state=1,
solver='lbfgs')
После обучении модель может предсказывать метки для новых образцов:
>>> clf.predict([[2., 2.], [-1., -2.]])
array([1, 0])
MLP может обучать нелинейную модель к обучающим данным. clf.coefs_
содержит весовые матрицы, определяющие параметры модели:
>>> [coef.shape for coef in clf.coefs_]
[(2, 5), (5, 2), (2, 1)]
В настоящее время MLPClassifier
поддерживает только функцию потерь Cross-Entropy, которая позволяет оценить вероятность, выполнив метод predict_proba
.
MLP обучается с помощью обратного распространения. Точнее, он обучается с помощью некоторой формы градиентного спуска, а градиенты вычисляются с помощью Backpropagation. Для классификации он минимизирует функцию потерь Cross-Entropy, давая вектор оценок вероятности \(P(y|x)\) на выборку \(x\):
>>> clf.predict_proba([[2., 2.], [1., 2.]])
array([[1.967...e-04, 9.998...-01],
[1.967...e-04, 9.998...-01]])
MLPClassifier
поддерживает многоклассовую классификацию, применяя в качестве выходной функции Softmax.
Кроме того, модель поддерживает классификацию по нескольким меткам, в которой образец может принадлежать более чем одному классу. Для каждого класса исходный результат проходит через логистическую функцию. Значения, большие или равные 0.5
, округляются до 1
, в противном случае - до 0
.
Для предсказанного вывода выборки индексы, в которых значение равно 1
, представляют собой назначенные классы этой выборки:
>>> X = [[0., 0.], [1., 1.]]
>>> y = [[0, 1], [1, 1]]
>>> clf = MLPClassifier(solver='lbfgs', alpha=1e-5,
... hidden_layer_sizes=(15,), random_state=1)
...
>>> clf.fit(X, y)
MLPClassifier(alpha=1e-05, hidden_layer_sizes=(15,), random_state=1,
solver='lbfgs')
>>> clf.predict([[1., 2.]])
array([[1, 1]])
>>> clf.predict([[0., 0.]])
array([[0, 1]])
Более подробную информацию см. в примерах ниже и в строке документации MLPClassifier.fit
.
1.17.3. Регрессия¶
Класс MLPRegressor
реализует многослойный перцептрон (MLP), который обучается с помощью обратного распространения без функции активации в выходном слое, что также можно рассматривать как использование функции тождества в качестве функции активации. Поэтому в качестве функции потерь используется квадратичная ошибка, а на выходе получается набор непрерывных значений.
MLPRegressor
также поддерживает многовыходную регрессию, в которой выборка может иметь более одной цели.
1.17.4. Регуляризация¶
Как в MLPRegressor
, так и в MLPClassifier
используется параметр alpha
для регуляризации (L2 regularization), который помогает избежать переобучения, штрафуя веса с большими величинами. Следующий график показывает изменение функции принятия решения в зависимости от значения параметра alpha.
Смотрите примеры ниже для получения дополнительной информации.
1.17.5. Алгоритмы¶
MLP обучается с помощью Стохастический градиентный спуск (Stochastic Gradient Descent), Adam, или L-BFGS. Стохастический градиентный спуск (SGD) обновляет параметры, используя градиент функции потерь относительно параметра, требующего адаптации, т.е.
где \(\eta\) - скорость обучения, которая управляет размером шага в поиске пространства параметров. \(Loss\) - функция потерь, используемая для сети.
Более подробную информацию можно найти в документации к SGD
.
Adam похож на SGD в том смысле, что это стохастический оптимизатор, но он может автоматически регулировать количество обновлений параметров на основе адаптивных оценок моментов низшего порядка.
В SGD и Adam обучение поддерживается в режиме онлайн и в мини-пакетах.
L-BFGS - это алгоритм, который аппроксимирует матрицу Гессиана, представляющую собой частную производную функции второго порядка. Далее он аппроксимирует обратную матрицу Гессиана для выполнения обновления параметров. В реализации используется Scipy-версия L-BFGS.
Если выбран алгоритм ‘L-BFGS’, обучение не поддерживает ни онлайн, ни мини-пакетное обучение.
1.17.6. Сложность¶
Предположим, что есть \(n\) обучающих выборок, \(m\) признаков, \(k\) скрытых слоев, каждый из которых содержит \(h\) нейронов - для простоты, и \(o\) выходных нейронов. Временная сложность обратного распространения равна \(O(n\cdot m \cdot h^k \cdot o \cdot i)\), где \(i\) - количество итераций. Поскольку обратное распространение имеет высокую временную сложность, рекомендуется начинать с меньшего числа скрытых нейронов и нескольких скрытых слоев для обучения.
1.17.7. Математическая формулировка¶
Дан набор обучающих примеров \((x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)\) где \(x_i \in \mathbf{R}^n\) и \(y_i \in \{0, 1\}\), один скрытый слой, один скрытый нейрон, MLP изучает функцию \(f(x) = W_2 g(W_1^T x + b_1) + b_2\) где \(W_1 \in \mathbf{R}^m\) и \(W_2, b_1, b_2 \in \mathbf{R}\) параметры модели. \(W_1, W_2\) представляют веса входного и скрытого слоев соответственно; и \(b_1, b_2\) представляют смещение, добавленное к скрытому слою и выходному слою соответственно. \(g(\cdot) : R \rightarrow R\) - это функция активации, установленная по умолчанию как гиперболический тангенс. Это дано как,
Для бинарной классификации \(f(x)\) проходит через логистическую функцию \(g(z)=1/(1+e^{-z})\) для получения выходных значений между нулем и единицей. Порог, установленный на 0.5, отнесет выборки с выходом, большим или равным 0.5, к положительному классу, а остальные - к отрицательному.
Если классов больше двух, то \(f(x)\) сам по себе будет вектором размера (n_classes,). Вместо того чтобы проходить через логистическую функцию, он проходит через функцию softmax, которая записывается как,
где \(z_i\) представляет \(i\)-й элемент входа в softmax, который соответствует классу \(i\), а \(K\) - количество классов. Результатом является вектор, содержащий вероятности того, что выборка \(x\) принадлежит каждому классу. Выходом является класс с наибольшей вероятностью.
В регрессии выход остается как \(f(x)\); поэтому функция активации выхода - это просто функция тождества.
MLP использует различные функции потерь в зависимости от типа задачи. Для классификации используется функция потерь Average Cross-Entropy, которая в двоичном случае имеет вид,
где \(\alpha ||W||_2^2\) - L2-регуляризационный член (он же штраф), который наказывает сложные модели; и \(\alpha > 0\) - неотрицательный гиперпараметр, который управляет величиной штрафа.
Для регрессии MLP использует функцию потерь по среднему квадрату ошибки, которая записывается как,
Начиная с начальных случайных весов, многослойный перцептрон (MLP) минимизирует функцию потерь путем многократного обновления этих весов. После вычисления потерь обратный проход распространяет их от выходного слоя к предыдущим слоям, предоставляя каждому весовому параметру обновленное значение, предназначенное для уменьшения потерь.
При градиентном спуске вычисляется градиент \(\nabla Loss_{W}\) потерь по отношению к весам и вычитается из \(W\). Более формально это выражается как,
где \(i\) - шаг итерации, а \(\epsilon\) - скорость обучения со значением больше 0.
Алгоритм останавливается, когда достигает заданного максимального числа итераций; или когда улучшение потерь ниже определенного, небольшого числа.
1.17.8. Советы по практическому использованию¶
Многослойный перцептрон чувствителен к масштабированию признаков, поэтому настоятельно рекомендуется масштабировать ваши данные. Например, масштабируйте каждый признак входного вектора X на [0, 1] или [-1, +1], или стандартизируйте его так, чтобы среднее значение было 0, а дисперсия - 1. Обратите внимание, что для получения значимых результатов необходимо применить такое же масштабирование к тестовому набору. Для стандартизации можно использовать
StandardScaler
.>>> from sklearn.preprocessing import StandardScaler >>> scaler = StandardScaler() >>> # Don't cheat - fit only on training data >>> scaler.fit(X_train) >>> X_train = scaler.transform(X_train) >>> # apply same transformation to test data >>> X_test = scaler.transform(X_test)
Альтернативным и рекомендуемым подходом является использование
StandardScaler
вPipeline
Для поиска разумного параметра регуляризации \(\alpha\) лучше всего использовать
GridSearchCV
, обычно в диапазоне10.0 ** -np.arange(1, 7)
.Эмпирически мы заметили, что
L-BFGS
сходится быстрее и имеет лучшие решения на небольших наборах данных. Однако для относительно больших наборов данныхAdam
очень устойчив. Обычно он быстро сходится и дает довольно хорошую производительность. С другой стороны,SGD
с импульсом или импульсом Нестерова может работать лучше, чем эти два алгоритма, если правильно настроить скорость обучения.
1.17.9. Больше контроля с помощью warm_start¶
Если вы хотите получить больше контроля над критериями остановки или скоростью обучения в SGD, или хотите провести дополнительный мониторинг, использование warm_start=True
и max_iter=1
и самостоятельных итераций может быть полезным:
>>> X = [[0., 0.], [1., 1.]]
>>> y = [0, 1]
>>> clf = MLPClassifier(hidden_layer_sizes=(15,), random_state=1, max_iter=1, warm_start=True)
>>> for i in range(10):
... clf.fit(X, y)
... # additional monitoring / inspection
MLPClassifier(...