梯度下降实现简单线性回归时成本函数上升至无穷大问题求助
问题排查结果
核心原因1:梯度计算多乘系数,变相放大了更新步长
你定义的损失函数已经做了1/(2n)的缩放,对应的梯度本身不需要额外乘系数2,你当前的梯度计算多乘了-2,相当于把实际参数更新步长放大了2倍,大幅提高了发散概率。
核心原因2:输入特征未归一化,学习率设置偏高
你使用的Advertising数据集中第一列TV特征的取值范围在0~300量级,数值偏大,会导致计算得到的m的梯度数值也很大,配合你设置的learning_rate=0.001时,参数更新步长过长,直接越过了损失函数的最低点,反而朝着损失增大的方向移动,最终导致损失飙升至无穷大。
修复方案
你可以选择下面任意一种方案解决发散问题,优先推荐方案1:
- 方案1:先对输入特征做标准化,调整梯度计算逻辑后用原学习率训练
加入特征归一化代码,同时将梯度计算调整为和损失函数匹配的标准形式,避免符号和系数出错:
梯度计算调整为:x = data.iloc[:,0].values # 新增标准化代码,将特征缩放到0均值、单位方差 x = (x - x.mean()) / x.std() y = data.iloc[:,-1].values# 标准均方误差损失对应的梯度公式 D_c = (1/n) * sum(y_pred - y) D_m = (1/n) * sum((y_pred - y) * x) - 方案2:不做归一化和梯度逻辑调整,直接调小学习率到
0.00001即可正常收敛
完整修复后代码示例
import numpy as np import pandas as pd import matplotlib.pyplot as plt data = pd.read_csv('Advertising.csv') data = data.drop(['Unnamed: 0'] ,axis=1) x = data.iloc[:,0].values # 特征标准化 x = (x - x.mean()) / x.std() y = data.iloc[:,-1].values m = 0 c = 0 n = len(y) learning_rate = 0.001 epoch = 1000 def hypothesis(x,m,c): y_pred = m * x + c return y_pred # 定义cost function def cost_function(y, n, m, c): error = y - hypothesis(x, m, c) sq_error = error ** 2 sum_sq_error = sum(sq_error) cost = 1/(2*n) * sum_sq_error return cost # 定义梯度下降函数 def gradient_function(m, c, n, learning_rate, epoch): updated_c = c updated_m = m for i in range(epoch): y_pred = hypothesis(x, updated_m, updated_c) # 调整为标准梯度计算逻辑 D_c = (1/n) * sum(y_pred - y) D_m = (1/n) * sum((y_pred - y) * x) updated_c = updated_c - learning_rate * D_c updated_m = updated_m - learning_rate * D_m if i % 100 == 0: print(f'Epoch {i}, cost: {cost_function(y, n, updated_m, updated_c)}') return updated_m, updated_c if __name__ == '__main__': final_m, final_c = gradient_function(m, c, n, learning_rate, 1000) print(f'最终参数m={final_m}, c={final_c}')
内容的提问来源于stack exchange,提问作者Wasim Pinjari
相关产品推荐
相关产品推荐

