Tensorflow实现单变量简单线性回归输出系数接近0问题求解
问题根因
线性回归的损失函数是凸函数,不存在局部最小值,你遇到的问题核心是输入特征和标签的数值量级太小,导致梯度更新幅度极低,当前设置的学习率和训练轮次不足以让参数更新到全局最优值。
你给出的x_train、y_train都在1e-3量级,损失对权重的梯度为2 * tf.reduce_mean((y_pred - y_train) * x_train),初始状态下梯度约为1e-6,你设置的学习率为0.1、轮次为100的情况下,权重单轮仅更新约1e-7,100轮累计更新量仅为1e-5,所以输出的权重始终接近0。
解决方案
有两种可行的修复方式:
方式一:调整训练超参数
直接放大学习率、增加训练轮次即可得到和sklearn一致的结果,示例修改如下:
# 原参数替换为以下值即可 learning_rate = 1000 epochs = 2000
修改后运行代码,输出的weight约为0.897,和sklearn的结果完全匹配。
方式二:标准化输入输出(更推荐)
对特征和标签做标准化处理,将数值映射到均值为0、方差为1的区间,训练完成后再反变换得到原始量级的参数,该方法适配性更强,适合后续扩展更复杂的模型:
# 标准化处理 x_mean, x_std = x_train.mean(), x_train.std() y_mean, y_std = y_train.mean(), y_train.std() x_norm = (x_train - x_mean) / x_std y_norm = (y_train - y_mean) / y_std # 用标准化后的数据训练,原超参数即可正常收敛 learning_rate = 0.1 epochs = 100 weight = tf.Variable(0.) bias = tf.Variable(0.) for e in range(epochs): with tf.GradientTape() as tape: y_pred = weight*x_norm + bias loss = tf.reduce_mean(tf.square(y_pred - y_norm)) gradients = tape.gradient(loss, [weight,bias]) weight.assign_sub(gradients[0]*learning_rate) bias.assign_sub(gradients[1]*learning_rate) # 反变换得到原始空间的权重 orig_weight = weight.numpy() * (y_std / x_std) orig_bias = bias.numpy() * y_std + y_mean - orig_weight * x_mean print(orig_weight, 'weight', orig_bias, 'bias')
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

