Кодировать слова непросто, пожалуйста, поставьте лайк!
Добро пожаловать на обмен и перепечатку, статья будет опубликована одновременно в паблике: Machine Learning Algorithm Engineer (Jeemy110)
Эта статья переведена сAn Overview of Regularization Techniques in Deep Learning (with Python code), оригинальный автор сохраняет авторские права.
введение
Одна из самых распространенных проблем, с которыми сталкиваются специалисты по науке о данных, — как избежатьпереоснащение. Вы когда-нибудь сталкивались с ситуацией, когда ваша модель исключительно хорошо работала на обучающих данных, но не могла предсказать тестовые данные? Или вы начали с вершины общедоступной таблицы лидеров, но в итоге отстали на сотни позиций? Что ж, вам нужно прочитать эту статью!
Производительность модели можно улучшить, просто избегая переобучения.
В этой статье вы поймете концепцию переобучения и узнаете, как использовать регуляризацию для решения этой проблемы. Затем я расскажу о нескольких различных методах регуляризации и использую Python для проведения тематических исследований для дальнейшего закрепления этих концепций.
Примечание. В этой статье предполагается, что у вас есть базовые знания о нейронных сетях и их реализации с использованием keras. Если нет, вы можете сначала обратиться к следующим статьям:
- Основы глубокого обучения — начиная с искусственной нейронной сети
- Tutorial: Optimizing Neural Networks using Keras (with Image recognition case study)
Что такое регуляризация?
Вы видели эту картину раньше? Слева направо модель пытается хорошо изучить детали и шум в обучающих данных, что в конечном итоге приводит к плохой работе с неизвестными данными. Другими словами, при движении вправо сложность модели увеличивается и ошибка обучения уменьшается, а ошибка теста — нет, как показано на рисунке ниже.
Если вы разрабатывали модели нейронных сетей, вы знаете, что они сложны, что делает их склонными к переоснащению.
Регуляризация точно настраивает алгоритм обучения, чтобы модель лучше обобщала, что, в свою очередь, повышает производительность модели на неизвестных данных.
Почему регуляризация помогает уменьшить переоснащение?
Как показано на рисунке ниже, модель нейронной сети переоснащена на обучающих выборках.
Если вы знакомы с концепцией регуляризации в машинном обучении, вы знаете, что это штрафной коэффициент. В глубоком обучении это весовая матрица, которая наказывает каждый узел. Предположим, что наш коэффициент регуляризации настолько велик, что некоторые элементы весовой матрицы равны 0.
Это приведет к тому, что окончательная модель будет простой линейной сетью и, возможно, не подойдет для обучающих выборок. Следовательно, такой большой коэффициент регуляризации бесполезен, нам нужен подходящий коэффициент регуляризации, который позволяет получить модель обобщения, как показано на следующем рисунке:
Стратегии регуляризации в глубоком обучении
Теперь мы понимаем, как регуляризация может помочь уменьшить переоснащение. Чтобы применить регуляризацию к глубокому обучению, вот несколько различных методов регуляризации.
Регуляризация L2 и L1
L1 и L2 являются наиболее распространенными методами регуляризации. Они добавляют член регуляризации к функции стоимости:
Из-за добавления этого члена регуляризации значение матрицы весов уменьшается, поскольку предполагается, что нейронная сеть с меньшей матрицей весов приводит к более простой модели. Следовательно, это также в некоторой степени снижает переоснащение. Однако этот член регуляризации различен в L1 и L2.
Для уровня 2:
здесь,– параметр регуляризации. Это гиперпараметр, который необходимо оптимизировать. Регуляризация L2 также известна как уменьшение веса.
распад, с точки зрения градиентного спуска), потому что это заставляет веса стремиться к 0 (но не ко всем 0).
Для уровня 1:
Здесь мы штрафуем абсолютное значение весовой матрицы. В отличие от L2, значение веса может быть уменьшено до 0. Таким образом, L1 полезен для сжатия моделей. В других случаях общий выбор состоит в том, чтобы предпочесть регуляризацию L2.
существуетKeras, мы используеммодуль регуляризаторовприменить регуляризацию L1 или L2 к определенному слою. Вот применение регуляризации L2 на плотном слое:
from keras import regularizers
model.add(Dense(64, input_dim=64,
kernel_regularizer=regularizers.l2(0.01)
Примечание: 0,01 — это значение $\lambda$, упомянутое выше, которое является гиперпараметром, который необходимо дополнительно оптимизировать.Вы можете использоватьМетод поиска по сетке (grid-search)оптимизировать.
Точно так же мы также можем использовать регуляризацию L1, которая будет объяснена более подробно в следующем примере.
Dropout
Это один из самых интересных методов регуляризации. Он может дать очень хорошие результаты и поэтому является наиболее часто используемым методом регуляризации в области глубокого обучения. Чтобы понять отсев, предположим, что структура нашей нейронной сети аналогична показанной ниже:
Принцип Dropout прост: во время каждой итерации случайным образом выбираются некоторые узлы, а прямые и обратные соединения удаляются, как показано на следующем рисунке:
Следовательно, каждый итерационный процесс будет иметь разную комбинацию узлов, что приведет к разным результатам. Это можно рассматривать как метод ансамбля в машинном обучении. Ансамблевые модели, как правило, лучше, чем отдельные модели, потому что они охватывают больше случайностей. Точно так же отсев заставляет модели нейронных сетей превосходить обычные модели.
Значение вероятности выбора количества удаляемых узлов является гиперпараметром. Как показано на рисунке выше, выпадение можно применить не только к скрытому слою, но и к входному слою.
По этим причинам отсев часто предпочтительнее, чтобы ввести больше случайности, когда у нас есть более крупные нейронные сети.
В Керасе мы можем использоватьвыпадающий слойДля реализации отсева код выглядит следующим образом:
from keras.layers.core import Dropout
model = Sequential([
Dense(output_dim=hidden1_num_units, input_dim=input_num_units, activation='relu'),
Dropout(0.25),
Dense(output_dim=output_num_units, input_dim=hidden5_num_units, activation='softmax'),
])
Видно, что значение вероятности отсева, установленное отсевом, равно 0,25, что также может быть дополнительно оптимизировано методом поиска по сетке.
увеличение данных
Самый простой способ уменьшить переобучение — увеличить обучающую выборку. В машинном обучении, поскольку помеченные данные дороги, мы не можем увеличить количество обучающих выборок. Но для задач с изображениями существует несколько способов увеличения обучающих выборок — вращение, переворачивание, масштабирование, смещение и т. д. Вот некоторые преобразования изображений в наборе данных MNIST:
Этот метод называется агументацией данных, и он часто значительно повышает точность модели. Обычно считается, что это обязательный метод для улучшения прогнозов.
В Керасе вы можете использоватьImageDataGeneratorЧтобы реализовать вышеуказанное преобразование изображения, у него есть много параметров для управления тем, как вы предварительно обрабатываете обучающие данные. Вот пример кода:
from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(horizontal_flip=True)
datagen.fit(train)
ранняя остановка
Ранняя остановка — это стратегия перекрестной проверки, в которой мы используем часть обучающего набора в качестве набора проверки. Когда мы увидели, что производительность на проверочном наборе становится все хуже и хуже, мы сразу же прекратили обучение модели. Это называется ранней остановкой.
На изображении выше мы останавливаем обучение модели на пунктирной линии, и в этот момент модель начинает соответствовать обучающим данным.
В Керасе мы можем использоватьcallbacksФункция реализует раннюю остановку, пример кода ниже:
from keras.callbacks import EarlyStopping
EarlyStopping(monitor='val_err', patience=5)
выше,monitor
Параметр указывает количество мониторинга, здесьval_err
представляет ошибку набора проверки. иpatience
Количество эпох параметра, когда в этом процессе не будет улучшения производительности, обучение будет остановлено. Для лучшего понимания давайте еще раз взглянем на изображение выше. После пунктирной линии каждая эпоха приводит к более высокой ошибке набора проверки. Следовательно, через 5 эпох после пунктира (patience
равно 5), модель прекратит обучение, потому что дальнейшее улучшение невозможно.
Примечание: на 5 эпохах (обычно устанавливаетсяpatience
значение), модель может снова начать улучшаться, и ошибка набора проверки начнет уменьшаться. Поэтому нам нужно быть осторожными при настройке этого гиперпараметра..
Пример MNIST на основе Keras
На данный момент у вас есть теоретическое понимание различных стратегий регуляризации. Ниже мы будем использовать эти знания для решения задачи глубокого обучения — распознавания рукописного шрифта, набора данных MNIST. Keras содержит этот набор данных. Во-первых, мы импортируем некоторые основные библиотеки.
import numpy as np
import matplotlib.pyplot as plt
from keras import Sequential
from keras.layers import Dense, Dropout
from keras.datasets import mnist
from keras.utils import to_categorical
from keras.preprocessing.image import ImageDataGenerator
from keras import regularizers
from keras.callbacks import EarlyStopping
# 避免随机性,可以重复试验
seed = 128
rng = np.random.RandomState(seed)
Затем загрузите набор данных:
# 加载数据集
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
Визуализируйте несколько картинок:
img_idx = rng.randint(len(train_images))
img = train_images[img_idx]
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.show()
Создайте проверочный набор для оптимизации модели, здесь соотношение обучающего набора к проверочному набору составляет 7:3:
train_images, train_labels = train_images[:50000], train_labels[:50000] # 使用部分数据
train_images = train_images.reshape((-1, 28*28)).astype(np.float32) / 255.0
test_images = test_images.reshape((-1, 28*28)).astype(np.float32) / 255.0
train_labels = to_categorical(train_labels, 10)
test_labels = to_categorical(test_labels, 10)
split_size = int(len(train_images) * 0.7)
x_train, y_train = train_images[:split_size], train_labels[:split_size]
x_val, y_val = train_images[split_size:], train_labels[split_size:]
Сначала мы создаем простую нейронную сеть с 5 скрытыми слоями, а количество нейронов скрытого слоя равно 500.
# 定义参数
input_num_units = 784
hidden1_num_units = 500
hidden2_num_units = 500
hidden3_num_units = 500
hidden4_num_units = 500
hidden5_num_units = 500
output_num_units = 10
epochs = 10
batch_size = 128
model = Sequential([
Dense(hidden1_num_units, input_shape=(input_num_units,), activation='relu'),
Dense(hidden2_num_units, activation='relu'),
Dense(hidden3_num_units, activation='relu'),
Dense(hidden4_num_units, activation='relu'),
Dense(hidden5_num_units, activation='relu'),
Dense(output_num_units, activation='softmax'),]
)
Затем мы тренируемся в течение 10 эпох и видим производительность модели:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
trained_model_5d = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=2, validation_data=(x_val, y_val))
Затем мы добавляем регуляризацию L2, чтобы увидеть, улучшается ли модель по сравнению с оригиналом:
reg_w = 1e-4
model = Sequential([
Dense(hidden1_num_units, input_shape=(input_num_units,), activation='relu', kernel_regularizer=regularizers.l2(reg_w)),
Dense(hidden2_num_units, activation='relu', kernel_regularizer=regularizers.l2(reg_w)),
Dense(hidden3_num_units, activation='relu', kernel_regularizer=regularizers.l2(reg_w)),
Dense(hidden4_num_units, activation='relu', kernel_regularizer=regularizers.l2(reg_w)),
Dense(hidden5_num_units, activation='relu', kernel_regularizer=regularizers.l2(reg_w)),
Dense(output_num_units, activation='softmax'),]
)
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
trained_model_5d = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=2, validation_data=(x_val, y_val))
выше мы использовалиПри значении 0,0001 обученная модель более точна, чем исходная модель.
Затем попробуйте регуляризацию L1:
## l1
reg_w = 1e-4
model = Sequential([
Dense(hidden1_num_units, input_shape=(input_num_units,), activation='relu', kernel_regularizer=regularizers.l1(reg_w)),
Dense(hidden2_num_units, activation='relu', kernel_regularizer=regularizers.l1(reg_w)),
Dense(hidden3_num_units, activation='relu', kernel_regularizer=regularizers.l1(reg_w)),
Dense(hidden4_num_units, activation='relu', kernel_regularizer=regularizers.l1(reg_w)),
Dense(hidden5_num_units, activation='relu', kernel_regularizer=regularizers.l1(reg_w)),
Dense(output_num_units, activation='softmax'),]
)
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
trained_model_5d = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=2, validation_data=(x_val, y_val))
Видно, что нет улучшения производительности при использовании регуляризации L1. Затем попробуйте стратегию отсева:
## dropout
from keras.layers.core import Dropout
model = Sequential([
Dense(output_dim=hidden1_num_units, input_dim=input_num_units, activation='relu'),
Dropout(0.25),
Dense(output_dim=hidden2_num_units, input_dim=hidden1_num_units, activation='relu'),
Dropout(0.25),
Dense(output_dim=hidden3_num_units, input_dim=hidden2_num_units, activation='relu'),
Dropout(0.25),
Dense(output_dim=hidden4_num_units, input_dim=hidden3_num_units, activation='relu'),
Dropout(0.25),
Dense(output_dim=hidden5_num_units, input_dim=hidden4_num_units, activation='relu'),
Dropout(0.25),
Dense(output_dim=output_num_units, input_dim=hidden5_num_units, activation='softmax'),
])
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
trained_model_5d = model.fit(x_train, y_train, nb_epoch=epochs, batch_size=batch_size, validation_data=(x_test, y_test))
Видно, что производительность модели немного улучшилась после использования отсева. Затем попробуйте методы увеличения данных:
train_images = np.reshape(train_images, (-1, 28, 28, 1))
datagen = ImageDataGenerator(rotation_range=20)
datagen.fit(train_images, augment=True)
Здесь, используяrotation_range
параметр, он повернет изображение на определенный угол, а затем обучит модель:
model = Sequential([
Dense(hidden1_num_units, input_shape=(input_num_units,), activation='relu'),
Dense(hidden2_num_units, activation='relu'),
Dense(hidden3_num_units, activation='relu'),
Dense(hidden4_num_units, activation='relu'),
Dense(hidden5_num_units, activation='relu'),
Dense(output_num_units, activation='softmax'),]
)
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
for e in range(epochs):
print('Epoch', e)
batches = 0
for x_batch, y_batch in datagen.flow(x_train, y_train, batch_size=batch_size):
x_batch = np.reshape(x_batch, (-1, 784)) / 255.0
model.train_on_batch(x_batch, y_batch)
batches += 1
if batches >= len(x_train) // batch_size:
# we need to break the loop by hand because
# the generator loops indefinitely
break
results = model.evaluate(x_val.reshape(-1, 784), y_val, verbose=0, batch_size=batch_size)
print(results)
После использования увеличения данных производительность повышается.Вы также можете попробовать другие методы увеличения данных.
Наконец, мы используем стратегию ранней остановки:
model = Sequential([
Dense(hidden1_num_units, input_shape=(input_num_units,), activation='relu'),
Dense(hidden2_num_units, activation='relu'),
Dense(hidden3_num_units, activation='relu'),
Dense(hidden4_num_units, activation='relu'),
Dense(hidden5_num_units, activation='relu'),
Dense(output_num_units, activation='softmax'),]
)
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
trained_model_5d = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=2,
validation_data=(x_val, y_val), callbacks=[EarlyStopping(monitor="val_acc", patience=2)])
В этот момент видно, что обучение останавливается на 8-й эпохе, потому что точность проверочного набора не улучшалась в течение 2-х последовательных эпох. Ранняя остановка хорошо работает для обучения больших эпох, вы можете думать об этом как об оптимизации количества эпох для обучения.
заключительные замечания
Я надеюсь, что теперь у вас есть понимание регуляризации и различных методов регуляризации в моделях глубокого обучения. Я настоятельно рекомендую вам применять его при работе с задачами глубокого обучения, это поможет вам расширить свой кругозор и лучше понять технику.
Примечание. Часть примера MNIST была немного изменена по сравнению с исходным текстом.
Кодировать слова непросто, пожалуйста, поставьте лайк!
Добро пожаловать на обмен и перепечатку, статья будет опубликована одновременно в паблике: Machine Learning Algorithm Engineer (Jeemy110)