Взрывающийся градиент тензорного потока

У меня есть архитектура CNN для вывода координат прямоугольника вокруг объекта:

Архитектура CNN

Однако, если я реализую его в tf, потеря станет nan даже после одной эпохи. Я пробовал обрезку градиента и пакетную нормализацию, но ничего не вышло. Подозреваю, что с моей потерей что-то не так, вот соответствующий код:

...
output = tf.layers.dense(dense, 4, name="output")

# Loss
error = output-y
error_sq = tf.square(error)
loss = tf.reduce_mean(error_sq, axis=-1)

# Training operation
optimizer = tf.train.RMSPropOptimizer(learning_rate=0.001, momentum=0.9, decay=0.0, epsilon=1e-08)
training_op = optimizer.minimize(loss)

Я реализовал ту же архитектуру с keras, и она отлично работает:

...
model.add(Dense(4))

# Optimizer
optimizer = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0)

# Compile
model.compile(optimizer = optimizer , loss = "mean_squared_error", metrics=["mean_squared_error"])

Я не вижу, чем они отличаются ..

Примечание 1: я также получаю nan, если отбрасываю аргумент axis = -1, однако я включил его, поскольку среднее значение keras вычисляется с тем же аргументом.

Примечание 2: даже если я тренирую только плотный слой на входе, модель keras медленно сходится, а модель тензорного потока - нет.


person lmz    schedule 19.12.2018    source источник
comment
В качестве побочного примечания вы можете использовать tf.losses.mean_squared_error, чтобы получить среднеквадратичную ошибку в тензорном потоке.   -  person BiBi    schedule 19.12.2018
comment
Что произойдет, если вы определите сеть с помощью Keras и оптимизируете ее с помощью собственного кода тензорного потока, как в вашем первом фрагменте? Какой формы error?   -  person BiBi    schedule 19.12.2018
comment
@BiBi Если я использую простой tf для оптимизации модели keras, у меня такая же проблема. Форма ошибки: (25,4), где 25 - размер моего пакета, а другое измерение имеет координаты поля локализации.   -  person lmz    schedule 19.12.2018
comment
Если размер вашего пакета является 0-й осью, я думаю, вам следует уменьшить по этой оси с помощью loss = tf.reduce_mean(error_sq, axis=0) вместо axis=-1, но это должно быть проблемой.   -  person BiBi    schedule 19.12.2018
comment
Да, изменение оси просто меняет форму получаемого нанометра;) Я выбрал axis = -1, потому что, насколько я понимаю, его использует keras (github.com/keras-team/keras/blob/master/keras/losses.py)   -  person lmz    schedule 19.12.2018


Ответы (1)


Уловка может быть из-за лески error = output-y. Потому что output - это логиты или вероятность предсказания каждого класса.

Если его распечатать, то он будет таким, как показано ниже:

output/logits =  [[-4.55290842e+00  9.54713643e-01  2.04970908e+00 ...  1.06385863e+00
  -1.76558220e+00  5.84793314e-02]
 [ 1.42444344e+01 -3.09316659e+00  4.31246233e+00 ... -1.64039159e+00
  -4.75767326e+00  2.69032687e-01]
 [-3.66746974e+00 -1.05631983e+00  1.63249350e+00 ...  2.34054995e+00
  -2.86306214e+00 -1.29766455e-02]
 ...
 [ 1.92035064e-01  2.18118310e+00  1.05751991e+01 ... -3.32132912e+00
   2.23277748e-01 -4.14045334e+00]
 [-3.95318937e+00  7.54375601e+00  5.60657620e-01 ...  3.35071832e-02
   2.31437039e+00 -3.36187315e+00]
 [-4.37104368e+00  4.23799706e+00  1.20920219e+01 ... -1.18962801e+00
   2.23617482e+00 -3.06528354e+00]]

Следовательно, шаги error = output-y, error_sq = tf.square(error) и loss = tf.reduce_mean(error_sq, axis=-1) могут привести к NaN.

Код ниже должен решить вашу проблему:

l1 = tf.layers.dense(normed_train_data, 64, activation='relu')
l2 = tf.layers.dense(l1, 64, activation='relu')
l3 = tf.layers.dense(l2, 4, name="output")

mse = tf.losses.mean_squared_error(labels=y, logits=l3)

loss = tf.reduce_mean(mse, name="loss")

optimizer = tf.train.RMSPropOptimizer(learning_rate=0.001, momentum=0.9, decay=0.0, epsilon=1e-08)
training_op = optimizer.minimize(loss)

correct = tf.nn.in_top_k(logits, y, 1)
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
person Tensorflow Support    schedule 06.08.2019