TensorFlow直方图摘要报错:权重参数中存在NaN值求助
解决TensorFlow直方图摘要中出现NaN的问题
嘿,我看到你作为TensorFlow新手在训练MNIST模型时碰到了直方图摘要出现NaN的错误,这个问题我之前也踩过坑,咱们一起来解决它~
问题根源分析
你遇到的InvalidArgumentError: Nan in summary histogram for: weights,核心原因是训练过程中权重(W)的数值变成了NaN,导致直方图无法生成。具体来说有两个关键问题:
- 损失函数数值量级过大:你用了
tf.reduce_mean(tf.reduce_sum(tf.square(my_label-y)))计算损失——先把每个样本的10个类别误差平方累加,再取平均。这个计算会让损失值变得非常大,梯度更新时很容易触发数值溢出,最终让权重变成NaN。 - 分类任务误用回归损失:MNIST是10分类任务,平方损失更适合回归问题,分类任务用交叉熵损失才更合理,它的数值稳定性更好,也更贴合分类任务的目标。
具体修复步骤
1. 替换为适合分类任务的交叉熵损失
把原来的平方和损失换成TensorFlow专门为分类任务提供的交叉熵损失API,这样能有效控制损失的数值量级:
# 替换原来的mean_error计算代码 cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(logits=my_label, labels=y) mean_error = tf.reduce_mean(cross_entropy)
2. 修复训练循环中的变量名错误
你代码里的train_accuracy = sess.run(train_step, ...)是个小bug:train_step是优化器的更新操作,运行它不会返回准确率,只会执行梯度更新。应该分开执行更新和准确率计算:
# 先执行梯度更新 sess.run(train_step, feed_dict={x: batch[0], y: batch[1]}) # 每500次迭代时单独计算准确率 if i % 500 == 0: train_acc = sess.run(accuracy, feed_dict={x: batch[0], y: batch[1]}) print(f"第{i}次迭代,训练准确率: {train_acc}")
3. 可选:如果坚持用平方损失的调整方案
如果你不想换损失函数,那需要缩小损失的数值量级,同时调整学习率:
# 去掉reduce_sum,直接计算每个样本每个类别的平方误差均值 mean_error = tf.reduce_mean(tf.square(my_label - y)) # 适当调小学习率,比如从0.0003改成0.0001 train_step=tf.train.GradientDescentOptimizer(0.0001).minimize(mean_error)
修改后的完整代码
import tensorflow as tf logdir="/tmp/mnist_tutorial5/" mnist = tf.contrib.learn.datasets.mnist.read_data_sets(train_dir=logdir+"data",one_hot = True) tf.reset_default_graph() sess = tf.Session() writer = tf.summary.FileWriter(logdir) def model(input): w = tf.Variable(tf.truncated_normal([784,10], stddev=0.1), name="W") b = tf.Variable(tf.constant(0.1, shape=[10]), name="B") act = tf.matmul(input,w) + b tf.summary.histogram("weights",w) tf.summary.histogram("biases",b) tf.summary.histogram("activations",act) return act def train(): x = tf.placeholder(tf.float32, shape=[None, 784], name="input_img") y = tf.placeholder(tf.float32, shape=[None, 10], name="labels") my_label = model(x) print("linear_regression is completed") # 替换为交叉熵损失 cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(logits=my_label, labels=y) mean_error = tf.reduce_mean(cross_entropy) tf.summary.scalar("loss", mean_error) train_step=tf.train.GradientDescentOptimizer(0.0003).minimize(mean_error) correct_prediction = tf.equal(tf.argmax(my_label, 1), tf.argmax(y, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) tf.summary.scalar("accuracy", accuracy) sess.run(tf.global_variables_initializer()) summ = tf.summary.merge_all() for i in range(2000): batch = mnist.train.next_batch(100) # 单独执行梯度更新 sess.run(train_step, feed_dict={x: batch[0], y: batch[1]}) print(f"{i} th iteration") if i%500==0: print("over 2") # 同时计算摘要和准确率 summarys, train_acc = sess.run([summ, accuracy], feed_dict={x: batch[0], y: batch[1]}) print(f"第{i}次迭代,训练准确率: {train_acc}") print("over 3") writer.add_summary(summarys,i) print("one over") train() writer.add_graph(sess.graph)
额外小提示
如果你的TensorFlow版本比较新,tf.contrib.learn.datasets.mnist可能已经被弃用,可以改用tf.keras.datasets.mnist来加载MNIST数据,不过这不会影响当前问题的解决。
内容的提问来源于stack exchange,提问作者Gopirengaraj
相关产品推荐
相关产品推荐

