TensorFlow神经网络实现房价线性回归:损失居高不下求排查
问题排查与修复方案
嘿,我帮你找到了几个核心问题,这就是你训练时损失一直处于10的幂级且无法下降的原因,咱们一步步来解决:
1. 最致命的错误:每轮训练都重置模型参数
你把sess.run(tf.global_variables_initializer())放在了训练循环里面!这意味着每跑一次迭代,就会把所有权重和偏置重新变回初始的随机值,模型根本没机会学习到数据里的规律,损失自然不会有任何有效下降(只会随机波动)。
赶紧把初始化操作移到循环外面,只在会话启动时执行一次:
with tf.Session() as sess: # 只初始化一次参数!这步是核心修复点 sess.run(tf.global_variables_initializer()) for i in range(0,1000): _, l = sess.run([optimizer, loss], feed_dict={x: X_tr, y: y_tr}) # 建议每隔几轮打印一次,避免刷屏 if i % 10 == 0: print(f"第{i}轮训练,损失值:{l}")
2. 数据未做归一化/标准化,梯度根本没法收敛
房价数据集的特征数值跨度太大了——比如房屋面积可能是几百,房价却是几十万甚至上百万,这种情况下梯度下降算法很难找到最优解,直接导致损失值飙到极高的数量级。
必须对输入特征做标准化处理,用sklearn的StandardScaler就很方便:
from sklearn.preprocessing import StandardScaler # 对特征做标准化 scaler = StandardScaler() X_tr = scaler.fit_transform(X_train) X_te = scaler.transform(X_test) # 如果房价本身数值太大,也可以考虑做对数转换或者标准化,训练完再逆转换回去
3. 学习率设置过高,模型直接震荡发散
你用的梯度下降优化器学习率是0.1,这个值在未归一化的数据上太大了,就算做了归一化,也建议先试试更小的值(比如0.01、0.001)。另外,更推荐用Adam优化器,它会自动调整学习率,比普通梯度下降更适合回归任务:
# 替换原来的优化器 optimizer = tf.train.AdamOptimizer(0.001).minimize(loss)
几个额外的小建议
- 加入验证监控:每轮训练后可以在测试集上计算损失,看看模型是不是过拟合了
- 增加训练轮数:1000轮可能不够,尤其是用梯度下降的时候,可以加到5000甚至10000轮
- 优化日志打印:别每轮都打印损失,每隔几十轮打一次,更容易观察趋势
修正后的完整代码示例
import tensorflow as tf from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler import numpy as np import pandas as pd # 假设df2是你处理好的特征数据集,y是目标房价 # 第一步:数据标准化 scaler = StandardScaler() scaled_features = scaler.fit_transform(df2) X_train, X_test, y_train, y_test = train_test_split(scaled_features, y, test_size=0.2) X_tr = np.array(X_train) y_tr = np.array(y_train) X_te = np.array(X_test) y_te = np.array(y_test) def get_weights(shape,name): s = tf.truncated_normal(shape) w = tf.Variable(s,name=name) return w def get_bias(number,name): s = tf.truncated_normal([number]) b = tf.Variable(s,name=name) return b x = tf.placeholder(tf.float32,name="input") w = get_weights([34,100],'layer1') b = get_bias(100,'bias1') op = tf.matmul(x,w)+b a = tf.nn.relu(op) fl = get_weights([100,1],'output') b2 = get_bias(1,'bias2') op2 = tf.matmul(a,fl)+b2 y = tf.placeholder(tf.float32,name='target') loss = tf.losses.mean_squared_error(y,op2) # 改用Adam优化器,学习率设为0.001 optimizer = tf.train.AdamOptimizer(0.001).minimize(loss) with tf.Session() as sess: # 仅初始化一次参数 sess.run(tf.global_variables_initializer()) epochs = 5000 for i in range(epochs): _, train_loss = sess.run([optimizer, loss], feed_dict={x: X_tr, y: y_tr}) # 每50轮打印一次训练和测试损失 if i % 50 == 0: test_loss = sess.run(loss, feed_dict={x: X_te, y: y_te}) print(f"Epoch {i:4d} | 训练损失: {train_loss:.4f} | 测试损失: {test_loss:.4f}")
按照上面的修改,你应该能看到损失值逐步下降到合理的范围了。
内容的提问来源于stack exchange,提问作者Rahul Deora
相关产品推荐
相关产品推荐

