You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TensorFlow四层字母识别神经网络精度异常及loss为nan问题求助

问题排查与修复方案

嘿,我帮你揪出了几个核心问题,这就是你的四层神经网络精度只有10%还时不时出现NaN的根源:

1. 网络结构“缩水”+ 验证/测试路径完全错误

你明明定义了hidden_neurons = [inputs, 1024, 512, 256,]打算做四层网络,但实际代码里只实现了两层隐藏层+输出层,完全没用到256神经元的那一层。更要命的是,验证和测试的预测逻辑直接跑偏了:

  • 训练时的路径是:输入→relu1→relu2→logits→softmax
  • 但验证/测试时居然是:输入→relu1→softmax(跳过了relu2之后的所有计算,直接对中间层结果做分类)
    这就相当于你训练了一个模型,测试时却用了另一个完全不同的网络,精度能上去才怪!

2. Loss出现NaN的三大元凶

(1)初始学习率高到离谱

你给GradientDescentOptimizer设了0.3的初始学习率,这值太大了,梯度更新时权重会突变,直接导致softmax交叉熵计算时出现数值溢出(比如logits变得无穷大),最后loss就成了NaN。

(2)权重初始化太“激进”

tf.truncated_normal默认标准差是1.0,对于大尺寸的权重矩阵(比如输入层到1024的矩阵),这种初始化会让神经元的激活值爆炸,经过relu后要么大量神经元饱和,要么引发梯度爆炸,最终搞出NaN。

(3)正则化计算画蛇添足

你已经对交叉熵loss做了tf.reduce_mean,结果加上正则化项后又做了一次tf.reduce_mean,这不仅让正则化项被不必要地缩小,还可能放大数值计算的不稳定性。

3. 修复后的完整代码

我帮你把所有问题都修正了,你可以直接用:

batch_size = 128 
beta = 0.01 
inputs = image_size*image_size 
hidden_neurons = [inputs, 1024, 512, 256,] 

graph = tf.Graph() 
with graph.as_default(): 
    global_step = tf.Variable(0) 

    # 输入数据定义保持不变
    tf_train_dataset = tf.placeholder(tf.float32, shape=(batch_size, image_size * image_size)) 
    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels)) 
    tf_valid_dataset = tf.constant(valid_dataset) 
    tf_test_dataset = tf.constant(test_dataset) 

    # 改用普通变量定义神经元数量,避免不必要的张量计算
    hidden_1_size = 1024
    hidden_2_size = 512
    hidden_3_size = 256  # 补上你原本计划的第三层隐藏层

    # 修正权重初始化:用小标准差0.01,避免激活值过大
    weights_1 = tf.Variable(tf.truncated_normal([image_size * image_size, hidden_1_size], stddev=0.01)) 
    biases_1 = tf.Variable(tf.zeros([hidden_1_size])) 

    weights_2 = tf.Variable(tf.truncated_normal([hidden_1_size, hidden_2_size], stddev=0.01)) 
    biases_2 = tf.Variable(tf.zeros([hidden_2_size])) 

    # 新增第三层隐藏层的权重和偏置
    weights_3 = tf.Variable(tf.truncated_normal([hidden_2_size, hidden_3_size], stddev=0.01)) 
    biases_3 = tf.Variable(tf.zeros([hidden_3_size])) 

    # 输出层权重:从第三层隐藏层映射到分类标签数
    weights_out = tf.Variable(tf.truncated_normal([hidden_3_size, num_labels], stddev=0.01)) 
    biases_out = tf.Variable(tf.zeros([num_labels])) 

    # 完整的四层网络训练路径
    relu_1 = tf.nn.relu(tf.matmul(tf_train_dataset, weights_1) + biases_1) 
    relu_2 = tf.nn.relu(tf.matmul(relu_1, weights_2) + biases_2) 
    relu_3 = tf.nn.relu(tf.matmul(relu_2, weights_3) + biases_3)  # 补上第三层relu激活
    logits = tf.matmul(relu_3, weights_out) + biases_out 

    # 修正loss计算:只做一次均值计算,正则化项直接相加
    cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=tf_train_labels, logits=logits)
    loss = tf.reduce_mean(cross_entropy) + beta * (
        tf.nn.l2_loss(weights_1) + 
        tf.nn.l2_loss(weights_2) + 
        tf.nn.l2_loss(weights_3) + 
        tf.nn.l2_loss(weights_out)
    )

    # 修正学习率:初始值降到0.05,避免梯度爆炸
    learning_rate = tf.train.exponential_decay(0.05, global_step, 100000, 0.7, staircase=True) 
    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step) 

    # 统一预测逻辑:训练/验证/测试走完全相同的网络路径
    def predict(dataset):
        relu_1 = tf.nn.relu(tf.matmul(dataset, weights_1) + biases_1)
        relu_2 = tf.nn.relu(tf.matmul(relu_1, weights_2) + biases_2)
        relu_3 = tf.nn.relu(tf.matmul(relu_2, weights_3) + biases_3)
        logits = tf.matmul(relu_3, weights_out) + biases_out
        return tf.nn.softmax(logits)

    train_prediction = predict(tf_train_dataset)
    valid_prediction = predict(tf_valid_dataset)
    test_prediction = predict(tf_test_dataset)

4. 额外小 tips

  • 可以给隐藏层加上Dropout(tf.nn.dropout),防止四层网络过拟合,比如在每个relu之后加tf.nn.dropout(relu_x, keep_prob=0.5)(注意训练时用0.5,验证/测试时用1.0)。
  • 如果还是出现NaN,试试把初始学习率再调低一点,或者改用AdamOptimizer(自适应学习率,对参数没那么敏感)。
  • 记得对输入图像做归一化(比如像素值除以255,缩到0-1区间),能让训练稳定很多。

内容的提问来源于stack exchange,提问作者Untimely Answers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:05:40