实现线性回归梯度下降时参数发散为nan的问题排查
故障原因及修复方案
核心问题1:梯度下降逻辑缺失参数c的更新
当前gradient_decent方法仅对参数m做了迭代更新,全程未修改参数c的取值,模型永远用c=0拟合,不可能收敛到真实值c=4,同时会持续放大参数m的更新误差。
核心问题2:学习率设置过大且梯度未做归一化
训练样本x取值范围是-20~19,当前梯度计算是直接对所有样本的梯度求和,没有除以样本总数做平均,初始迭代时梯度的量级可达数千,乘以0.01的学习率后单次更新步长超过10,直接导致参数m震荡发散,数值溢出后变为nan。
次要隐患:self.X.index(x)写法存在风险
如果输入的X存在重复值,index()会始终返回第一个匹配项的下标,导致y的取值匹配错误,建议直接按下标遍历样本,避免查找索引的开销和错误。
修复后的梯度下降代码示例
def gradient_decent(self): print('Original: ', self.m, self.c) n_samples = len(self.X) nm = 0 prev_m = self.m prev_c = self.c mprecision = 1 cprecision = 1 while nm < self.itter and (mprecision > self.max_precision or cprecision > self.max_precision): prev_m = self.m prev_c = self.c nm += 1 # 计算梯度时除以样本数做平均,降低梯度量级 grad_m = 0 grad_c = 0 for i in range(n_samples): x_i = self.X[i] y_i = self.Y[i] error = self.h(x_i, self.m, self.c) - y_i grad_m += error * x_i grad_c += error grad_m /= n_samples grad_c /= n_samples # 同时更新两个参数 self.m = self.m - self.learning_rate * grad_m self.c = self.c - self.learning_rate * grad_c mprecision = abs(self.m - prev_m) cprecision = abs(self.c - prev_c) return self.m, self.c
调整学习率到0.001左右即可正常收敛到m≈3,c≈4。
内容的提问来源于stack exchange,提问作者Shubham Gupta - TCH
相关产品推荐
相关产品推荐

