我有一个 CNN 架构来输出对象周围的框的坐标:
但是,如果我在 tf 中实现它,即使在一个 epoch 之后,损失也会变成 nan。我尝试了梯度裁剪和批量归一化,但都不起作用。我怀疑我的loss有问题,下面是相应的代码:
...
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: 如果我删除 axis=-1 参数,我也会得到 nan's,但是我将它包括在内,因为 keras 均值是使用相同的参数计算的。
注2: 即使我只在输入上训练一个密集层,keras 模型也会慢慢收敛,而 tensorflow 模型则不会。
请您参考如下方法:
捕获可能是因为行 error = output-y。因为 output 是每个类别的 Logits 或预测概率。
如果我们打印它,它会如下图所示:
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))
