探秘机器学习核心逻辑:梯度下降的迭代过程 (图文详解)

一  需求解函数

f() 和 g()函数分别为求y值求导数的函数。

目的:求该函数的最小值:

        y = (x - 3.5)^ 2 - 4.5 * x + 10

 代码:

import numpy as np
import matplotlib.pyplot as plt 

f = lambda x : (x - 3.5) ** 2 - 4.5 * x + 10
g = lambda x : 2 * (x - 3.5) - 4.5

x = np.linspace(0, 11.5, 100)
y = f(x)

plt.plot(x, y) 

二 随机初始化一个值

在 0 - 12 中随机取一个值:10

k = np.random.randint(0, 12)
print('随机取到的值k:', k)  # 10 

三 查看此时的斜率

查看此时的切线方程:

k = 10
g(x) = 8.5   # 斜率
f(x) = 7.5   # y值
# 该点的切线方程:y = 8.5 * x - 77.5

plt.plot(x, y) 
plt.scatter(k, f(k), color = 'red', s = 30)

# 生成x的范围
x_values = np.linspace(8, 11.5, 100)

# 计算对应的y值
y_values = 8.5 * x_values - 77.5
# 绘制直线
plt.plot(x_values, y_values, color='blue', label='Line')

四 根据斜率和学习率确定下一个点

设置学习率为0.2,与初始点的梯度反向进行下降,如果在上一个点斜率为正,说明需要x需要向左移动才能接近最小值:next_k = k - 学习率*斜率

学习率可以改,设置值比较大移动比较快,设置比较小移动比较慢。

求到的第一个K:8.3

learing_ratio = 0.2
next_k = k - learing_ratio*g(k) 

plt.plot(x, y) 
plt.scatter(k, f(k), color = 'red', s = 30)
plt.scatter(next_k, f(next_k), color = 'red', s = 30) 

print(next_k, f(next_k))
# 8.3 -4.309999999999995

五 根据该逻辑继续计算下一个值

用上一次计算的 8.2 计算一个值:next_k2 = next_k - learing_ratio*g(next_k) 

求到的第二个K:7.28

learing_ratio = 0.2
next_k2 = next_k - learing_ratio*g(next_k) 

plt.plot(x, y) 
plt.scatter(k, f(k), color = 'red', s = 30)
plt.scatter(next_k, f(next_k), color = 'red', s = 30)
plt.scatter(next_k2, f(next_k2), color = 'red', s = 30)
print(next_k2, f(next_k2))
# 7.28 -8.471599999999995

六 同时查看两次迭代过程中 y值的变化率

查看两次迭代过程中 y值的变化率分别为:-11.559999999999995  -4.1616

plt.plot(x, y) 
plt.scatter([k, next_k, next_k2], [f(k), f(next_k), f(next_k2)], 
            color = 'red', s = 30)

# 绘制直线
plt.plot(x, [f(k)] * len(x), label='y=5', color='blue', linestyle='--')
plt.plot(x, [f(next_k)] * len(x), label='y=5', color='green', linestyle='--')
plt.plot(x, [f(next_k2)] * len(x), label='y=5', color='red', linestyle='--')

print(f(next_k) - f(k), f(next_k2) - f(next_k))  # -11.5599999999-4.1616

七 设置循环,求最接近的目标值

注意:截止条件设置的变化率是x 的变化率,就是当 斜率的变化值足够小 的时候截止,其实也是y值的变化率乘学习率后的变化值 !!

k = k - learing_ratio*g(k)

设置截止循环条件:precision = 0.0001

learing_ratio = 0.2
last_k = k + 0.1
# 精确度
precision = 0.0001

k_ = [k]
count = 0  # 记录迭代次数

while True:
    if np.abs(k - last_k) < precision:
        break
    last_k = k
    count += 1
    k = k - learing_ratio*g(k)  # 迭代
    k_.append(k)
    print(f'-> 迭代次数cnt:{count:2},更新后的x:{k:0.7f}, 实时的y:{f(k):0.7f}')

print(f'梯度下降的次数:{count}')
plt.plot(x, y) 
print('最后的k值:', k)  # 5.75009323204022

# 散点图,转换为array数组可以用f(x)直接求列表的y值
k_ = np.array(k_)
plt.scatter(k_, f(k_), color = 'red', s = 30)

 

PS:最后的列表直接求y值是先转换为了 np.array数组!!!

实际值:5.75

循环21次,最后求到的k值:5.75009323204022

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值