Python实现梯度下降做数据拟合,线性正常二次模型结果异常如何解决
二次拟合梯度下降异常的原因及解决方法
核心问题原因
你写的偏导数计算逻辑本身是完全正确的,异常是训练配置问题导致的:
- 特征量级不匹配,未做归一化:二次项
X²的取值范围是136,一次项`X`取值范围是16,不同特征的数值量级差异过大,导致各参数的梯度更新步长差距明显,统一学习率下无法同时适配所有参数的更新需求,收敛速度极慢。 - 迭代次数不足:仅设置100次迭代,对于未归一化的特征,完全不足以让参数收敛到全局最优值,运行结束时参数还处于迭代的初始阶段,自然得到异常拟合结果。
- 学习率设置不合理:线性拟合时你使用的学习率为100,切换到二次拟合后直接将学习率降到0.01,步长太小,参数更新的幅度非常有限,进一步加剧了收敛慢的问题。
修复方案
你可以选择两种方式调整:
- 先对所有特征做归一化,把一次项、二次项都缩放到相近的数值区间,再用原迭代次数和学习率训练即可正常收敛
- 不做归一化的话,直接调大迭代次数到10000次以上,同时将学习率调整到0.001左右,也可以得到正常收敛结果
修复后可正常运行的代码示例
import numpy as np import matplotlib.pyplot as plt def gradient(x, y): P0 = P1 = P2 = 0 # 增大迭代次数 iterations = 20000 # 调整到合适的学习率 learning_rate = 0.001 l = len(x) for i in range(iterations): y_predicted = P0 + P1*x + P2*(x**2) err = (1/l) * sum([val**2 for val in (y-y_predicted)]) if err <= 1e-6: break P0d = - (2/l) * sum(y - y_predicted) P1d = - (2/l) * sum(x * (y - y_predicted)) P2d = - (2/l) * sum(x**2 * (y - y_predicted)) P0 = P0 - learning_rate * P0d P1 = P1 - learning_rate * P1d P2 = P2 - learning_rate * P2d return P0, P1, P2 X = np.asarray([1, 2, 4, 5, 6]) Y = np.asarray([2, 4, 6, 8, 10]) P0, P1, P2 = gradient(X, Y) # 收敛后P2会非常接近0,拟合结果和线性模型一致 pred = P0 + P1*X + P2*X**2 plt.figure(1, figsize=(6,4), dpi=120) plt.scatter(x=X, y=Y, c='red', marker='o', label='Data') plt.plot(X, pred, '--m', label='Model') plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者Никита Михалков
相关产品推荐
相关产品推荐

