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

TensorFlow中损失值始终不变的问题排查求助

问题:TensorFlow神经网络训练时损失值始终保持不变

我正在尝试使用TensorFlow搭建神经网络以更好地学习该库,但我的损失值始终保持不变。以下是我的代码:

import tensorflow as tf
import numpy as np
import pandas as pd
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
all_data = pd.read_csv('/projects/data/testfile.csv')
all_data = all_data.values
size_layer1 = 1
size_layer2 = 10
size_layer3 = 1
labels = all_data[:, 9]; labels = tf.convert_to_tensor(labels, np.float32); labels = tf.reshape(labels, [985, 1])
data = all_data[:, 6]; data = tf.convert_to_tensor(data, np.float32)
theta1 = tf.Variable(tf.zeros([size_layer2, size_layer1])); theta1 = tf.reshape(theta1, [10, 1])
theta2 = tf.Variable(tf.zeros([size_layer3, size_layer2])); theta2 = tf.reshape(theta2, [1, 10])
a1 = data; a1 = tf.reshape(a1, [1, 985])
z2 = tf.matmul(theta1, a1)
a2 = tf.nn.relu(z2)
z3 = tf.matmul(theta2, a2)
a3 = tf.nn.sigmoid(z3)
h = tf.transpose(a3)
cost = tf.losses.mean_squared_error(labels, h)
train = tf.train.GradientDescentOptimizer(0.01).minimize(cost)
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for i in range(10):
        sess.run(train)
        print(sess.run(cost))

我的数据集为985×12的矩阵,但多数列是文本类型,因此我提取了两列数据。我清楚这种1:10:1节点结构搭配实数值标签的神经网络设计并不合理,但我并非要优化网络,只是学习TensorFlow语法。我也知道应该进行特征缩放/均值归一化,但同样并非要完美优化网络。

我的输出结果为:

73948990000.0
73948990000.0
73948990000.0
73948990000.0
73948990000.0
73948990000.0
73948990000.0
73948990000.0
73948990000.0
73948990000.0

我已经尝试了多种方法:最初使用普通交叉熵作为损失函数,但由于数据是实数值,我改为均方误差(mean squared error);也尝试更换优化器,但均无效果。请问问题出在网络架构设计不佳,还是其他原因?


问题分析与解决方案

咱们先从代码细节里找问题,你遇到的损失不更新,核心原因不是架构简单,而是初始化、维度匹配和激活函数选择这几个基础错误,和架构关系不大:

1. 全0权重初始化导致梯度消失

你把theta1和theta2都初始化成了全0张量:

theta1 = tf.Variable(tf.zeros([size_layer2, size_layer1]))
theta2 = tf.Variable(tf.zeros([size_layer3, size_layer2]))

当所有权重都是0时,第一层的所有神经元输出完全相同,反向传播时所有权重的梯度也完全一致,权重永远不会产生差异,网络根本无法学习——这是神经网络初始化的经典坑!

解决方法:用随机初始化替代全0,比如正态分布初始化:

theta1 = tf.Variable(tf.random.normal([size_layer2, size_layer1], mean=0, stddev=0.1))
theta2 = tf.Variable(tf.random.normal([size_layer3, size_layer2], mean=0, stddev=0.1))

2. 输入与权重的矩阵乘法维度逻辑混乱

你的输入维度处理不符合常规训练逻辑:

  • a1被reshape成[1, 985](1个特征,985个样本),但通常我们会把样本放在第一维度([样本数, 特征数]),这样计算和梯度传播更直观,也不容易出错。
  • 后续的矩阵乘法虽然维度能运算,但最终输出的转置操作容易掩盖逻辑问题,导致梯度传播异常。

调整输入与权重维度:

# 把data改成[985, 1](985个样本,每个样本1个特征)
data = tf.reshape(data, [985, 1])
# theta1改成[1, 10](输入特征数1,输出神经元数10)
theta1 = tf.Variable(tf.random.normal([size_layer1, size_layer2], mean=0, stddev=0.1))
# z2计算为[985,1] × [1,10] = [985,10],符合样本在前的逻辑
z2 = tf.matmul(data, theta1)
a2 = tf.nn.relu(z2)
# theta2改成[10,1](输入10个神经元,输出1个)
theta2 = tf.Variable(tf.random.normal([size_layer2, size_layer3], mean=0, stddev=0.1))
z3 = tf.matmul(a2, theta2)
# 此时a3直接是[985,1],和labels维度完全匹配,不需要转置

3. Sigmoid激活函数不适合回归任务输出层

你的标签是实数值,但Sigmoid的输出范围固定在[0,1],如果你的标签值远大于1或者小于0,模型根本无法拟合,损失自然不会变化。对于回归任务,输出层应该用线性输出:

# 去掉sigmoid,直接用线性输出
a3 = z3

4. 学习率太小且训练轮数不足

你用了0.01的学习率,而且只训练10轮,就算前面的问题都解决了,这么少的轮数也很难看到损失变化。可以先把学习率调到0.1,训练轮数增加到100或者更多,观察损失是否下降。

调整后的完整代码示例

import tensorflow as tf
import numpy as np
import pandas as pd
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

all_data = pd.read_csv('/projects/data/testfile.csv')
all_data = all_data.values

size_layer1 = 1
size_layer2 = 10
size_layer3 = 1

# 处理标签和输入数据
labels = all_data[:, 9]
labels = tf.convert_to_tensor(labels, dtype=tf.float32)
labels = tf.reshape(labels, [985, 1])

data = all_data[:, 6]
data = tf.convert_to_tensor(data, dtype=tf.float32)
data = tf.reshape(data, [985, 1])  # 样本数在前,特征数在后

# 随机初始化权重,避免全0
theta1 = tf.Variable(tf.random.normal([size_layer1, size_layer2], mean=0, stddev=0.1))
theta2 = tf.Variable(tf.random.normal([size_layer2, size_layer3], mean=0, stddev=0.1))

# 前向传播
z2 = tf.matmul(data, theta1)
a2 = tf.nn.relu(z2)
z3 = tf.matmul(a2, theta2)
a3 = z3  # 回归任务用线性输出

# 计算损失和优化器
cost = tf.losses.mean_squared_error(labels, a3)
train = tf.train.GradientDescentOptimizer(0.1).minimize(cost)  # 增大学习率
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    for i in range(100):  # 增加训练轮数
        sess.run(train)
        if (i+1) % 10 == 0:  # 每10轮打印一次损失
            print(f"第{i+1}轮损失: {sess.run(cost)}")

总结

你的核心问题不是架构简单,而是权重全0初始化、维度匹配错误、激活函数选择不当这几个基础问题。调整后应该能看到损失值开始下降,虽然因为数据没做归一化可能下降得不够平滑,但至少能验证TensorFlow的训练逻辑是正常的。

内容的提问来源于stack exchange,提问作者Ronan Venkat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:11:03