Как обычно, код в этом примере будет использовать API tf.keras; подробности см. в руководстве TensorFlow Keras.
В предыдущих двух примерах (классификация обзоров фильмов и прогнозирование цен на жилье) мы узнали, что после определенного количества циклов обучения точность модели на проверочных данных достигает пика, а затем начинает снижаться.
То есть модель соответствует обучающим данным. Обязательно узнайте, как бороться с переоснащением. Хотя часто можно достичь очень высокой точности на обучающем наборе, мы действительно хотим разработать модели, которые хорошо обобщают тестовые данные (или данные, которых раньше не было).
Противоположностью переобучения является недообучивание. Недообучение происходит, когда еще есть возможности для улучшения тестовых данных. Это может произойти по ряду причин: модель недостаточно мощная, слишком регуляризирована или просто недостаточно долго обучалась. Это означает, что сеть не изучила соответствующие закономерности в обучающих данных.
Если время обучения слишком велико, модель начнет переоснащаться и изучать шаблоны из обучающих данных, которые нельзя обобщить на тестовые данные. Нам нужно найти баланс между ними. Знание того, как тренироваться для необходимого количества циклов, является полезным навыком, который мы рассмотрим далее.
Чтобы предотвратить переоснащение, лучшее решение — использовать больше обучающих данных. Модели, обученные на большем количестве данных, естественным образом обобщают лучше. Если это решение невозможно, следующим лучшим решением является использование таких методов, как регуляризация. Эти методы ограничивают количество и тип информации, которую может хранить модель. Если сеть может запомнить только небольшое количество паттернов, процесс оптимизации заставит ее сосредоточиться на наиболее заметных паттернах, поскольку у них больше шансов на лучшее обобщение.
В этой записной книжке мы рассмотрим два распространенных метода регуляризации (регуляризация веса и отсев) и используем их для улучшения нашей записной книжки класса теневой оценки IMDB.
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)
1.13.1
Загрузите набор данных IMDB
Вместо того, чтобы использовать вложения, как в предыдущей записной книжке, мы будем мульти-горячее кодировать предложения. Модель быстро перекроет тренировочный набор. Он будет использоваться для демонстрации того, когда происходит переобучение и как его предотвратить.
Списки мультигорячего кодирования означают преобразование их в вектор из 0 и 1. Например, преобразуйте последовательность [3, 5] в 10000-мерный вектор (все 0, кроме индексов 3 и 5, которые преобразуются в 1).
NUM_WORDS = 10000
(train_data, train_labels), (test_data, test_labels) = keras.datasets.imdb.load_data(num_words=NUM_WORDS)
def multi_hot_sequences(sequences, dimension):
# Create an all-zero matrix of shape (len(sequences), dimension)
results = np.zeros((len(sequences), dimension))
for i, word_indices in enumerate(sequences):
results[i, word_indices] = 1.0 # set specific indices of results[i] to 1s
return results
train_data = multi_hot_sequences(train_data, dimension=NUM_WORDS)
test_data = multi_hot_sequences(test_data, dimension=NUM_WORDS)
Давайте взглянем на один из сгенерированных мультигорячих векторов. Индексы терминов отсортированы по частоте, поэтому рядом с индексом 0 должно быть больше 1 значений, как показано на следующем изображении:
plt.plot(train_data[0])
[<matplotlib.lines.Line2D at 0x2318f5c0>]
Демонстрация переобучения
Самый простой способ предотвратить переобучение — это сжать модель, т. е. уменьшить количество обучаемых параметров в модели (определяется количеством слоев и количеством единиц на уровне). В глубоком обучении количество обучаемых параметров в модели часто называют «емкостью» модели. Интуитивно модель с большим количеством параметров имеет больший «объем памяти», поэтому она может легко обучиться лексикографически совершенному отображению (отображению без какой-либо способности к обобщению) между обучающими выборками и их целями, но если вы хотите, чтобы данные делали прогнозы, отображение бесполезно.
Важно иметь в виду, что модели глубокого обучения, как правило, хорошо подходят для обучающих данных, но настоящая проблема заключается в обобщении, а не в подборе.
С другой стороны, если сеть имеет ограниченные ресурсы памяти, она не может легко изучить отображение. Чтобы свести к минимуму потери, он должен изучить сжатое представление с большей предсказательной силой. В то же время, если модель слишком мала, будет сложно подогнать обучающие данные. Нам нужно найти баланс между «слишком большой мощностью» и «недостаточной мощностью».
К сожалению, не существует волшебной формулы для определения подходящего размера модели или архитектуры (определяемой количеством слоев или подходящим размером каждого слоя). Вам нужно будет попробовать ряд различных архитектур.
Чтобы найти правильный размер модели, лучше всего начать с относительно небольшого количества слоев и параметров, а затем начать увеличивать размер слоев или добавлять новые слои, пока не увидите уменьшение потерь при проверке. Давайте попробуем этот метод на Movie Rating Network.
Мы создадим простую базовую модель, используя только плотные слои, затем создадим уменьшенную и увеличенную версии и сравним эти версии.
Создайте базовую модель
baseline_model = keras.Sequential([
# `input_shape` is only required here so that `.summary` works.
keras.layers.Dense(16, activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
keras.layers.Dense(16, activation=tf.nn.relu),
keras.layers.Dense(1, activation=tf.nn.sigmoid)
])
baseline_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', 'binary_crossentropy'])
baseline_model.summary()
WARNING:tensorflow:From e:\program files\python37\lib\site-packages\tensorflow\python\ops\resource_variable_ops.py:435: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 16) 160016
_________________________________________________________________
dense_1 (Dense) (None, 16) 272
_________________________________________________________________
dense_2 (Dense) (None, 1) 17
=================================================================
Total params: 160,305
Trainable params: 160,305
Non-trainable params: 0
_________________________________________________________________
baseline_history = baseline_model.fit(train_data,
train_labels,
epochs=20,
batch_size=512,
validation_data=(test_data, test_labels),
verbose=2)
Train on 25000 samples, validate on 25000 samples
WARNING:tensorflow:From e:\program files\python37\lib\site-packages\tensorflow\python\ops\math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.cast instead.
Epoch 1/20
- 6s - loss: 0.5216 - acc: 0.7562 - binary_crossentropy: 0.5216 - val_loss: 0.3669 - val_acc: 0.8697 - val_binary_crossentropy: 0.3669
Epoch 2/20
- 3s - loss: 0.2672 - acc: 0.9091 - binary_crossentropy: 0.2672 - val_loss: 0.2868 - val_acc: 0.8883 - val_binary_crossentropy: 0.2868
Epoch 3/20
- 4s - loss: 0.1909 - acc: 0.9336 - binary_crossentropy: 0.1909 - val_loss: 0.2874 - val_acc: 0.8845 - val_binary_crossentropy: 0.2874
Epoch 4/20
- 4s - loss: 0.1545 - acc: 0.9468 - binary_crossentropy: 0.1545 - val_loss: 0.3123 - val_acc: 0.8774 - val_binary_crossentropy: 0.3123
Epoch 5/20
- 4s - loss: 0.1281 - acc: 0.9572 - binary_crossentropy: 0.1281 - val_loss: 0.3270 - val_acc: 0.8758 - val_binary_crossentropy: 0.3270
Epoch 6/20
- 4s - loss: 0.1076 - acc: 0.9658 - binary_crossentropy: 0.1076 - val_loss: 0.3542 - val_acc: 0.8732 - val_binary_crossentropy: 0.3542
Epoch 7/20
- 4s - loss: 0.0908 - acc: 0.9717 - binary_crossentropy: 0.0908 - val_loss: 0.3841 - val_acc: 0.8702 - val_binary_crossentropy: 0.3841
Epoch 8/20
- 4s - loss: 0.0766 - acc: 0.9785 - binary_crossentropy: 0.0766 - val_loss: 0.4187 - val_acc: 0.8662 - val_binary_crossentropy: 0.4187
Epoch 9/20
- 4s - loss: 0.0618 - acc: 0.9841 - binary_crossentropy: 0.0618 - val_loss: 0.4531 - val_acc: 0.8635 - val_binary_crossentropy: 0.4531
Epoch 10/20
- 4s - loss: 0.0511 - acc: 0.9879 - binary_crossentropy: 0.0511 - val_loss: 0.4954 - val_acc: 0.8609 - val_binary_crossentropy: 0.4954
Epoch 11/20
- 4s - loss: 0.0389 - acc: 0.9929 - binary_crossentropy: 0.0389 - val_loss: 0.5310 - val_acc: 0.8584 - val_binary_crossentropy: 0.5310
Epoch 12/20
- 4s - loss: 0.0299 - acc: 0.9956 - binary_crossentropy: 0.0299 - val_loss: 0.5702 - val_acc: 0.8574 - val_binary_crossentropy: 0.5702
Epoch 13/20
- 4s - loss: 0.0231 - acc: 0.9976 - binary_crossentropy: 0.0231 - val_loss: 0.6117 - val_acc: 0.8553 - val_binary_crossentropy: 0.6117
Epoch 14/20
- 4s - loss: 0.0175 - acc: 0.9987 - binary_crossentropy: 0.0175 - val_loss: 0.6467 - val_acc: 0.8542 - val_binary_crossentropy: 0.6467
Epoch 15/20
- 4s - loss: 0.0139 - acc: 0.9991 - binary_crossentropy: 0.0139 - val_loss: 0.6658 - val_acc: 0.8544 - val_binary_crossentropy: 0.6658
Epoch 16/20
- 4s - loss: 0.0111 - acc: 0.9995 - binary_crossentropy: 0.0111 - val_loss: 0.7014 - val_acc: 0.8538 - val_binary_crossentropy: 0.7014
Epoch 17/20
- 4s - loss: 0.0091 - acc: 0.9995 - binary_crossentropy: 0.0091 - val_loss: 0.7202 - val_acc: 0.8535 - val_binary_crossentropy: 0.7202
Epoch 18/20
- 4s - loss: 0.0074 - acc: 0.9996 - binary_crossentropy: 0.0074 - val_loss: 0.7477 - val_acc: 0.8531 - val_binary_crossentropy: 0.7477
Epoch 19/20
- 4s - loss: 0.0062 - acc: 0.9996 - binary_crossentropy: 0.0062 - val_loss: 0.7680 - val_acc: 0.8518 - val_binary_crossentropy: 0.7680
Epoch 20/20
- 4s - loss: 0.0053 - acc: 0.9996 - binary_crossentropy: 0.0053 - val_loss: 0.7896 - val_acc: 0.8513 - val_binary_crossentropy: 0.7896
Создать модель меньшего размера
Мы создаем модель с меньшим количеством скрытых единиц и сравниваем ее с только что созданной базовой моделью:
smaller_model = keras.Sequential([
keras.layers.Dense(4, activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
keras.layers.Dense(4, activation=tf.nn.relu),
keras.layers.Dense(1, activation=tf.nn.sigmoid)
])
smaller_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', 'binary_crossentropy'])
smaller_model.summary()
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_3 (Dense) (None, 4) 40004
_________________________________________________________________
dense_4 (Dense) (None, 4) 20
_________________________________________________________________
dense_5 (Dense) (None, 1) 5
=================================================================
Total params: 40,029
Trainable params: 40,029
Non-trainable params: 0
_________________________________________________________________
Обучите модель с теми же данными:
smaller_history = smaller_model.fit(train_data,
train_labels,
epochs=20,
batch_size=512,
validation_data=(test_data, test_labels),
verbose=2)
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
- 4s - loss: 0.6087 - acc: 0.6926 - binary_crossentropy: 0.6087 - val_loss: 0.5521 - val_acc: 0.7424 - val_binary_crossentropy: 0.5521
Epoch 2/20
- 3s - loss: 0.4927 - acc: 0.8387 - binary_crossentropy: 0.4927 - val_loss: 0.4727 - val_acc: 0.8355 - val_binary_crossentropy: 0.4727
Epoch 3/20
- 3s - loss: 0.3925 - acc: 0.9019 - binary_crossentropy: 0.3925 - val_loss: 0.3872 - val_acc: 0.8710 - val_binary_crossentropy: 0.3872
Epoch 4/20
- 3s - loss: 0.2983 - acc: 0.9252 - binary_crossentropy: 0.2983 - val_loss: 0.3294 - val_acc: 0.8816 - val_binary_crossentropy: 0.3294
Epoch 5/20
- 3s - loss: 0.2389 - acc: 0.9338 - binary_crossentropy: 0.2389 - val_loss: 0.3037 - val_acc: 0.8839 - val_binary_crossentropy: 0.3037
Epoch 6/20
- 3s - loss: 0.2031 - acc: 0.9402 - binary_crossentropy: 0.2031 - val_loss: 0.2909 - val_acc: 0.8873 - val_binary_crossentropy: 0.2909
Epoch 7/20
- 3s - loss: 0.1773 - acc: 0.9476 - binary_crossentropy: 0.1773 - val_loss: 0.2887 - val_acc: 0.8859 - val_binary_crossentropy: 0.2887
Epoch 8/20
- 3s - loss: 0.1583 - acc: 0.9533 - binary_crossentropy: 0.1583 - val_loss: 0.2916 - val_acc: 0.8838 - val_binary_crossentropy: 0.2916
Epoch 9/20
- 3s - loss: 0.1430 - acc: 0.9593 - binary_crossentropy: 0.1430 - val_loss: 0.3027 - val_acc: 0.8788 - val_binary_crossentropy: 0.3027
Epoch 10/20
- 3s - loss: 0.1305 - acc: 0.9648 - binary_crossentropy: 0.1305 - val_loss: 0.3060 - val_acc: 0.8795 - val_binary_crossentropy: 0.3060
Epoch 11/20
- 3s - loss: 0.1193 - acc: 0.9682 - binary_crossentropy: 0.1193 - val_loss: 0.3150 - val_acc: 0.8773 - val_binary_crossentropy: 0.3150
Epoch 12/20
- 3s - loss: 0.1099 - acc: 0.9717 - binary_crossentropy: 0.1099 - val_loss: 0.3239 - val_acc: 0.8758 - val_binary_crossentropy: 0.3239
Epoch 13/20
- 3s - loss: 0.1012 - acc: 0.9747 - binary_crossentropy: 0.1012 - val_loss: 0.3355 - val_acc: 0.8727 - val_binary_crossentropy: 0.3355
Epoch 14/20
- 3s - loss: 0.0936 - acc: 0.9772 - binary_crossentropy: 0.0936 - val_loss: 0.3476 - val_acc: 0.8708 - val_binary_crossentropy: 0.3476
Epoch 15/20
- 3s - loss: 0.0871 - acc: 0.9796 - binary_crossentropy: 0.0871 - val_loss: 0.3579 - val_acc: 0.8702 - val_binary_crossentropy: 0.3579
Epoch 16/20
- 3s - loss: 0.0810 - acc: 0.9821 - binary_crossentropy: 0.0810 - val_loss: 0.3678 - val_acc: 0.8689 - val_binary_crossentropy: 0.3678
Epoch 17/20
- 3s - loss: 0.0748 - acc: 0.9849 - binary_crossentropy: 0.0748 - val_loss: 0.3796 - val_acc: 0.8680 - val_binary_crossentropy: 0.3796
Epoch 18/20
- 3s - loss: 0.0697 - acc: 0.9865 - binary_crossentropy: 0.0697 - val_loss: 0.3962 - val_acc: 0.8671 - val_binary_crossentropy: 0.3962
Epoch 19/20
- 3s - loss: 0.0651 - acc: 0.9881 - binary_crossentropy: 0.0651 - val_loss: 0.4038 - val_acc: 0.8668 - val_binary_crossentropy: 0.4038
Epoch 20/20
- 3s - loss: 0.0608 - acc: 0.9897 - binary_crossentropy: 0.0608 - val_loss: 0.4175 - val_acc: 0.8659 - val_binary_crossentropy: 0.4175
Создать большую модель
В качестве упражнения вы можете создать более крупную модель и посмотреть, как быстро она начнет подгонять. Затем мы добавляем к этому тесту гораздо большую сеть, намного превышающую то, что необходимо для решения проблемы:
bigger_model = keras.models.Sequential([
keras.layers.Dense(512, activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
keras.layers.Dense(512, activation=tf.nn.relu),
keras.layers.Dense(1, activation=tf.nn.sigmoid)
])
bigger_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy','binary_crossentropy'])
bigger_model.summary()
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_6 (Dense) (None, 512) 5120512
_________________________________________________________________
dense_7 (Dense) (None, 512) 262656
_________________________________________________________________
dense_8 (Dense) (None, 1) 513
=================================================================
Total params: 5,383,681
Trainable params: 5,383,681
Non-trainable params: 0
_________________________________________________________________
Снова обучите модель с теми же данными:
bigger_history = bigger_model.fit(train_data, train_labels,
epochs=20,
batch_size=512,
validation_data=(test_data, test_labels),
verbose=2)
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
- 9s - loss: 0.3443 - acc: 0.8530 - binary_crossentropy: 0.3443 - val_loss: 0.3148 - val_acc: 0.8696 - val_binary_crossentropy: 0.3148
Epoch 2/20
- 9s - loss: 0.1417 - acc: 0.9484 - binary_crossentropy: 0.1417 - val_loss: 0.3314 - val_acc: 0.8744 - val_binary_crossentropy: 0.3314
Epoch 3/20
- 9s - loss: 0.0441 - acc: 0.9874 - binary_crossentropy: 0.0441 - val_loss: 0.4434 - val_acc: 0.8685 - val_binary_crossentropy: 0.4434
Epoch 4/20
- 9s - loss: 0.0069 - acc: 0.9989 - binary_crossentropy: 0.0069 - val_loss: 0.5873 - val_acc: 0.8682 - val_binary_crossentropy: 0.5873
Epoch 5/20
- 9s - loss: 9.7864e-04 - acc: 1.0000 - binary_crossentropy: 9.7864e-04 - val_loss: 0.7093 - val_acc: 0.8656 - val_binary_crossentropy: 0.7093
Epoch 6/20
- 9s - loss: 8.7528e-04 - acc: 1.0000 - binary_crossentropy: 8.7528e-04 - val_loss: 0.7232 - val_acc: 0.8691 - val_binary_crossentropy: 0.7232
Epoch 7/20
- 9s - loss: 1.4544e-04 - acc: 1.0000 - binary_crossentropy: 1.4544e-04 - val_loss: 0.7518 - val_acc: 0.8686 - val_binary_crossentropy: 0.7518
Epoch 8/20
- 9s - loss: 9.5470e-05 - acc: 1.0000 - binary_crossentropy: 9.5470e-05 - val_loss: 0.7742 - val_acc: 0.8687 - val_binary_crossentropy: 0.7742
Epoch 9/20
- 9s - loss: 7.0958e-05 - acc: 1.0000 - binary_crossentropy: 7.0958e-05 - val_loss: 0.7910 - val_acc: 0.8686 - val_binary_crossentropy: 0.7910
Epoch 10/20
- 9s - loss: 5.5851e-05 - acc: 1.0000 - binary_crossentropy: 5.5851e-05 - val_loss: 0.8047 - val_acc: 0.8684 - val_binary_crossentropy: 0.8047
Epoch 11/20
- 9s - loss: 4.5268e-05 - acc: 1.0000 - binary_crossentropy: 4.5268e-05 - val_loss: 0.8176 - val_acc: 0.8686 - val_binary_crossentropy: 0.8176
Epoch 12/20
- 9s - loss: 3.7788e-05 - acc: 1.0000 - binary_crossentropy: 3.7788e-05 - val_loss: 0.8276 - val_acc: 0.8685 - val_binary_crossentropy: 0.8276
Epoch 13/20
- 9s - loss: 3.1885e-05 - acc: 1.0000 - binary_crossentropy: 3.1885e-05 - val_loss: 0.8364 - val_acc: 0.8684 - val_binary_crossentropy: 0.8364
Epoch 14/20
- 9s - loss: 2.7393e-05 - acc: 1.0000 - binary_crossentropy: 2.7393e-05 - val_loss: 0.8452 - val_acc: 0.8685 - val_binary_crossentropy: 0.8452
Epoch 15/20
- 9s - loss: 2.3753e-05 - acc: 1.0000 - binary_crossentropy: 2.3753e-05 - val_loss: 0.8530 - val_acc: 0.8686 - val_binary_crossentropy: 0.8530
Epoch 16/20
- 9s - loss: 2.0851e-05 - acc: 1.0000 - binary_crossentropy: 2.0851e-05 - val_loss: 0.8606 - val_acc: 0.8686 - val_binary_crossentropy: 0.8606
Epoch 17/20
- 9s - loss: 1.8398e-05 - acc: 1.0000 - binary_crossentropy: 1.8398e-05 - val_loss: 0.8673 - val_acc: 0.8688 - val_binary_crossentropy: 0.8673
Epoch 18/20
- 9s - loss: 1.6352e-05 - acc: 1.0000 - binary_crossentropy: 1.6352e-05 - val_loss: 0.8737 - val_acc: 0.8688 - val_binary_crossentropy: 0.8737
Epoch 19/20
- 9s - loss: 1.4625e-05 - acc: 1.0000 - binary_crossentropy: 1.4625e-05 - val_loss: 0.8793 - val_acc: 0.8687 - val_binary_crossentropy: 0.8793
Epoch 20/20
- 9s - loss: 1.3164e-05 - acc: 1.0000 - binary_crossentropy: 1.3164e-05 - val_loss: 0.8852 - val_acc: 0.8686 - val_binary_crossentropy: 0.8852
Постройте график потери обучения и потери проверки
Сплошная линия — это потери при обучении, а пунктирная линия — потери при проверке (помните: чем меньше потери при проверке, тем лучше модель). В этом примере меньшая сеть начинает переоснащаться позже, чем базовая модель (первая после 6 эпох, а вторая после 4 эпох), и ее эффект снижается медленнее после того, как она начинает переобучать намного больше.
def plot_history(histories, key='binary_crossentropy'):
plt.figure(figsize=(16,10))
for name, history in histories:
val = plt.plot(history.epoch, history.history['val_'+key],
'--', label=name.title()+' Val')
plt.plot(history.epoch, history.history[key], color=val[0].get_color(),
label=name.title()+' Train')
plt.xlabel('Epochs')
plt.ylabel(key.replace('_',' ').title())
plt.legend()
plt.xlim([0,max(history.epoch)])
plot_history([('baseline', baseline_history),
('smaller', smaller_history),
('bigger', bigger_history)])
Обратите внимание, что более крупная сеть начинает переобучаться почти сразу после всего 1 цикла, а после этого становится намного хуже. Чем больше пропускная способность сети, тем быстрее могут быть смоделированы обучающие данные (что приводит к меньшим потерям при обучении), но тем легче их переобучить (что приводит к большой разнице между потерями при обучении и потерями при проверке).
Стратегия
Добавить регуляризацию веса
Возможно, вы знакомы с бритвой Оккама: если есть два объяснения одного и того же явления, то наиболее верным объяснением будет «самое простое», то есть то, в котором делается наименьшее количество предположений. Это также относится к моделям, изученным нейронными сетями: учитывая некоторые обучающие данные и архитектуру сети, существует несколько наборов значений веса (несколько моделей), которые могут объяснить данные, а простые модели менее склонны к переоснащению, чем сложные модели.
«Простая модель» в данном контексте — это модель с более низкой энтропией распределения значений параметров (или модель с меньшим количеством параметров, как мы видели в разделе выше). Поэтому, чтобы смягчить переоснащение, общий подход состоит в том, чтобы ограничить сложность сети, заставив ее веса принимать только небольшие значения, делая распределение значений весов более «регулярным». Это называется «регуляризацией веса» и осуществляется путем добавления стоимости, связанной с большими весами, к функции потерь сети. Существует два вида этой стоимости:
Регуляризация L1, где добавленная стоимость пропорциональна абсолютной величине весовых коэффициентов (так называемая «норма L1» весов).
L2-регуляризация, где добавленная стоимость пропорциональна квадрату значения весового коэффициента (так называемая «L2-норма» веса). Регуляризация L2 также известна как уменьшение веса в области нейронных сетей. Не запутайтесь в разных названиях: с математической точки зрения уменьшение веса точно такое же, как регуляризация L2.
В tf.keras регуляризация веса добавляется следующим образом: экземпляр термина регуляризации веса передается слою в качестве аргумента ключевого слова. Теперь давайте добавим регуляризацию веса L2.
l2_model = keras.models.Sequential([
keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
activation=tf.nn.relu),
keras.layers.Dense(1, activation=tf.nn.sigmoid)
])
l2_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', 'binary_crossentropy'])
l2_model_history = l2_model.fit(train_data, train_labels,
epochs=20,
batch_size=512,
validation_data=(test_data, test_labels),
verbose=2)
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
- 4s - loss: 0.5023 - acc: 0.8133 - binary_crossentropy: 0.4605 - val_loss: 0.3661 - val_acc: 0.8791 - val_binary_crossentropy: 0.3226
Epoch 2/20
- 4s - loss: 0.2924 - acc: 0.9104 - binary_crossentropy: 0.2456 - val_loss: 0.3344 - val_acc: 0.8860 - val_binary_crossentropy: 0.2851
Epoch 3/20
- 4s - loss: 0.2439 - acc: 0.9316 - binary_crossentropy: 0.1925 - val_loss: 0.3387 - val_acc: 0.8843 - val_binary_crossentropy: 0.2858
Epoch 4/20
- 4s - loss: 0.2226 - acc: 0.9418 - binary_crossentropy: 0.1682 - val_loss: 0.3571 - val_acc: 0.8789 - val_binary_crossentropy: 0.3014
Epoch 5/20
- 4s - loss: 0.2073 - acc: 0.9495 - binary_crossentropy: 0.1506 - val_loss: 0.3691 - val_acc: 0.8771 - val_binary_crossentropy: 0.3116
Epoch 6/20
- 4s - loss: 0.1957 - acc: 0.9548 - binary_crossentropy: 0.1373 - val_loss: 0.3820 - val_acc: 0.8749 - val_binary_crossentropy: 0.3231
Epoch 7/20
- 4s - loss: 0.1889 - acc: 0.9574 - binary_crossentropy: 0.1291 - val_loss: 0.4039 - val_acc: 0.8707 - val_binary_crossentropy: 0.3435
Epoch 8/20
- 4s - loss: 0.1829 - acc: 0.9592 - binary_crossentropy: 0.1217 - val_loss: 0.4151 - val_acc: 0.8696 - val_binary_crossentropy: 0.3534
Epoch 9/20
- 3s - loss: 0.1775 - acc: 0.9600 - binary_crossentropy: 0.1151 - val_loss: 0.4341 - val_acc: 0.8649 - val_binary_crossentropy: 0.3711
Epoch 10/20
- 4s - loss: 0.1731 - acc: 0.9632 - binary_crossentropy: 0.1097 - val_loss: 0.4419 - val_acc: 0.8667 - val_binary_crossentropy: 0.3780
Epoch 11/20
- 4s - loss: 0.1685 - acc: 0.9654 - binary_crossentropy: 0.1041 - val_loss: 0.4562 - val_acc: 0.8639 - val_binary_crossentropy: 0.3913
Epoch 12/20
- 4s - loss: 0.1655 - acc: 0.9653 - binary_crossentropy: 0.1001 - val_loss: 0.4730 - val_acc: 0.8622 - val_binary_crossentropy: 0.4073
Epoch 13/20
- 4s - loss: 0.1610 - acc: 0.9692 - binary_crossentropy: 0.0949 - val_loss: 0.4828 - val_acc: 0.8611 - val_binary_crossentropy: 0.4165
Epoch 14/20
- 4s - loss: 0.1590 - acc: 0.9686 - binary_crossentropy: 0.0922 - val_loss: 0.4988 - val_acc: 0.8588 - val_binary_crossentropy: 0.4318
Epoch 15/20
- 4s - loss: 0.1588 - acc: 0.9690 - binary_crossentropy: 0.0915 - val_loss: 0.5141 - val_acc: 0.8592 - val_binary_crossentropy: 0.4462
Epoch 16/20
- 4s - loss: 0.1571 - acc: 0.9701 - binary_crossentropy: 0.0884 - val_loss: 0.5248 - val_acc: 0.8558 - val_binary_crossentropy: 0.4557
Epoch 17/20
- 4s - loss: 0.1541 - acc: 0.9708 - binary_crossentropy: 0.0852 - val_loss: 0.5294 - val_acc: 0.8572 - val_binary_crossentropy: 0.4604
Epoch 18/20
- 4s - loss: 0.1520 - acc: 0.9723 - binary_crossentropy: 0.0825 - val_loss: 0.5622 - val_acc: 0.8521 - val_binary_crossentropy: 0.4924
Epoch 19/20
- 4s - loss: 0.1512 - acc: 0.9713 - binary_crossentropy: 0.0812 - val_loss: 0.5532 - val_acc: 0.8546 - val_binary_crossentropy: 0.4828
Epoch 20/20
- 4s - loss: 0.1441 - acc: 0.9766 - binary_crossentropy: 0.0736 - val_loss: 0.5628 - val_acc: 0.8539 - val_binary_crossentropy: 0.4925
l2(0,001) означает, что каждый коэффициент в матрице весов слоя добавляет 0,001 * значение_весового_коэффициента**2 к общим потерям сети. Обратите внимание, что, поскольку этот штраф добавляется только во время обучения, потери этой сети во время обучения будут намного выше, чем во время тестирования.
Вот эффект штрафа за регуляризацию L2:
plot_history([('baseline', baseline_history),
('l2', l2_model_history)])
Можно видеть, что регуляризованная модель L2 гораздо более устойчива к переоснащению, чем базовая модель, хотя две модели имеют одинаковое количество параметров.
Добавить слой капли
Dropout, разработанный Хинтоном и его студентами из Университета Торонто, является одним из наиболее эффективных и часто используемых методов регуляризации нейронных сетей. Отбрасывание (применение к слою) относится к случайному «отбрасыванию» (т. е. установленному на 0) нескольких выходных функций этого слоя во время обучения. Предположим, что заданный слой обычно возвращает вектор [0,2, 0,5, 1,3, 0,8, 1,1] для данной входной выборки во время обучения; после применения отсева этот вектор будет случайным образом распределен с несколькими 0 элементами, например [0, 0,5, 1,3 , 0, 1.1]. «Показатель отсева» относится к доле функций, которые становятся 0, и обычно устанавливается между 0,2 и 0,5. Во время тестирования сеть не отбрасывает никаких блоков, но уменьшает выходное значение слоя на коэффициент, равный частоте отсева, чтобы сбалансировать тот факт, что количество активных блоков во время тестирования больше, чем количество действующих подразделений во время обучения.
В tf.keras можно ввести отсев в сеть через слои отсева, чтобы его можно было заранее применить к выходу слоя.
Давайте добавим два слоя отсева в сеть IMDB и посмотрим, насколько хорошо они уменьшают переобучение:
dpt_model = keras.models.Sequential([
keras.layers.Dense(16, activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
keras.layers.Dropout(0.5),
keras.layers.Dense(16, activation=tf.nn.relu),
keras.layers.Dropout(0.5),
keras.layers.Dense(1, activation=tf.nn.sigmoid)
])
dpt_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy','binary_crossentropy'])
dpt_model_history = dpt_model.fit(train_data, train_labels,
epochs=20,
batch_size=512,
validation_data=(test_data, test_labels),
verbose=2)
WARNING:tensorflow:From e:\program files\python37\lib\site-packages\tensorflow\python\keras\layers\core.py:143: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.
Instructions for updating:
Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
- 4s - loss: 0.6432 - acc: 0.6127 - binary_crossentropy: 0.6432 - val_loss: 0.5211 - val_acc: 0.8422 - val_binary_crossentropy: 0.5211
Epoch 2/20
- 4s - loss: 0.4937 - acc: 0.7782 - binary_crossentropy: 0.4937 - val_loss: 0.3720 - val_acc: 0.8755 - val_binary_crossentropy: 0.3720
Epoch 3/20
- 4s - loss: 0.3972 - acc: 0.8453 - binary_crossentropy: 0.3972 - val_loss: 0.3092 - val_acc: 0.8852 - val_binary_crossentropy: 0.3092
Epoch 4/20
- 4s - loss: 0.3319 - acc: 0.8764 - binary_crossentropy: 0.3319 - val_loss: 0.2802 - val_acc: 0.8889 - val_binary_crossentropy: 0.2802
Epoch 5/20
- 4s - loss: 0.2871 - acc: 0.8955 - binary_crossentropy: 0.2871 - val_loss: 0.2767 - val_acc: 0.8889 - val_binary_crossentropy: 0.2767
Epoch 6/20
- 4s - loss: 0.2460 - acc: 0.9126 - binary_crossentropy: 0.2460 - val_loss: 0.2813 - val_acc: 0.8855 - val_binary_crossentropy: 0.2813
Epoch 7/20
- 4s - loss: 0.2198 - acc: 0.9270 - binary_crossentropy: 0.2198 - val_loss: 0.2924 - val_acc: 0.8866 - val_binary_crossentropy: 0.2924
Epoch 8/20
- 4s - loss: 0.1932 - acc: 0.9340 - binary_crossentropy: 0.1932 - val_loss: 0.3089 - val_acc: 0.8845 - val_binary_crossentropy: 0.3089
Epoch 9/20
- 3s - loss: 0.1771 - acc: 0.9396 - binary_crossentropy: 0.1771 - val_loss: 0.3187 - val_acc: 0.8839 - val_binary_crossentropy: 0.3187
Epoch 10/20
- 4s - loss: 0.1570 - acc: 0.9470 - binary_crossentropy: 0.1570 - val_loss: 0.3355 - val_acc: 0.8828 - val_binary_crossentropy: 0.3355
Epoch 11/20
- 4s - loss: 0.1457 - acc: 0.9509 - binary_crossentropy: 0.1457 - val_loss: 0.3532 - val_acc: 0.8817 - val_binary_crossentropy: 0.3532
Epoch 12/20
- 3s - loss: 0.1365 - acc: 0.9525 - binary_crossentropy: 0.1365 - val_loss: 0.3798 - val_acc: 0.8804 - val_binary_crossentropy: 0.3798
Epoch 13/20
- 4s - loss: 0.1249 - acc: 0.9565 - binary_crossentropy: 0.1249 - val_loss: 0.3950 - val_acc: 0.8792 - val_binary_crossentropy: 0.3950
Epoch 14/20
- 4s - loss: 0.1106 - acc: 0.9617 - binary_crossentropy: 0.1106 - val_loss: 0.4083 - val_acc: 0.8783 - val_binary_crossentropy: 0.4083
Epoch 15/20
- 4s - loss: 0.1090 - acc: 0.9612 - binary_crossentropy: 0.1090 - val_loss: 0.4413 - val_acc: 0.8788 - val_binary_crossentropy: 0.4413
Epoch 16/20
- 3s - loss: 0.0996 - acc: 0.9652 - binary_crossentropy: 0.0996 - val_loss: 0.4641 - val_acc: 0.8777 - val_binary_crossentropy: 0.4641
Epoch 17/20
- 4s - loss: 0.0969 - acc: 0.9648 - binary_crossentropy: 0.0969 - val_loss: 0.4753 - val_acc: 0.8779 - val_binary_crossentropy: 0.4753
Epoch 18/20
- 4s - loss: 0.0940 - acc: 0.9666 - binary_crossentropy: 0.0940 - val_loss: 0.4847 - val_acc: 0.8747 - val_binary_crossentropy: 0.4847
Epoch 19/20
- 4s - loss: 0.0873 - acc: 0.9686 - binary_crossentropy: 0.0873 - val_loss: 0.5048 - val_acc: 0.8759 - val_binary_crossentropy: 0.5048
Epoch 20/20
- 3s - loss: 0.0807 - acc: 0.9699 - binary_crossentropy: 0.0807 - val_loss: 0.5233 - val_acc: 0.8755 - val_binary_crossentropy: 0.5233
plot_history([('baseline', baseline_history),
('dropout', dpt_model_history)])
Добавление выпадающих слоев значительно улучшает базовую модель.
Вот краткое изложение наиболее распространенных способов предотвращения переобучения нейронных сетей:
- Получите больше обучающих данных.
- Уменьшите пропускную способность сети.
- Добавьте регуляризацию веса.
- Добавьте слой капли.
В этом руководстве не рассматриваются еще два важных метода: увеличение данных и нормализация партии.