多元回归梯度下降实现触发OverflowError整数溢出报错问题
报错根因定位
- 直接触发溢出报错的核心原因:初始theta数组用整型列表初始化,生成的是int64类型的numpy数组。由于原始输入特征取值范围为1-100,搭配0.05的偏高学习率,梯度更新过程中theta的数值会快速指数级增长,很快超过int64类型的C层存储上限,numpy尝试将超大Python整数转回C层整型存储时直接抛出溢出错误。
- 间接导致发散溢出的设计缺陷:
- 未对输入特征做标准化处理,偏置项(全1)和成绩类特征(1-100)的数值量级差异过大,梯度更新过程会出现震荡,无法稳定收敛。
- 成本函数、梯度计算中硬编码了样本数47,逻辑鲁棒性差,样本量变化时会直接导致计算偏差。
- 逐列循环更新theta的逻辑存在隐式类型转换,会进一步加速数值膨胀的速度。
可落地解决方案
- 修正theta初始化的类型:将原来的整型初始化改为64位浮点类型,利用float64的大数值存储范围规避整数溢出问题,替换初始化代码为
theta = np.zeros(len(X.columns), dtype=np.float64)。 - 增加特征标准化环节:对非偏置项的成绩类特征做Z-score标准化,缩放到均值为0、标准差为1的范围,消除不同特征的量级差异,让梯度下降的更新过程稳定收敛。
- 调低学习率:配合特征缩放将学习率从0.05调整为0.01,避免步长过大导致的参数震荡发散。
- 替换硬编码的样本数:把代码中固定写死的47替换为实际样本数
len(y),匹配任意规模的数据集。 - 优化计算逻辑:将逐列循环更新theta的逻辑改为向量化矩阵计算,减少循环带来的隐式类型转换和精度误差。
修正后可直接运行的代码
import numpy as np import pandas as pd # 数据拆分 X = df.drop(columns="Math") y = df.iloc[:, 4] # 浮点类型初始化theta,避免整数溢出 theta = np.zeros(len(X.columns), dtype=np.float64) # 对非偏置列做Z-score标准化 if X.iloc[:, 0].nunique() == 1: # 判断第一列为全1的偏置列 X.iloc[:, 1:] = (X.iloc[:, 1:] - X.iloc[:, 1:].mean()) / X.iloc[:, 1:].std() def hypothesis(theta, X): # 矩阵乘法实现假设函数,避免广播带来的维度歧义 return X.values @ theta def computeCost(X, y, theta): y_pred = hypothesis(theta, X) m = len(y) # 动态获取样本数,替换硬编码的47 return np.sum((y_pred - y)**2) / (2 * m) def gradientDescent(X, y, theta, alpha, iteration_num): J_history = [] m = len(y) for _ in range(iteration_num): y_pred = hypothesis(theta, X) error = y_pred - y # 向量化更新所有参数,无需逐列循环 theta = theta - alpha * (X.values.T @ error) / m current_cost = computeCost(X, y, theta) J_history.append(current_cost) return J_history, current_cost, theta # 用适配特征缩放的学习率运行梯度下降 J, final_cost, theta = gradientDescent(X, y, theta, 0.01, 10000)
内容的提问来源于stack exchange,提问作者Yedija Messa
相关产品推荐
相关产品推荐

