基于梯度下降的多项式近似:高次权重爆炸问题优化问询
高次多项式反向传播权重爆炸问题的优化方案
你的核心问题是高次幂项x^n数值随次数急剧膨胀,导致SGD更新时梯度项过大,权重被推到极端值引发溢出或发散。以下是几个直接有效的优化方案:
1. 用正交多项式基替代普通幂次项
普通幂次项x^n在x>1时会指数级增长,而正交多项式(如切比雪夫、勒让德多项式)在标准化区间内数值始终维持在[-1,1]左右,从根源上解决特征值爆炸的问题。
修改特征生成逻辑,以切比雪夫多项式为例:
import numpy as np import matplotlib.pyplot as plt from numpy.polynomial import chebyshev as cheb x = np.array([1,2,3,4,5]) y = np.array([5,15,25,45,65]) grade = 10 # 测试高次场景 def interpolate_backprop(x,y,grade,alfa=1e-3, steps = 50000): # 先把x缩放到切比雪夫多项式的标准区间[-1,1] x_scaled = 2 * (x - x.min()) / (x.max() - x.min()) - 1 # 生成0到grade-1阶的切比雪夫特征矩阵 inputs = cheb.chebvander(x_scaled, grade-1).astype(np.double) weights = np.random.normal(size=grade) # 用正态分布初始化权重更稳定 for n in range(steps): # 批量梯度下降,用所有样本的平均梯度 outputs = np.dot(inputs, weights) error = outputs - y gradient = np.dot(inputs.T, error) / len(x) weights -= alfa * gradient if n % 5000 == 0: mse = np.mean(error**2) print(f"Step {n}, MSE = {mse:.4f}") return weights, x.min(), x.max() weights, x_min, x_max = interpolate_backprop(x,y,grade) # 测试拟合效果 x_scaled = 2 * (x - x_min) / (x_max - x_min) - 1 inputs = cheb.chebvander(x_scaled, grade-1) for xi, pred, true in zip(x, np.dot(inputs, weights), y): print(f"x={xi}: 预测值={pred:.2f}, 真实值={true}") # 绘制拟合曲线 xx = np.arange(x[0]-1, x[-1]+1, 0.1) xx_scaled = 2 * (xx - x_min) / (x_max - x_min) - 1 xx_inputs = cheb.chebvander(xx_scaled, grade-1) yy = np.dot(xx_inputs, weights) plt.scatter(x, y, label='原始数据') plt.plot(xx, yy, label=f'{grade}次切比雪夫多项式拟合') plt.legend() plt.show()
2. 输入特征标准化
如果坚持用普通幂次项,必须对每个特征维度(即每个n次项)做标准化,消除不同次项之间的数值差异:
def interpolate_backprop(x,y,grade,alfa=1e-3, steps = 50000): inputs = np.array([[xi**n for n in range(grade)] for xi in x], dtype=np.double) # 对每一列(每个幂次项)做Z-score标准化 mean = np.mean(inputs, axis=0) std = np.std(inputs, axis=0) std[std == 0] = 1e-8 # 避免除以0 inputs = (inputs - mean) / std weights = np.random.normal(size=grade) for n in range(steps): outputs = np.dot(inputs, weights) error = outputs - y gradient = np.dot(inputs.T, error) / len(x) weights -= alfa * gradient if n % 5000 == 0: mse = np.mean(error**2) print(f"Step {n}, MSE = {mse:.4f}") return weights, mean, std # 预测时要对新输入做同样的标准化 weights, mean, std = interpolate_backprop(x,y,grade) xx_inputs = np.array([[xi**n for n in range(grade)] for xi in xx], dtype=np.double) xx_inputs = (xx_inputs - mean) / std yy = np.dot(xx_inputs, weights)
3. 添加权重正则化
在权重更新时加入L2正则项,限制权重的绝对值大小,防止过度膨胀:
lambda_reg = 1e-4 # 正则系数,根据情况调整 weights -= alfa * (gradient + lambda_reg * weights)
关键注意事项
- 优先用正交多项式方案,这是解决高次多项式拟合数值不稳定最有效的方法;
- 避免用纯SGD,改用批量或小批量梯度下降,梯度更稳定;
- 不要随意修改反向传播的梯度公式(你之前去掉input项的做法是错误的,破坏了导数的正确性)。
内容的提问来源于stack exchange,提问作者Smer5
相关产品推荐
相关产品推荐

