TensorFlow线性梯度下降优化器NaN值问题求助
嘿,刚看完你的问题和代码,这是梯度下降里非常常见的梯度爆炸问题——因为参数更新的步子太大,直接让损失值飙升到无穷大,最后变成NaN。咱们来一步步解决这个问题:
问题根源分析
- 学习率过高:你设置的学习率
a=0.1对于你的数据来说太大了,尤其是x2的数值范围(1.5~8.3)比x1大很多,梯度更新时参数会直接“飞”出去,导致损失值指数级增长。 - 特征未做归一化:不同特征的数值尺度差异大,会让梯度下降的更新方向不稳定,放大学习率带来的负面影响。
具体解决方案
1. 先降低学习率
把原来的学习率从0.1改成更小的值,比如0.001或者0.0001,先尝试小步更新:
a = 0.0001 # 替换原来的tf.Variable(0.1),其实这里不需要用Variable,直接用数值就行
2. 对特征做标准化处理
将特征缩放到同一尺度(比如Z-score标准化,让均值为0,方差为1),这能大幅提升梯度下降的稳定性。修改你的数据读取部分:
import tensorflow as tf import csv import numpy as np x1_data=[] x2_data=[] y_data=[] with open('Dataset.csv') as csvfile: readCSV=csv.reader(csvfile,delimiter=',') for row in readCSV: x1_data.append(float(row[0])) x2_data.append(float(row[1])) y_data.append(float(row[2])) # 转成numpy数组并做Z-score标准化 x1_data = np.array(x1_data) x2_data = np.array(x2_data) y_data = np.array(y_data) x1_data = (x1_data - np.mean(x1_data)) / np.std(x1_data) x2_data = (x2_data - np.mean(x2_data)) / np.std(x2_data)
3. 可选:改用自适应学习率优化器
如果你觉得调学习率麻烦,可以试试TensorFlow的AdamOptimizer,它会自动根据梯度调整学习率,稳定性比梯度下降好很多:
# 替换原来的GradientDescentOptimizer optimizer = tf.train.AdamOptimizer(learning_rate=0.01) train = optimizer.minimize(cost)
修改后的完整代码示例
import tensorflow as tf import csv import numpy as np x1_data=[] x2_data=[] y_data=[] with open('Dataset.csv') as csvfile: readCSV=csv.reader(csvfile,delimiter=',') for row in readCSV: x1_data.append(float(row[0])) x2_data.append(float(row[1])) y_data.append(float(row[2])) # 特征标准化 x1_data = np.array(x1_data) x2_data = np.array(x2_data) y_data = np.array(y_data) x1_data = (x1_data - np.mean(x1_data)) / np.std(x1_data) x2_data = (x2_data - np.mean(x2_data)) / np.std(x2_data) W1 = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) W2 = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) b = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) hypothesis = W1 * x1_data + W2 * x2_data + b cost = tf.reduce_mean(tf.square(hypothesis - y_data)) # 改用Adam优化器,学习率设置为0.01 optimizer = tf.train.AdamOptimizer(learning_rate=0.01) train = optimizer.minimize(cost) init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) for step in range(2001): sess.run(train) if step % 20 == 0: print(step, sess.run(cost), sess.run(W1), sess.run(W2), sess.run(b))
为什么这些方法有效?
- 特征标准化让所有特征处于同一数值尺度,梯度更新时不会因为某个特征数值大就导致参数突变;
- 降低学习率或者用自适应优化器,能避免参数更新的步子太大,防止损失值发散到无穷大;
你可以先试试上面的代码,应该就能解决NaN的问题啦!
内容的提问来源于stack exchange,提问作者Thanatos
相关产品推荐
相关产品推荐

