Python实现梯度下降函数:损失函数与权重更新异常排查
梯度下降函数实现错误排查
错误根因
两处核心逻辑错误直接对应两条报错:
- 损失函数实现错误:你写的损失公式既不是逻辑回归要求的交叉熵损失,计算全程没有用到sigmoid输出的预测值
h,属于公式套用错误,自然输出不对。 - 权重更新逻辑错误:误差项误用了线性输出
z和标签y的差值,逻辑回归的梯度计算需要用sigmoid激活后的预测值h和标签y的差值作为误差项,误差项错了梯度计算结果完全不对,theta自然无法收敛到正确值。
你看到的cost持续下降是假象:错误的损失计算刚好和真实损失的大趋势一致,数值会持续走低,但根本不是练习要求统计的损失值,永远达不到收敛阈值。
修正点说明
- 把误差项从
z - y改成h - y,匹配逻辑回归的梯度计算要求 - 替换交叉熵损失公式为逻辑回归标准形式:
J = (-1/m) * np.sum(y * np.log(h) + (1-y)*np.log(1-h)) - 注意梯度计算的维度匹配:
x.T和误差项点乘后除以样本数m得到平均梯度,更新theta时直接乘学习率alpha即可,不要重复除以m - 取样本数m推荐用
x.shape[0],比len(x)对numpy矩阵的兼容性更好
修正后可运行代码
import numpy as np def sigmoid(z): return 1 / (1 + np.exp(-z)) def gradientDescent(x, y, theta, alpha, num_iters): """ Input: x: 特征矩阵,维度(m,n+1) y: 对应标签,维度(m,1) theta: 权重向量,维度(n+1,1) alpha: 学习率 num_iters: 训练迭代次数 Output: J: 最终损失值 theta: 训练完成的权重向量 """ m = x.shape[0] J = 0 for i in range(num_iters): z = np.dot(x, theta) h = sigmoid(z) # 计算预测误差 loss = h - y # 计算交叉熵损失 J = (-1/m) * np.sum(y * np.log(h) + (1 - y) * np.log(1 - h)) print(f"Iteration {i} | Cost: {J:.6f}") # 计算平均梯度 gradient = np.dot(x.T, loss) / m # 更新权重 theta = theta - alpha * gradient J = float(J) return J, theta
额外提示
如果跑的时候出现log计算的nan警告,可以在算log的时候给h加一个极小值epsilon,比如np.log(h + 1e-8)、np.log(1 - h + 1e-8),避免预测值完全为0或1时对数计算无意义,练习场景下不加也能跑通。
内容的提问来源于stack exchange,提问作者Frederik
相关产品推荐
相关产品推荐

