Python 在彩虹图中绘制梯度下降轨迹

 什么叫梯度:https://blog.csdn.net/qq_35781447/article/details/109197005

编程以及操作思路

画彩虹图

画彩虹图需要导入以下三个包

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

彩虹图有三个坐标系,X,Y,Z   也就是说可以简单的描绘成 Z=F(X,Y) 即Z由X, Y通过某种函数关系转换而来

在画彩虹图之前我们需要确定好X Y的范围 例如:

x = np.arange(-15, 15, 0.1)
y = np.arange(-15, 15, 0.1)

然后将其转换成网格数据,不然输送给计算机的就只是间隔很大的零散点,转换成网格数据可以使用以下函数

X, Y = np.meshgrid(x, y)

然后我们来表示Z与X Y的关系,这里需要用网格化的数据,例如

Z = (10*X**2 + Y**2)/2

最后我们便可以通过Axes3D将将彩虹图画出

fig = plt.figure()
ax = Axes3D(fig)
#   画出Z的关于X Y函数图像
figure1 = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap="rainbow")

在彩虹图上画梯度下降(非gif)

好像python可以画出gif图,这里先不做讲解 等后续鄙人用到时再进行更新

梯度下降实际就是类似于求导的概念,每次X,Y减少一丢丢,看看Z变化是啥样子。故这里有两个变量:X Y下降多少----梯度值   Z变化多少---变化值

梯度值我们正常使用  \text { learningrate*f'(x) }来表示 , 所以X Y的梯度值可以表示为\text { learningrate*f'(X) } 和\text { learningrate*f'(Y) }, 因为\text { Z=f(X,Y) }是已知的,所以\text { f'(X) }\text { f'(Y) }便也是已知的(就是对函数求个偏导)。OK,到这里便一目了然了,影响函数梯度的变量就是learningrate了,learningrate越大 X Y下降就越多,收敛就越快。

X Y一直减小,Z也跟着变。当Z变化量越来越小,就说明函数收敛了,到了极小值了(也可能极大值,那就是反向梯度了) 。那么变化量究竟要到多小,我们才能说他收敛了?那是不是得研究变化量的变化量了。其实也不用那么麻烦 就直接自己给个小一点的值吧,比如0.0000000000000001  哈哈哈哈,看个人需要。变化量越小越接近极值。

综上所述 我们要设置两个变量:learningrate 和 变化量的比较值

learningrate = 0.001
com_p = 0.0000001

做个循环,X Y每次下降\text { learningrate*f'(X) } 和\text { learningrate*f'(Y) },去对比下Z的变化值是不是小于com_p。如果小于了 则说明收敛了,就可以退出循环,此时的X Y便最接近极值。

#a=[x,y]
#给x,y一个初始值,即你想从哪个点开始进行梯度下降
def Stochastic_GD(a):
    X_t = a
    while 1:
        X1_list.append(X_t[0])
        X2_list.append(X_t[1])
        Y_list.append(Func(X_t))
        X_t1 = X_t -learningrate*Der_Func(X_t)
        if abs(Func(X_t1) - Func(X_t)) < com_p:
            print("X minimum :", X_t1)
            print("Y=", Func(X_t1))
            X_list.append(X_t1[0])
            Y_list.append(X_t1[1])
            Z_list.append(Func(X_t1))
            break
            pass
        X_t = X_t1
        pass

在上述的循环中 我们建立了三个变量,用了记录 X Y Z每一次变化  这样 我们只需要在彩虹图中将这三个数组对应画上去便可以描绘梯度下降了。

X_list = []
Y_list = []
Z_list = []

利用plot函数把这三个数组画到彩虹图上:

figure2 = ax.plot(X_list, Y_list, Z_list, c='b')

实战

目标:利用python绘制f(\boldsymbol{x})=\left(10 x_{1}^{2}+x_{2}^{2}\right) / 2 通过梯度下降球极小值的过程

代码实现:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
com_p = 0.0000001
learningrate = 0.001
x_1 = np.arange(-15, 15, 0.1)
x_2 = np.arange(-15, 15, 0.1)
X = [x_1, x_2]
X = np.array(X)
print(np.shape(X))
print(X.T[1, :2])
X1_list = []
X2_list = []
Y_list = []

#定义函数
def Func(x):
    return (1/2*np.dot(np.array([10,1]), (x.T**2)))

#定义求导函数 对两个X分别求导
def Der_Func(x):
    return np.array([10*x[0], x[1]])

#梯度下降过程
def Stochastic_GD(x):
    X_t = x
    while 1:
        X1_list.append(X_t[0])
        X2_list.append(X_t[1])
        Y_list.append(Func(X_t))
        X_t1 = X_t -learningrate*Der_Func(X_t)
        if abs(Func(X_t1) - Func(X_t)) < com_p:
            print("X minimum :", X_t1)
            print("Y=", Func(X_t1))
            X1_list.append(X_t1[0])
            X2_list.append(X_t1[1])
            Y_list.append(Func(X_t1))
            break
            pass
        X_t = X_t1
        pass

Stochastic_GD(np.array([-10, 5]))

#####################################################
# 生成网格数据
X_1, X_2 = np.meshgrid(x_1, x_2)
Y = (10*X_1**2 + X_2**2)/2
fig = plt.figure()
ax = Axes3D(fig)
#   画出y的函数图像
figure1 = ax.plot_surface(X_1, X_2, Y, rstride=1, cstride=1, cmap="rainbow")
#   画出梯度下降的过程
figure2 = ax.plot(X1_list, X2_list, Y_list, c='b')

plt.show()

实验结果:

 

 

 

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MacalDan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值