04 基于sklearn的机械学习-梯度下降(上)

发布于:2025-08-02 ⋅ 阅读:(5) ⋅ 点赞:(0)

梯度下降

一 、为什么要用到梯度下降?

正规方程的缺陷:

  1. 非凸函数问题:损失函数非凸时,导数为0会得到多个极值点(非唯一解)

  2. 计算效率低:逆矩阵运算时间复杂度 O(n3),特征量翻倍时计算时间增为8倍(16特征需512秒)。

 

结论:梯度下降是高效求解大规模、非凸问题的通用优化算法。

二、梯度下降核心思想

目标:以最快的速度找到损失函数 loss的最小值点(最优参数 W)。

原理类比

人在山地走向谷底,每一步沿当前最陡峭下坡方向行走。

步骤 1:判断 “下坡最陡的方向”

你低头观察脚下的地面:

  • 左边地面微微向下倾斜,坡度较缓;

  • 正前方地面明显向下倾斜,坡度最陡;

  • 右边地面甚至有点向上倾斜(上坡)。

这里的 “坡度” 就是梯度—— 它不仅告诉你 “哪个方向是下坡”,还告诉你 “哪个方向下坡最陡”(梯度的方向),以及 “陡到什么程度”(梯度的大小)。

步骤 2:沿最陡方向走一小步

既然正前方下坡最陡,你就朝着正前方走一步(步长不能太大,否则可能踩空或错过转弯)。这一步对应参数更新

  • 方向:沿 “最陡下坡方向”(负梯度方向,因为梯度本身是 “上坡最陡” 的方向);

  • 步长:对应 “学习率”(不能太大,否则可能直接冲到山的另一侧;也不能太小,否则走得太慢)。

步骤 3:重复调整方向,逐步逼近山脚

走完一步后,你站在新的位置,再次观察脚下的坡度(重新计算梯度),发现此时 “左前方” 变成了最陡的下坡方向。于是你调整方向,沿左前方再走一步…… 这个过程不断重复:每次都根据当前位置的坡度调整方向,走一小步,直到走到坡度几乎为 0 的平地(山脚)

  • 梯度 g是损失函数 loss对参数 W 的偏导数。

    • 如果 g < 0, w 就变大 ; 如果g > 0 , w 就变小(目标左边是斜率为负右边为正 )

  • 沿梯度反方向更新参数:W=W−α⋅g(α 为学习率)。

  • 然后判断是否收敛(loss变化很小就收敛),如果收敛就跳出迭代,如果没收敛就再次更新参数 W...

三、单参数(w)梯度下降实现

1. 更新公式

2. 参数α更新逻辑
    位置 梯度 gg 更新方向 操作
    最小值左侧 g<0 w 增大 w=w−(负值)→右移 
    最小值右侧 g>0 w 减小 w=w−(正值)→左移 

    示例流程(初始 w=0.2,α=0.01):

    1. 计算 : 假设w=0.2时g=0.24 → w_new=0.2−0.01×0.24=0.1976

    2. 迭代更新直至收敛(g最小)。

    # 定义总损失
    def loss(w):
        return 10*(w**2)-15.9*w+6.5
    
    # 定义梯度
    def g(w):
        return 20*w-15.9
    
    # 定义模型
    def model(x,w):
        return x*w
    
    # 绘制模型
    def draw_line(w):
        pt_x = np.linspace(0,5,100)
        pt_y = model(pt_x,w)
        plt.plot(pt_x,pt_y)
    
    #随机初始化w
    w =10
    
    # 迭代
    for i in range(100):
        print('w:',w,'loss:',loss(w))
        # 学习率
        lr = 1/(i+100)
        # 更新w
        w = w-lr*g(w)
        
    x=np.array([4.2,4.2, 2.7, 0.8, 3.7, 1.7, 3.2])
    y=np.array([3.8,2.7, 2.4, 1.,  2.8, 0.9, 2.9])   
    plt.plot(x,y,'o')
    draw_line(w)
    plt.show()

    四、学习率(α)

    学习率α是控制参数更新的 “步长”,是影响收敛的核心超参数:

    • 过小:收敛缓慢,需大量迭代;
    • 过大:可能跳过最优解,导致损失震荡甚至发散;

    一般我们把它设置为0.1,0.01,0.001甚至更小。一般情况下学习率在迭代过程中是不变的,但是也可以设置为动态调整,即随着迭代次数逐渐变小,越接近目标W '步子'迈的更小,以更精准地找到W。

    五、多参数(如 w0,w1)梯度下降实现

    假设损失函数是有两个w1,w2特征的椎体

    1. 初始化:随机生成正态分布参数 W(如 w0,w1)。

    2. 计算梯度g:求当前 loss 的梯度 g

    3. 更新参数:W=W−α⋅g

    4. 收敛判断

      • loss变化量 < 阈值

      • 或达到预设迭代次数(如1000次)。

    5. 终止:满足条件则输出 W;否则返回步骤2。

    假设loss = (100w1 + 200w2 +1000)**2

    import numpy as np
    # 假设总损失
    def loss(w1,w2):
        return (100*w1 + 200*w2 +1000)**2
    ​
    # 梯度
    # 以w1为参数的梯度
    def g1(w1,w2):
        return 2*(100*w1 + 200*w2 +1000)*100
    ​
    # 以w2为参数的梯度
    def g2(w1,w2):
        return 2*(100*w1 + 200*w2 +1000)*200
    ​
    # 初始化w1,w2
    w1 = 10
    w2 = 10
    for i in range(50):
        print('w1:',w1,'w2:',w2,'loss:',loss(w1,w2))
        w1,w2 = w1-0.001*g1(w1,w2), w2-0.01*g2(w1,w2)
    ​


    网站公告

    今日签到

    点亮在社区的每一天
    去签到