tf.keras потеря становится NaN - PullRequest
4 голосов
/ 25 марта 2019

Я программирую нейронную сеть в tf.keras, с 3 слоями.Мой набор данных - это набор данных MNIST.Я уменьшил количество примеров в наборе данных, поэтому время выполнения меньше.Это мой код:

import tensorflow as tf
from tensorflow.keras import layers
import numpy as np
import pandas as pd

!git clone https://github.com/DanorRon/data
%cd data
!ls

batch_size = 32
epochs = 10
alpha = 0.0001
lambda_ = 0
h1 = 50

train = pd.read_csv('/content/first-repository/mnist_train.csv.zip')
test = pd.read_csv('/content/first-repository/mnist_test.csv.zip')

train = train.loc['1':'5000', :]
test = test.loc['1':'2000', :]

train = train.sample(frac=1).reset_index(drop=True)
test = test.sample(frac=1).reset_index(drop=True)

x_train = train.loc[:, '1x1':'28x28']
y_train = train.loc[:, 'label']

x_test = test.loc[:, '1x1':'28x28']
y_test = test.loc[:, 'label']

x_train = x_train.values
y_train = y_train.values

x_test = x_test.values
y_test = y_test.values

nb_classes = 10
targets = y_train.reshape(-1)
y_train_onehot = np.eye(nb_classes)[targets]

nb_classes = 10
targets = y_test.reshape(-1)
y_test_onehot = np.eye(nb_classes)[targets]

model = tf.keras.Sequential()
model.add(layers.Dense(784, input_shape=(784,)))
model.add(layers.Dense(h1, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(lambda_)))
model.add(layers.Dense(10, activation='sigmoid', kernel_regularizer=tf.keras.regularizers.l2(lambda_)))

model.compile(optimizer=tf.train.GradientDescentOptimizer(alpha), 
             loss = 'categorical_crossentropy',
             metrics = ['accuracy'])

model.fit(x_train, y_train_onehot, epochs=epochs, batch_size=batch_size)

Всякий раз, когда я запускаю его, происходит одна из 3 вещей:

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

  2. Потери и точность остаются одинаковыми для каждой эпохи.Обычно потеря составляет 2,3025, а точность равна 0,0986.

  3. Потеря начинается с NaN (и остается такой же), в то время как точность остается низкой.

В большинстве случаев модель делает одну из этих вещей, но иногда она делает что-то случайное.Похоже, что тип ошибочного поведения является совершенно случайным.Я понятия не имею, в чем проблема.Как мне решить эту проблему?

Редактировать: Иногда потери уменьшаются, но точность остается неизменной.Кроме того, иногда потери уменьшаются и точность увеличивается, затем через некоторое время точность уменьшается, тогда как потери все еще уменьшаются.Или потеря уменьшается, а точность увеличивается, затем она переключается, и потеря быстро возрастает, в то время как точность падает, в конечном итоге заканчивая потерей: 2.3025 в соотв.: 0.0986.

Редактировать 2: Это пример чего-то, чтоиногда случается:

Epoch 1/100
49999/49999 [==============================] - 5s 92us/sample - loss: 1.8548 - acc: 0.2390

Epoch 2/100
49999/49999 [==============================] - 5s 104us/sample - loss: 0.6894 - acc: 0.8050

Epoch 3/100
49999/49999 [==============================] - 4s 90us/sample - loss: 0.4317 - acc: 0.8821

Epoch 4/100
49999/49999 [==============================] - 5s 104us/sample - loss: 2.2178 - acc: 0.1345

Epoch 5/100
49999/49999 [==============================] - 5s 90us/sample - loss: 2.3025 - acc: 0.0986

Epoch 6/100
49999/49999 [==============================] - 4s 90us/sample - loss: 2.3025 - acc: 0.0986

Epoch 7/100
49999/49999 [==============================] - 4s 89us/sample - loss: 2.3025 - acc: 0.0986

Редактировать 3: Я изменил потерю на среднеквадратичную ошибку, и теперь сеть работает хорошо.Есть ли способ сохранить его в перекрестной энтропии, не приближаясь к локальному минимуму?

Ответы [ 2 ]

1 голос
/ 01 апреля 2019

Я изменил потерю на среднеквадратичную ошибку, и теперь сеть работает хорошо

MSE является , а не подходящей функцией потерь для таких задач классификации; Вы, конечно, должны придерживаться loss = 'categorical_crossentropy'.

Скорее всего, проблема в том, что ваши данные MNIST не нормализованы; вы должны нормализовать ваши окончательные переменные как

x_train = x_train.values/255
x_test = x_test.values/255

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

Другой совет: установите activation='relu' для первого плотного слоя и избавьтесь от аргументов регуляризатора и инициализатора из всех слоев (по умолчанию glorot_uniform на самом деле лучший инициализатор, тогда как регуляризация здесь может на самом деле быть вредной для производительность).

В качестве общего совета попробуйте , а не , чтобы заново изобрести колесо - начните с примера Keras , используя встроенные данные MNIST ...

1 голос
/ 25 марта 2019

Разочарование, которое вы испытываете по поводу случайного вывода вашего кода, понятно и правильно идентифицировано.Каждый раз, когда модель начинает тренироваться, она случайным образом инициализирует веса.В зависимости от этой инициализации вы видите один из трех ваших выходных сценариев.

Скорее всего, проблема связана с исчезающими градиентами.Это явление, которое возникает, когда обратное распространение приводит к умножению очень малых весов на небольшое число для создания почти бесконечно малого значения.Решение состоит в том, чтобы добавить небольшой джиттер (1e-10) к каждому из ваших градиентов (из функции стоимости), чтобы они никогда не достигали нуля.

Существуют тонны более подробных блогов об исчезновении градиентов в сети и для строки проверки примера реализации 217 этой TensorFlow Network

...